From 174c20bd8f1f3d6a92004d6e7a701413021e43ef Mon Sep 17 00:00:00 2001 From: Kilian Hofmann Date: Tue, 27 Sep 2022 15:34:46 +0200 Subject: [PATCH] Update XPLM for ARM64 --- TODO.md | 2 - XPSDK/CHeaders/Widgets/XPStandardWidgets.h | 518 ++--- XPSDK/CHeaders/Widgets/XPUIGraphics.h | 443 ++-- XPSDK/CHeaders/Widgets/XPWidgetDefs.h | 675 +++--- XPSDK/CHeaders/Widgets/XPWidgetUtils.h | 228 ++- XPSDK/CHeaders/Widgets/XPWidgets.h | 593 +++--- XPSDK/CHeaders/Wrappers/XPCBroadcaster.cpp | 75 +- XPSDK/CHeaders/Wrappers/XPCBroadcaster.h | 35 +- XPSDK/CHeaders/Wrappers/XPCDisplay.cpp | 145 +- XPSDK/CHeaders/Wrappers/XPCDisplay.h | 101 +- XPSDK/CHeaders/Wrappers/XPCListener.cpp | 30 +- XPSDK/CHeaders/Wrappers/XPCListener.h | 36 +- XPSDK/CHeaders/Wrappers/XPCProcessing.cpp | 74 +- XPSDK/CHeaders/Wrappers/XPCProcessing.h | 40 +- XPSDK/CHeaders/Wrappers/XPCWidget.cpp | 186 +- XPSDK/CHeaders/Wrappers/XPCWidget.h | 115 +- .../Wrappers/XPCWidgetAttachments.cpp | 416 ++-- .../CHeaders/Wrappers/XPCWidgetAttachments.h | 190 +- XPSDK/CHeaders/XPLM/XPLMCamera.h | 152 +- XPSDK/CHeaders/XPLM/XPLMDataAccess.h | 726 ++++--- XPSDK/CHeaders/XPLM/XPLMDefs.h | 510 +++-- XPSDK/CHeaders/XPLM/XPLMDisplay.h | 1813 ++++++++++++---- XPSDK/CHeaders/XPLM/XPLMGraphics.h | 472 +++-- XPSDK/CHeaders/XPLM/XPLMInstance.h | 136 ++ XPSDK/CHeaders/XPLM/XPLMMap.h | 628 ++++++ XPSDK/CHeaders/XPLM/XPLMMenus.h | 248 ++- XPSDK/CHeaders/XPLM/XPLMNavigation.h | 319 ++- XPSDK/CHeaders/XPLM/XPLMPlanes.h | 256 ++- XPSDK/CHeaders/XPLM/XPLMPlugin.h | 315 ++- XPSDK/CHeaders/XPLM/XPLMProcessing.h | 262 +-- XPSDK/CHeaders/XPLM/XPLMScenery.h | 424 ++-- XPSDK/CHeaders/XPLM/XPLMUtilities.h | 1451 +++++++------ XPSDK/Delphi/Widgets/XPStandardWidgets.pas | 355 ++-- XPSDK/Delphi/Widgets/XPUIGraphics.pas | 352 ++-- XPSDK/Delphi/Widgets/XPWidgetDefs.pas | 506 +++-- XPSDK/Delphi/Widgets/XPWidgetUtils.pas | 210 +- XPSDK/Delphi/Widgets/XPWidgets.pas | 704 +++---- XPSDK/Delphi/XPLM/XPLMCamera.pas | 173 +- XPSDK/Delphi/XPLM/XPLMDataAccess.pas | 800 ++++---- XPSDK/Delphi/XPLM/XPLMDefs.pas | 172 +- XPSDK/Delphi/XPLM/XPLMDisplay.pas | 1823 ++++++++++++----- XPSDK/Delphi/XPLM/XPLMGraphics.pas | 525 +++-- XPSDK/Delphi/XPLM/XPLMInstance.pas | 125 ++ XPSDK/Delphi/XPLM/XPLMMap.pas | 608 ++++++ XPSDK/Delphi/XPLM/XPLMMenus.pas | 278 +-- XPSDK/Delphi/XPLM/XPLMNavigation.pas | 400 ++-- XPSDK/Delphi/XPLM/XPLMPlanes.pas | 350 ++-- XPSDK/Delphi/XPLM/XPLMPlugin.pas | 458 +++-- XPSDK/Delphi/XPLM/XPLMProcessing.pas | 292 ++- XPSDK/Delphi/XPLM/XPLMScenery.pas | 485 ++--- XPSDK/Delphi/XPLM/XPLMUtilities.pas | 1372 +++++++------ XPSDK/Libraries/Mac/XPLM.framework/XPLM | Bin 650652 -> 566176 bytes .../Mac/XPWidgets.framework/XPWidgets | Bin 210904 -> 195312 bytes XPSDK/Libraries/Win/XPLM.lib | Bin 39362 -> 0 bytes XPSDK/Libraries/Win/XPLM_64.lib | Bin 39060 -> 51320 bytes XPSDK/Libraries/Win/XPWidgets.lib | Bin 10524 -> 0 bytes XPSDK/Libraries/Win/XPWidgets_64.lib | Bin 10564 -> 10830 bytes XPSDK/README.txt | 67 +- ixwebsocket/CMakeLists.txt | 2 + 59 files changed, 12475 insertions(+), 9196 deletions(-) create mode 100644 XPSDK/CHeaders/XPLM/XPLMInstance.h create mode 100644 XPSDK/CHeaders/XPLM/XPLMMap.h create mode 100644 XPSDK/Delphi/XPLM/XPLMInstance.pas create mode 100644 XPSDK/Delphi/XPLM/XPLMMap.pas delete mode 100644 XPSDK/Libraries/Win/XPLM.lib delete mode 100644 XPSDK/Libraries/Win/XPWidgets.lib diff --git a/TODO.md b/TODO.md index f019edb..92f190c 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1 @@ -- Update OSXCross Docker image to SDK 11 -- Implement ARM64 arch for Plugin - Implement Logbook PHP diff --git a/XPSDK/CHeaders/Widgets/XPStandardWidgets.h b/XPSDK/CHeaders/Widgets/XPStandardWidgets.h index ee3654c..42d4987 100644 --- a/XPSDK/CHeaders/Widgets/XPStandardWidgets.h +++ b/XPSDK/CHeaders/Widgets/XPStandardWidgets.h @@ -2,29 +2,29 @@ #define _XPStandardWidgets_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPStandardWidgets + ***************************************************************************/ /* - * XPStandardWidgets - THEORY OF OPERATION - * - * The standard widgets are widgets built into the widgets library. While you + * ## THEORY OF OPERATION + * + * The standard widgets are widgets built into the widgets library. While you * can gain access to the widget function that drives them, you generally use * them by calling XPCreateWidget and then listening for special messages, * etc. - * + * * The standard widgets often send mesages to themselves when the user * performs an event; these messages are sent up the widget hierarchy until - * they are handled. So you can add a widget proc directly to a push button + * they are handled. So you can add a widget proc directly to a push button * (for example) to intercept the message when it is clicked, or you can put - * one widget proc on a window for all of the push buttons in the window. - * Most of these messages contain the original widget ID as a parameter so you - * can know which widget is messaging no matter who it is sent to. + * one widget proc on a window for all of the push buttons in the window. Most + * of these messages contain the original widget ID as a parameter so you can + * know which widget is messaging no matter who it is sent to. * */ @@ -39,8 +39,8 @@ extern "C" { ***************************************************************************/ /* * The main window widget class provides a "window" as the user knows it. - * These windows are dragable and can be selected. Use them to create - * floating windows and non-modal dialogs. + * These windows are dragable and can be selected. Use them to create floating + * windows and non-modal dialogs. * */ @@ -49,48 +49,43 @@ extern "C" { /* * Main Window Type Values - * - * These type values are used to control the appearance of a main window. + * + * These type values are used to control the appearance of a main window. * */ enum { - /* The standard main window; pin stripes on XP7, metal frame on XP 6. */ - xpMainWindowStyle_MainWindow = 0 + /* The standard main window; pin stripes on XP7, metal frame on XP 6. */ + xpMainWindowStyle_MainWindow = 0, - /* A translucent dark gray window, like the one ATC messages appear in. */ - , - xpMainWindowStyle_Translucent = 1 + /* A translucent dark gray window, like the one ATC messages appear in. */ + xpMainWindowStyle_Translucent = 1, }; /* - * Main Window Properties - * + * Main Window Properties * */ enum { - /* This property specifies the type of window. Set to one of the main - * window * types above. */ - xpProperty_MainWindowType = 1100 + /* This property specifies the type of window. Set to one of the main window * + * types above. */ + xpProperty_MainWindowType = 1100, - /* This property specifies whether the main window has close boxes in its * - * corners. */ - , - xpProperty_MainWindowHasCloseBoxes = 1200 + /* This property specifies whether the main window has close boxes in its * + * corners. */ + xpProperty_MainWindowHasCloseBoxes = 1200, }; /* - * MainWindow Messages - * + * MainWindow Messages * */ enum { - /* This message is sent when the close buttons are pressed for your window. - */ - xpMessage_CloseButtonPushed = 1200 + /* This message is sent when the close buttons are pressed for your window. */ + xpMessage_CloseButtonPushed = 1200, }; @@ -99,9 +94,9 @@ enum { * SUB WINDOW ***************************************************************************/ /* - * X-plane dialogs are divided into separate areas; the sub window widgets + * X-Plane dialogs are divided into separate areas; the sub window widgets * allow you to make these areas. Create one main window and place several - * subwindows inside it. Then place your controls inside the subwindows. + * subwindows inside it. Then place your controls inside the subwindows. * */ @@ -110,34 +105,31 @@ enum { /* * SubWindow Type Values - * - * These values control the appearance of the subwindow. + * + * These values control the appearance of the subwindow. * */ enum { - /* A panel that sits inside a main window. */ - xpSubWindowStyle_SubWindow = 0 + /* A panel that sits inside a main window. */ + xpSubWindowStyle_SubWindow = 0, - /* A screen that sits inside a panel for showing text information. */ - , - xpSubWindowStyle_Screen = 2 + /* A screen that sits inside a panel for showing text information. */ + xpSubWindowStyle_Screen = 2, - /* A list view for scrolling lists. */ - , - xpSubWindowStyle_ListView = 3 + /* A list view for scrolling lists. */ + xpSubWindowStyle_ListView = 3, }; /* - * SubWindow Properties - * + * SubWindow Properties * */ enum { - /* This property specifies the type of window. Set to one of the subwindow - * * types above. */ - xpProperty_SubWindowType = 1200 + /* This property specifies the type of window. Set to one of the subwindow * + * types above. */ + xpProperty_SubWindowType = 1200, }; @@ -147,21 +139,21 @@ enum { ***************************************************************************/ /* * The button class provides a number of different button styles and - * behaviors, including push buttons, radio buttons, check boxes, etc. The + * behaviors, including push buttons, radio buttons, check boxes, etc. The * button label appears on or next to the button depending on the button's * appearance, or type. - * + * * The button's behavior is a separate property that dictates who it hilights - * and what kinds of messages it sends. Since behavior and type are - * different, you can do strange things like make check boxes that act as push - * buttons or push buttons with radio button behavior. - * - * In X-Plane 6 there were no check box graphics. The result is the following - * behavior: in x-plane 6 all check box and radio buttons are round - * (radio-button style) buttons; in X-Plane 7 they are all square (check-box - * style) buttons. In a future version of x-plane, the xpButtonBehavior enums - * will provide the correct graphic (check box or radio button) giving the - * expected result. + * and what kinds of messages it sends. Since behavior and type are different, + * you can do strange things like make check boxes that act as push buttons or + * push buttons with radio button behavior. + * + * In X-Plane 6 there were no check box graphics. The result is the following + * behavior: in X-Plane + * 6 all check box and radio buttons are round (radio-button style) buttons; + * in X-Plane 7 they are all square (check-box style) buttons. In a future + * version of X-Plane, the xpButtonBehavior enums will provide the correct + * graphic (check box or radio button) giving the expected result. * */ @@ -170,111 +162,99 @@ enum { /* * Button Types - * + * * These define the visual appearance of buttons but not how they respond to - * the mouse. + * the mouse. * */ enum { - /* This is a standard push button, like an "OK" or "Cancel" button in a - * dialog * box. */ - xpPushButton = 0 + /* This is a standard push button, like an 'OK' or 'Cancel' button in a dialog* + * box. */ + xpPushButton = 0, - /* A check box or radio button. Use this and the button behaviors below to - * * get the desired behavior. */ - , - xpRadioButton = 1 + /* A check box or radio button. Use this and the button behaviors below to * + * get the desired behavior. */ + xpRadioButton = 1, - /* A window close box. */ - , - xpWindowCloseBox = 3 + /* A window close box. */ + xpWindowCloseBox = 3, - /* A small down arrow. */ - , - xpLittleDownArrow = 5 + /* A small down arrow. */ + xpLittleDownArrow = 5, - /* A small up arrow. */ - , - xpLittleUpArrow = 6 + /* A small up arrow. */ + xpLittleUpArrow = 6, }; /* * Button Behavior Values - * - * These define how the button responds to mouse clicks. + * + * These define how the button responds to mouse clicks. * */ enum { - /* Standard push button behavior. The button hilites while the mouse is * - * clicked over it and unhilites when the mouse is moved outside of it or * - * released. If the mouse is released over the button, the * - * xpMsg_PushButtonPressed message is sent. */ - xpButtonBehaviorPushButton = 0 + /* Standard push button behavior. The button hilites while the mouse is * + * clicked over it and unhilites when the mouse is moved outside of it or * + * released. If the mouse is released over the button, the * + * xpMsg_PushButtonPressed message is sent. */ + xpButtonBehaviorPushButton = 0, - /* Check box behavior. The button immediately toggles its value when the * - * mouse is clicked and sends out a xpMsg_ButtonStateChanged message. */ - , - xpButtonBehaviorCheckBox = 1 + /* Check box behavior. The button immediately toggles its value when the mouse* + * is clicked and sends out a xpMsg_ButtonStateChanged message. */ + xpButtonBehaviorCheckBox = 1, - /* Radio button behavior. The button immediately sets its state to one and - * * sends out a xpMsg_ButtonStateChanged message if it was not already set - * to * one. You must turn off other radio buttons in a group in your - * code. */ - , - xpButtonBehaviorRadioButton = 2 + /* Radio button behavior. The button immediately sets its state to one and * + * sends out a xpMsg_ButtonStateChanged message if it was not already set to * + * one. You must turn off other radio buttons in a group in your code. */ + xpButtonBehaviorRadioButton = 2, }; /* - * Button Properties - * + * Button Properties * */ enum { - /* This property sets the visual type of button. Use one of the button - * types * above. */ - xpProperty_ButtonType = 1300 + /* This property sets the visual type of button. Use one of the button types * + * above. */ + xpProperty_ButtonType = 1300, - /* This property sets the button's behavior. Use one of the button - * behaviors * above. */ - , - xpProperty_ButtonBehavior = 1301 + /* This property sets the button's behavior. Use one of the button behaviors * + * above. */ + xpProperty_ButtonBehavior = 1301, - /* This property tells whether a check box or radio button is "checked" or * - * not. Not used for push buttons. */ - , - xpProperty_ButtonState = 1302 + /* This property tells whether a check box or radio button is "checked" or * + * not. Not used for push buttons. */ + xpProperty_ButtonState = 1302, }; /* * Button Messages - * + * * These messages are sent by the button to itself and then up the widget - * chain when the button is clicked. (You may intercept them by providing a + * chain when the button is clicked. (You may intercept them by providing a * widget handler for the button itself or by providing a handler in a parent - * widget.) + * widget.) * */ enum { - /* This message is sent when the user completes a click and release in a * - * button with push button behavior. Parameter one of the message is the * - * widget ID of the button. This message is dispatched up the widget * - * hierarchy. */ - xpMsg_PushButtonPressed = 1300 + /* This message is sent when the user completes a click and release in a * + * button with push button behavior. Parameter one of the message is the * + * widget ID of the button. This message is dispatched up the widget * + * hierarchy. */ + xpMsg_PushButtonPressed = 1300, - /* This message is sent when a button is clicked that has radio button or * - * check box behavior and its value changes. (Note that if the value - * changes * by setting a property you do not receive this message!) - * Parameter one is * the widget ID of the button, parameter 2 is the new - * state value, either * - * zero or one. This message is dispatched up the widget hierarchy. */ - , - xpMsg_ButtonStateChanged = 1301 + /* This message is sent when a button is clicked that has radio button or * + * check box behavior and its value changes. (Note that if the value changes * + * by setting a property you do not receive this message!) Parameter one is * + * the widget ID of the button, parameter 2 is the new state value, either * + * zero or one. This message is dispatched up the widget hierarchy. */ + xpMsg_ButtonStateChanged = 1301, }; @@ -284,20 +264,20 @@ enum { ***************************************************************************/ /* * The text field widget provides an editable text field including mouse - * selection and keyboard navigation. The contents of the text field are its - * descriptor. (The descriptor changes as the user types.) - * + * selection and keyboard navigation. The contents of the text field are its + * descriptor. (The descriptor changes as the user types.) + * * The text field can have a number of types, that effect the visual layout of * the text field. The text field sends messages to itself so you may control * its behavior. - * + * * If you need to filter keystrokes, add a new handler and intercept the key - * press message. Since key presses are passed by pointer, you can modify the + * press message. Since key presses are passed by pointer, you can modify the * keystroke and pass it through to the text field widget. - * - * WARNING: in x-plane before 7.10 (including 6.70) null characters could - * crash x-plane. To prevent this, wrap this object with a filter function - * (more instructions can be found on the SDK website). + * + * WARNING: in X-Plane before 7.10 (including 6.70) null characters could + * crash X-Plane. To prevent this, wrap this object with a filter function + * (more instructions can be found on the SDK website). * */ @@ -306,89 +286,74 @@ enum { /* * Text Field Type Values - * - * These control the look of the text field. + * + * These control the look of the text field. * */ enum { - /* A field for text entry. */ - xpTextEntryField = 0 + /* A field for text entry. */ + xpTextEntryField = 0, - /* A transparent text field. The user can type and the text is drawn, but - * no * background is drawn. You can draw your own background by adding a - * widget * handler and prehandling the draw message. */ - , - xpTextTransparent = 3 + /* A transparent text field. The user can type and the text is drawn, but no * + * background is drawn. You can draw your own background by adding a widget * + * handler and prehandling the draw message. */ + xpTextTransparent = 3, - /* A translucent edit field, dark gray. */ - , - xpTextTranslucent = 4 + /* A translucent edit field, dark gray. */ + xpTextTranslucent = 4, }; /* - * Text Field Properties - * + * Text Field Properties * */ enum { - /* This is the character position the selection starts at, zero based. If it - * * is the same as the end insertion point, the insertion point is not a * - * selection. */ - xpProperty_EditFieldSelStart = 1400 + /* This is the character position the selection starts at, zero based. If it * + * is the same as the end insertion point, the insertion point is not a * + * selection. */ + xpProperty_EditFieldSelStart = 1400, - /* This is the character position of the end of the selection. */ - , - xpProperty_EditFieldSelEnd = 1401 + /* This is the character position of the end of the selection. */ + xpProperty_EditFieldSelEnd = 1401, - /* This is the character position a drag was started at if the user is * - * dragging to select text, or -1 if a drag is not in progress. */ - , - xpProperty_EditFieldSelDragStart = 1402 + /* This is the character position a drag was started at if the user is * + * dragging to select text, or -1 if a drag is not in progress. */ + xpProperty_EditFieldSelDragStart = 1402, - /* This is the type of text field to display, from the above list. */ - , - xpProperty_TextFieldType = 1403 + /* This is the type of text field to display, from the above list. */ + xpProperty_TextFieldType = 1403, - /* Set this property to 1 to password protect the field. Characters will be - * * drawn as *s even though the descriptor will contain plain-text. */ - , - xpProperty_PasswordMode = 1404 + /* Set this property to 1 to password protect the field. Characters will be * + * drawn as *s even though the descriptor will contain plain-text. */ + xpProperty_PasswordMode = 1404, - /* The max number of characters you can enter, if limited. Zero means * - * unlimited. */ - , - xpProperty_MaxCharacters = 1405 + /* The max number of characters you can enter, if limited. Zero means * + * unlimited. */ + xpProperty_MaxCharacters = 1405, - /* The first visible character on the left. This effectively scrolls the - * text * field. */ - , - xpProperty_ScrollPosition = 1406 + /* The first visible character on the left. This effectively scrolls the text* + * field. */ + xpProperty_ScrollPosition = 1406, - /* The font to draw the field's text with. (An XPLMFontID.) */ - , - xpProperty_Font = 1407 + /* The font to draw the field's text with. (An XPLMFontID.) */ + xpProperty_Font = 1407, - /* This is the active side of the insert selection. (Internal) */ - , - xpProperty_ActiveEditSide = 1408 + /* This is the active side of the insert selection. (Internal) */ + xpProperty_ActiveEditSide = 1408, }; /* - * Text Field Messages - * + * Text Field Messages * */ enum { - /* Text Field Messages * - * * - * The text field sends this message to itself when its text changes. It * - * sends the message up the call chain; param1 is the text field's widget - * ID. */ - xpMsg_TextFieldChanged = 1400 + /* The text field sends this message to itself when its text changes. It sends* + * the message up the call chain; param1 is the text field's widget ID. */ + xpMsg_TextFieldChanged = 1400, }; @@ -397,9 +362,9 @@ enum { * SCROLL BAR ***************************************************************************/ /* - * A standard scroll bar or slider control. The scroll bar has a minimum, - * maximum and current value that is updated when the user drags it. The - * scroll bar sends continuous messages as it is dragged. + * A standard scroll bar or slider control. The scroll bar has a minimum, + * maximum and current value that is updated when the user drags it. The + * scroll bar sends continuous messages as it is dragged. * */ @@ -408,68 +373,55 @@ enum { /* * Scroll Bar Type Values - * - * This defines how the scroll bar looks. + * + * This defines how the scroll bar looks. * */ enum { - /* Scroll bar types. * - * * - * A standard x-plane scroll bar (with arrows on the ends). */ - xpScrollBarTypeScrollBar = 0 + /* A standard X-Plane scroll bar (with arrows on the ends). */ + xpScrollBarTypeScrollBar = 0, - /* A slider, no arrows. */ - , - xpScrollBarTypeSlider = 1 + /* A slider, no arrows. */ + xpScrollBarTypeSlider = 1, }; /* - * Scroll Bar Properties - * + * Scroll Bar Properties * */ enum { - /* The current position of the thumb (in between the min and max, inclusive) - */ - xpProperty_ScrollBarSliderPosition = 1500 + /* The current position of the thumb (in between the min and max, inclusive) */ + xpProperty_ScrollBarSliderPosition = 1500, - /* The value the scroll bar has when the thumb is in the lowest position. */ - , - xpProperty_ScrollBarMin = 1501 + /* The value the scroll bar has when the thumb is in the lowest position. */ + xpProperty_ScrollBarMin = 1501, - /* The value the scroll bar has when the thumb is in the highest position. - */ - , - xpProperty_ScrollBarMax = 1502 + /* The value the scroll bar has when the thumb is in the highest position. */ + xpProperty_ScrollBarMax = 1502, - /* How many units to moev the scroll bar when clicking next to the thumb. - * The * scroll bar always moves one unit when the arrows are clicked. */ - , - xpProperty_ScrollBarPageAmount = 1503 + /* How many units to move the scroll bar when clicking next to the thumb. The * + * scroll bar always moves one unit when the arrows are clicked. */ + xpProperty_ScrollBarPageAmount = 1503, - /* The type of scrollbar from the enums above. */ - , - xpProperty_ScrollBarType = 1504 + /* The type of scrollbar from the enums above. */ + xpProperty_ScrollBarType = 1504, - /* Used internally. */ - , - xpProperty_ScrollBarSlop = 1505 + /* Used internally. */ + xpProperty_ScrollBarSlop = 1505, }; /* - * Scroll Bar Messages - * + * Scroll Bar Messages * */ enum { - /* The Scroll Bar sends this message when the slider position changes. It * - * sends the message up the call chain; param1 is the Scroll Bar widget ID. - */ - xpMsg_ScrollBarSliderPositionChanged = 1500 + /* The scroll bar sends this message when the slider position changes. It * + * sends the message up the call chain; param1 is the Scroll Bar widget ID. */ + xpMsg_ScrollBarSliderPositionChanged = 1500, }; @@ -479,8 +431,8 @@ enum { ***************************************************************************/ /* * A caption is a simple widget that shows its descriptor as a string, useful - * for labeling parts of a window. It always shows its descriptor as its - * string and is otherwise transparent. + * for labeling parts of a window. It always shows its descriptor as its + * string and is otherwise transparent. * */ @@ -488,14 +440,13 @@ enum { #define xpWidgetClass_Caption 6 /* - * Caption Properties - * + * Caption Properties * */ enum { - /* This property specifies whether the caption is lit; use lit captions * - * against screens. */ - xpProperty_CaptionLit = 1600 + /* This property specifies whether the caption is lit; use lit captions * + * against screens. */ + xpProperty_CaptionLit = 1600, }; @@ -505,7 +456,7 @@ enum { ***************************************************************************/ /* * The general graphics widget can show one of many icons available from - * x-plane. + * X-Plane. * */ @@ -514,78 +465,59 @@ enum { /* * General Graphics Types Values - * - * These define the icon for the general graphics. + * + * These define the icon for the general graphics. * */ enum { - xpShip = 4 + xpShip = 4, - , - xpILSGlideScope = 5 + xpILSGlideScope = 5, - , - xpMarkerLeft = 6 + xpMarkerLeft = 6, - , - xp_Airport = 7 + xp_Airport = 7, - , - xpNDB = 8 + xpNDB = 8, - , - xpVOR = 9 + xpVOR = 9, - , - xpRadioTower = 10 + xpRadioTower = 10, - , - xpAircraftCarrier = 11 + xpAircraftCarrier = 11, - , - xpFire = 12 + xpFire = 12, - , - xpMarkerRight = 13 + xpMarkerRight = 13, - , - xpCustomObject = 14 + xpCustomObject = 14, - , - xpCoolingTower = 15 + xpCoolingTower = 15, - , - xpSmokeStack = 16 + xpSmokeStack = 16, - , - xpBuilding = 17 + xpBuilding = 17, - , - xpPowerLine = 18 + xpPowerLine = 18, - , - xpVORWithCompassRose = 19 + xpVORWithCompassRose = 19, - , - xpOilPlatform = 21 + xpOilPlatform = 21, - , - xpOilPlatformSmall = 22 + xpOilPlatformSmall = 22, - , - xpWayPoint = 23 + xpWayPoint = 23, }; /* - * General Graphics Properties - * + * General Graphics Properties * */ enum { - /* This property controls the type of icon that is drawn. */ - xpProperty_GeneralGraphicsType = 1700 + /* This property controls the type of icon that is drawn. */ + xpProperty_GeneralGraphicsType = 1700, }; @@ -594,29 +526,25 @@ enum { * PROGRESS INDICATOR ***************************************************************************/ /* - * This widget implements a progress indicator as seen when x-plane starts up. + * This widget implements a progress indicator as seen when X-Plane starts up. * */ - #define xpWidgetClass_Progress 8 /* - * Progress Indicator Properties - * + * Progress Indicator Properties * */ enum { - /* This is the current value of the progress indicator. */ - xpProperty_ProgressPosition = 1800 + /* This is the current value of the progress indicator. */ + xpProperty_ProgressPosition = 1800, - /* This is the minimum value, equivalent to 0% filled. */ - , - xpProperty_ProgressMin = 1801 + /* This is the minimum value, equivalent to 0% filled. */ + xpProperty_ProgressMin = 1801, - /* This is the maximum value, equivalent to 100% filled. */ - , - xpProperty_ProgressMax = 1802 + /* This is the maximum value, equivalent to 100% filled. */ + xpProperty_ProgressMax = 1802, }; diff --git a/XPSDK/CHeaders/Widgets/XPUIGraphics.h b/XPSDK/CHeaders/Widgets/XPUIGraphics.h index be67bb4..b70e0f6 100644 --- a/XPSDK/CHeaders/Widgets/XPUIGraphics.h +++ b/XPSDK/CHeaders/Widgets/XPUIGraphics.h @@ -2,18 +2,14 @@ #define _XPUIGraphics_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ -/* - * - * - */ +/*************************************************************************** + * XPUIGraphics + ***************************************************************************/ #include "XPWidgetDefs.h" @@ -24,53 +20,43 @@ extern "C" { /*************************************************************************** * UI GRAPHICS ***************************************************************************/ -/* - * - * - */ - /* * XPWindowStyle - * + * * There are a few built-in window styles in X-Plane that you can use. - * + * * Note that X-Plane 6 does not offer real shadow-compositing; you must make * sure to put a window on top of another window of the right style to the - * shadows work, etc. This applies to elements with insets and shadows. The + * shadows work, etc. This applies to elements with insets and shadows. The * rules are: - * + * * Sub windows must go on top of main windows, and screens and list views on - * top of subwindows. Only help and main windows can be over the main screen. - * - * + * top of subwindows. Only help and main windows can be over the main screen. + * * With X-Plane 7 any window or element may be placed over any other element. - * - * Some windows are scaled by stretching, some by repeating. The drawing - * routines know which scaling method to use. The list view cannot be - * rescaled in x-plane 6 because it has both a repeating pattern and a - * gradient in one element. All other elements can be rescaled. + * + * Some windows are scaled by stretching, some by repeating. The drawing + * routines know which scaling method to use. The list view cannot be rescaled + * in X-Plane 6 because it has both a repeating pattern and a gradient in one + * element. All other elements can be rescaled. * */ enum { - /* An LCD screen that shows help. */ - xpWindow_Help = 0 + /* An LCD screen that shows help. */ + xpWindow_Help = 0, - /* A dialog box window. */ - , - xpWindow_MainWindow = 1 + /* A dialog box window. */ + xpWindow_MainWindow = 1, - /* A panel or frame within a dialog box window. */ - , - xpWindow_SubWindow = 2 + /* A panel or frame within a dialog box window. */ + xpWindow_SubWindow = 2, - /* An LCD screen within a panel to hold text displays. */ - , - xpWindow_Screen = 4 + /* An LCD screen within a panel to hold text displays. */ + xpWindow_Screen = 4, - /* A list view within a panel for scrolling file names, etc. */ - , - xpWindow_ListView = 5 + /* A list view within a panel for scrolling file names, etc. */ + xpWindow_ListView = 5, }; @@ -78,184 +64,154 @@ typedef int XPWindowStyle; /* * XPDrawWindow - * + * * This routine draws a window of the given dimensions at the given offset on - * the virtual screen in a given style. The window is automatically scaled as + * the virtual screen in a given style. The window is automatically scaled as * appropriate using a bitmap scaling technique (scaling or repeating) as - * appropriate to the style. + * appropriate to the style. * */ -WIDGET_API void - XPDrawWindow(int inX1, int inY1, int inX2, int inY2, XPWindowStyle inStyle); +WIDGET_API void XPDrawWindow( + int inX1, + int inY1, + int inX2, + int inY2, + XPWindowStyle inStyle); /* * XPGetWindowDefaultDimensions - * - * This routine returns the default dimensions for a window. Output is either - * a minimum or fixed value depending on whether the window is scalable. + * + * This routine returns the default dimensions for a window. Output is either + * a minimum or fixed value depending on whether the window is scalable. * */ -WIDGET_API void XPGetWindowDefaultDimensions(XPWindowStyle inStyle, - int *outWidth, /* Can be NULL */ - int *outHeight); /* Can be NULL */ +WIDGET_API void XPGetWindowDefaultDimensions( + XPWindowStyle inStyle, + int * outWidth, /* Can be NULL */ + int * outHeight); /* Can be NULL */ /* * XPElementStyle - * - * Elements are individually drawable UI things like push buttons, etc. The - * style defines what kind of element you are drawing. Elements can be - * stretched in one or two dimensions (depending on the element). Some + * + * Elements are individually drawable UI things like push buttons, etc. The + * style defines what kind of element you are drawing. Elements can be + * stretched in one or two dimensions (depending on the element). Some * elements can be lit. - * - * In x-plane 6 some elements must be drawn over metal. Some are scalable and - * some are not. Any element can be drawn anywhere in x-plane 7. - * - * Scalable Axis Required Background + * + * In X-Plane 6 some elements must be drawn over metal. Some are scalable and + * some are not. Any element can be drawn anywhere in X-Plane 7. + * + * Scalable Axis Required Background * */ enum { - /* x metal */ - xpElement_TextField = 6 + /* x metal */ + xpElement_TextField = 6, - /* none metal */ - , - xpElement_CheckBox = 9 + /* none metal */ + xpElement_CheckBox = 9, - /* none metal */ - , - xpElement_CheckBoxLit = 10 + /* none metal */ + xpElement_CheckBoxLit = 10, - /* none window header */ - , - xpElement_WindowCloseBox = 14 + /* none window header */ + xpElement_WindowCloseBox = 14, - /* none window header */ - , - xpElement_WindowCloseBoxPressed = 15 + /* none window header */ + xpElement_WindowCloseBoxPressed = 15, - /* x metal */ - , - xpElement_PushButton = 16 + /* x metal */ + xpElement_PushButton = 16, - /* x metal */ - , - xpElement_PushButtonLit = 17 + /* x metal */ + xpElement_PushButtonLit = 17, - /* none any */ - , - xpElement_OilPlatform = 24 + /* none any */ + xpElement_OilPlatform = 24, - /* none any */ - , - xpElement_OilPlatformSmall = 25 + /* none any */ + xpElement_OilPlatformSmall = 25, - /* none any */ - , - xpElement_Ship = 26 + /* none any */ + xpElement_Ship = 26, - /* none any */ - , - xpElement_ILSGlideScope = 27 + /* none any */ + xpElement_ILSGlideScope = 27, - /* none any */ - , - xpElement_MarkerLeft = 28 + /* none any */ + xpElement_MarkerLeft = 28, - /* none any */ - , - xpElement_Airport = 29 + /* none any */ + xpElement_Airport = 29, - /* none any */ - , - xpElement_Waypoint = 30 + /* none any */ + xpElement_Waypoint = 30, - /* none any */ - , - xpElement_NDB = 31 + /* none any */ + xpElement_NDB = 31, - /* none any */ - , - xpElement_VOR = 32 + /* none any */ + xpElement_VOR = 32, - /* none any */ - , - xpElement_RadioTower = 33 + /* none any */ + xpElement_RadioTower = 33, - /* none any */ - , - xpElement_AircraftCarrier = 34 + /* none any */ + xpElement_AircraftCarrier = 34, - /* none any */ - , - xpElement_Fire = 35 + /* none any */ + xpElement_Fire = 35, - /* none any */ - , - xpElement_MarkerRight = 36 + /* none any */ + xpElement_MarkerRight = 36, - /* none any */ - , - xpElement_CustomObject = 37 + /* none any */ + xpElement_CustomObject = 37, - /* none any */ - , - xpElement_CoolingTower = 38 + /* none any */ + xpElement_CoolingTower = 38, - /* none any */ - , - xpElement_SmokeStack = 39 + /* none any */ + xpElement_SmokeStack = 39, - /* none any */ - , - xpElement_Building = 40 + /* none any */ + xpElement_Building = 40, - /* none any */ - , - xpElement_PowerLine = 41 + /* none any */ + xpElement_PowerLine = 41, - /* none metal */ - , - xpElement_CopyButtons = 45 + /* none metal */ + xpElement_CopyButtons = 45, - /* none metal */ - , - xpElement_CopyButtonsWithEditingGrid = 46 + /* none metal */ + xpElement_CopyButtonsWithEditingGrid = 46, - /* x, y metal */ - , - xpElement_EditingGrid = 47 + /* x, y metal */ + xpElement_EditingGrid = 47, - /* THIS CAN PROBABLY BE REMOVED */ - , - xpElement_ScrollBar = 48 + /* THIS CAN PROBABLY BE REMOVED */ + xpElement_ScrollBar = 48, - /* none any */ - , - xpElement_VORWithCompassRose = 49 + /* none any */ + xpElement_VORWithCompassRose = 49, - /* none metal */ - , - xpElement_Zoomer = 51 + /* none metal */ + xpElement_Zoomer = 51, - /* x, y metal */ - , - xpElement_TextFieldMiddle = 52 + /* x, y metal */ + xpElement_TextFieldMiddle = 52, - /* none metal */ - , - xpElement_LittleDownArrow = 53 + /* none metal */ + xpElement_LittleDownArrow = 53, - /* none metal */ - , - xpElement_LittleUpArrow = 54 + /* none metal */ + xpElement_LittleUpArrow = 54, - /* none metal */ - , - xpElement_WindowDragBar = 61 + /* none metal */ + xpElement_WindowDragBar = 61, - /* none metal */ - , - xpElement_WindowDragBarSmooth = 62 + /* none metal */ + xpElement_WindowDragBarSmooth = 62, }; @@ -263,62 +219,62 @@ typedef int XPElementStyle; /* * XPDrawElement - * + * * XPDrawElement draws a given element at an offset on the virtual screen in - * set dimensions. EVEN if the element is not scalable, it will be scaled if - * the width and height do not match the preferred dimensions; it'll just look - * ugly. Pass inLit to see the lit version of the element; if the element - * cannot be lit this is ignored. + * set dimensions. + * *Even* if the element is not scalable, it will be scaled if the width and + * height do not match the preferred dimensions; it'll just look ugly. Pass + * inLit to see the lit version of the element; if the element cannot be lit + * this is ignored. * */ -WIDGET_API void XPDrawElement(int inX1, - int inY1, - int inX2, - int inY2, - XPElementStyle inStyle, - int inLit); +WIDGET_API void XPDrawElement( + int inX1, + int inY1, + int inX2, + int inY2, + XPElementStyle inStyle, + int inLit); /* * XPGetElementDefaultDimensions - * + * * This routine returns the recommended or minimum dimensions of a given UI - * element. outCanBeLit tells whether the element has both a lit and unlit - * state. Pass NULL to not receive any of these parameters. + * element. outCanBeLit tells whether the element has both a lit and unlit + * state. Pass `NULL` to not receive any of these parameters. * */ -WIDGET_API void - XPGetElementDefaultDimensions(XPElementStyle inStyle, - int *outWidth, /* Can be NULL */ - int *outHeight, /* Can be NULL */ - int *outCanBeLit); /* Can be NULL */ +WIDGET_API void XPGetElementDefaultDimensions( + XPElementStyle inStyle, + int * outWidth, /* Can be NULL */ + int * outHeight, /* Can be NULL */ + int * outCanBeLit); /* Can be NULL */ /* * XPTrackStyle - * + * * A track is a UI element that displays a value vertically or horizontally. * X-Plane has three kinds of tracks: scroll bars, sliders, and progress bars. * Tracks can be displayed either horizontally or vertically; tracks will * choose their own layout based on the larger dimension of their dimensions - * (e.g. they know if they are tall or wide). Sliders may be lit or unlit + * (e.g. they know if they are tall or wide). Sliders may be lit or unlit * (showing the user manipulating them). - * - * ScrollBar - this is a standard scroll bar with arrows and a thumb to drag. - * Slider - this is a simple track with a ball in the middle that can be - * slid. Progress - this is a progress indicator showing how a long task is - * going. + * + * - ScrollBar: this is a standard scroll bar with arrows and a thumb to drag. + * - Slider: this is a simple track with a ball in the middle that can be + * slid. + * - Progress: this is a progress indicator showing how a long task is going. * */ enum { - /* not over metal can be lit can be rotated */ - xpTrack_ScrollBar = 0 + /* not over metal can be lit can be rotated */ + xpTrack_ScrollBar = 0, - /* over metal can be lit can be rotated */ - , - xpTrack_Slider = 1 + /* over metal can be lit can be rotated */ + xpTrack_Slider = 1, - /* over metal cannot be lit cannot be rotated */ - , - xpTrack_Progress = 2 + /* over metal cannot be lit cannot be rotated */ + xpTrack_Progress = 2, }; @@ -326,67 +282,70 @@ typedef int XPTrackStyle; /* * XPDrawTrack - * - * This routine draws a track. You pass in the track dimensions and size; the - * track picks the optimal orientation for these dimensions. Pass in the + * + * This routine draws a track. You pass in the track dimensions and size; the + * track picks the optimal orientation for these dimensions. Pass in the * track's minimum current and maximum values; the indicator will be - * positioned appropriately. You can also specify whether the track is lit or - * not. + * positioned appropriately. You can also specify whether the track is lit or + * not. * */ -WIDGET_API void XPDrawTrack(int inX1, - int inY1, - int inX2, - int inY2, - int inMin, - int inMax, - int inValue, - XPTrackStyle inTrackStyle, - int inLit); +WIDGET_API void XPDrawTrack( + int inX1, + int inY1, + int inX2, + int inY2, + int inMin, + int inMax, + int inValue, + XPTrackStyle inTrackStyle, + int inLit); /* * XPGetTrackDefaultDimensions - * + * * This routine returns a track's default smaller dimension; all tracks are - * scalable in the larger dimension. It also returns whether a track can be - * lit. + * scalable in the larger dimension. It also returns whether a track can be + * lit. * */ -WIDGET_API void XPGetTrackDefaultDimensions(XPTrackStyle inStyle, - int *outWidth, - int *outCanBeLit); +WIDGET_API void XPGetTrackDefaultDimensions( + XPTrackStyle inStyle, + int * outWidth, + int * outCanBeLit); /* * XPGetTrackMetrics - * - * This routine returns the metrics of a track. If you want to write UI code + * + * This routine returns the metrics of a track. If you want to write UI code * to manipulate a track, this routine helps you know where the mouse * locations are. For most other elements, the rectangle the element is drawn * in is enough information. However, the scrollbar drawing routine does some - * automatic placement; this routine lets you know where things ended up. You - * pass almost everything you would pass to the draw routine. You get out the + * automatic placement; this routine lets you know where things ended up. You + * pass almost everything you would pass to the draw routine. You get out the * orientation, and other useful stuff. - * + * * Besides orientation, you get five dimensions for the five parts of a * scrollbar, which are the down button, down area (area before the thumb), - * the thumb, and the up area and button. For horizontal scrollers, the left - * button decreases; for vertical scrollers, the top button decreases. + * the thumb, and the up area and button. For horizontal scrollers, the left + * button decreases; for vertical scrollers, the top button decreases. * */ -WIDGET_API void XPGetTrackMetrics(int inX1, - int inY1, - int inX2, - int inY2, - int inMin, - int inMax, - int inValue, - XPTrackStyle inTrackStyle, - int *outIsVertical, - int *outDownBtnSize, - int *outDownPageSize, - int *outThumbSize, - int *outUpPageSize, - int *outUpBtnSize); +WIDGET_API void XPGetTrackMetrics( + int inX1, + int inY1, + int inX2, + int inY2, + int inMin, + int inMax, + int inValue, + XPTrackStyle inTrackStyle, + int * outIsVertical, + int * outDownBtnSize, + int * outDownPageSize, + int * outThumbSize, + int * outUpPageSize, + int * outUpBtnSize); #ifdef __cplusplus } diff --git a/XPSDK/CHeaders/Widgets/XPWidgetDefs.h b/XPSDK/CHeaders/Widgets/XPWidgetDefs.h index 15ae492..c1b2341 100644 --- a/XPSDK/CHeaders/Widgets/XPWidgetDefs.h +++ b/XPSDK/CHeaders/Widgets/XPWidgetDefs.h @@ -2,18 +2,14 @@ #define _XPWidgetDefs_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ -/* - * - * - */ +/*************************************************************************** + * XPWidgetDefs + ***************************************************************************/ #include "XPLMDefs.h" @@ -23,113 +19,107 @@ extern "C" { #if APL -#if XPWIDGETS -#if __GNUC__ >= 4 -#define WIDGET_API __attribute__((visibility("default"))) -#elif __MACH__ -#define WIDGET_API -#else -#define WIDGET_API __declspec(dllexport) -#endif -#else -#define WIDGET_API -#endif + #if XPWIDGETS + #if __GNUC__ >= 4 + #define WIDGET_API __attribute__((visibility("default"))) + #elif __MACH__ + #define WIDGET_API + #else + #define WIDGET_API __declspec(dllexport) + #endif + #else + #define WIDGET_API + #endif #elif IBM -#if XPWIDGETS -#define WIDGET_API __declspec(dllexport) -#else -#define WIDGET_API __declspec(dllimport) -#endif + #if XPWIDGETS + #define WIDGET_API __declspec(dllexport) + #else + #define WIDGET_API __declspec(dllimport) + #endif #elif LIN -#if XPWIDGETS -#if __GNUC__ >= 4 -#define WIDGET_API __attribute__((visibility("default"))) -#else -#define WIDGET_API -#endif -#else -#define WIDGET_API -#endif + #if XPWIDGETS + #if __GNUC__ >= 4 + #define WIDGET_API __attribute__((visibility("default"))) + #else + #define WIDGET_API + #endif + #else + #define WIDGET_API + #endif #else #pragma error "Platform not defined!" #endif -/*************************************************************************** + /*************************************************************************** * WIDGET DEFINITIONS ***************************************************************************/ /* * A widget is a call-back driven screen entity like a push-button, window, * text entry field, etc. - * - * Use the widget API to create widgets of various classes. You can nest them - * into trees of widgets to create complex user interfaces. + * + * Use the widget API to create widgets of various classes. You can nest them + * into trees of widgets to create complex user interfaces. * */ /* * XPWidgetID - * + * * A Widget ID is an opaque unique non-zero handle identifying your widget. - * Use 0 to specify "no widget". This type is defined as wide enough to hold - * a pointer. You receive a widget ID when you create a new widget and then - * use that widget ID to further refer to the widget. + * Use 0 to specify "no widget". This type is defined as wide enough to hold a + * pointer. You receive a widget ID when you create a new widget and then use + * that widget ID to further refer to the widget. * */ -typedef void *XPWidgetID; +typedef void * XPWidgetID; /* * XPWidgetPropertyID - * - * Properties are values attached to instances of your widgets. A property is + * + * Properties are values attached to instances of your widgets. A property is * identified by a 32-bit ID and its value is the width of a pointer. - * - * Each widget instance may have a property or not have it. When you set a + * + * Each widget instance may have a property or not have it. When you set a * property on a widget for the first time, the property is added to the * widget; it then stays there for the life of the widget. - * + * * Some property IDs are predefined by the widget package; you can make up - * your own property IDs as well. + * your own property IDs as well. * */ enum { - /* A window's refcon is an opaque value used by client code to find other - * data * based on it. */ - xpProperty_Refcon = 0 + /* A window's refcon is an opaque value used by client code to find other data* + * based on it. */ + xpProperty_Refcon = 0, - /* These properties are used by the utlities to implement dragging. */ - , - xpProperty_Dragging = 1 + /* These properties are used by the utlities to implement dragging. */ + xpProperty_Dragging = 1, - , - xpProperty_DragXOff = 2 + xpProperty_DragXOff = 2, - , - xpProperty_DragYOff = 3 + xpProperty_DragYOff = 3, - /* Is the widget hilited? (For widgets that support this kind of thing.) */ - , - xpProperty_Hilited = 4 + /* Is the widget hilited? (For widgets that support this kind of thing.) */ + xpProperty_Hilited = 4, - /* Is there a C++ object attached to this widget? */ - , - xpProperty_Object = 5 + /* Is there a C++ object attached to this widget? */ + xpProperty_Object = 5, - /* If this property is 1, the widget package will use OpenGL to restrict * - * drawing to the Wiget's exposed rectangle. */ - , - xpProperty_Clip = 6 + /* If this property is 1, the widget package will use OpenGL to restrict * + * drawing to the Wiget's exposed rectangle. */ + xpProperty_Clip = 6, - /* Is this widget enabled (for those that have a disabled state too)? */ - , - xpProperty_Enabled = 7 + /* Is this widget enabled (for those that have a disabled state too)? */ + xpProperty_Enabled = 7, - /* NOTE: Property IDs 1 - 999 are reserved for the widget's library. * - * * - * NOTE: Property IDs 1000 - 9999 are allocated to the standard widget - * classes * provided with the library Properties 1000 - 1099 are for widget - * class 0, * 1100 - 1199 for widget class 1, etc. */ - , - xpProperty_UserStart = 10000 + /* NOTE: Property IDs 1 - 999 are reserved for the widgets library. * + * * + * NOTE: Property IDs 1000 - 9999 are allocated to the standard widget classes* + * provided with the library. * + * * + * Properties 1000 - 1099 are for widget class 0, 1100 - 1199 for widget class* + * 1, etc. */ + xpProperty_UserStart = 10000, }; @@ -137,86 +127,81 @@ typedef int XPWidgetPropertyID; /* * XPMouseState_t - * + * * When the mouse is clicked or dragged, a pointer to this structure is passed - * to your widget function. + * to your widget function. * */ typedef struct { - int x; - int y; - /* Mouse Button number, left = 0 (right button not yet supported. */ - int button; + int x; + int y; + /* Mouse Button number, left = 0 (right button not yet supported. */ + int button; #if defined(XPLM200) - /* Scroll wheel delta (button in this case would be the wheel axis number). - */ - int delta; + /* Scroll wheel delta (button in this case would be the wheel axis number). */ + int delta; #endif /* XPLM200 */ } XPMouseState_t; /* * XPKeyState_t - * + * * When a key is pressed, a pointer to this struct is passed to your widget - * function. + * function. * */ typedef struct { - /* The ASCII key that was pressed. WARNING: this may be 0 for some - * non-ASCII * key sequences. */ - char key; - /* The flags. Make sure to check this if you only want key-downs! */ - XPLMKeyFlags flags; - /* The virtual key code for the key */ - char vkey; + /* The ASCII key that was pressed. WARNING: this may be 0 for some non-ASCII * + * key sequences. */ + char key; + /* The flags. Make sure to check this if you only want key-downs! */ + XPLMKeyFlags flags; + /* The virtual key code for the key */ + char vkey; } XPKeyState_t; /* * XPWidgetGeometryChange_t - * + * * This structure contains the deltas for your widget's geometry when it - * changes. + * changes. * */ typedef struct { - int dx; - /* +Y = the widget moved up */ - int dy; - int dwidth; - int dheight; + int dx; + /* +Y = the widget moved up */ + int dy; + int dwidth; + int dheight; } XPWidgetGeometryChange_t; /* * XPDispatchMode - * - * The dispatching modes describe how the widgets library sends out messages. - * Currently there are three modes: + * + * The dispatching modes describe how the widgets library sends out messages. + * Currently there are three modes: * */ enum { - /* The message will only be sent to the target widget. */ - xpMode_Direct = 0 + /* The message will only be sent to the target widget. */ + xpMode_Direct = 0, - /* The message is sent to the target widget, then up the chain of parents * - * until the message is handled or a parentless widget is reached. */ - , - xpMode_UpChain = 1 + /* The message is sent to the target widget, then up the chain of parents * + * until the message is handled or a parentless widget is reached. */ + xpMode_UpChain = 1, - /* The message is sent to the target widget and then all of its children * - * recursively depth-first. */ - , - xpMode_Recursive = 2 + /* The message is sent to the target widget and then all of its children * + * recursively depth-first. */ + xpMode_Recursive = 2, - /* The message is snet just to the target, but goes to every callback, even - * if * it is handled. */ - , - xpMode_DirectAllCallbacks = 3 + /* The message is snet just to the target, but goes to every callback, even if* + * it is handled. */ + xpMode_DirectAllCallbacks = 3, - /* The message is only sent to the very first handler even if it is not * - * accepted. (This is really only useful for some internal Widget Lib * - * functions. */ - , - xpMode_Once = 4 + /* The message is only sent to the very first handler even if it is not * + * accepted. (This is really only useful for some internal widget library * + * functions.) */ + xpMode_Once = 4, }; @@ -224,270 +209,236 @@ typedef int XPDispatchMode; /* * XPWidgetClass - * - * Widget classes define predefined widget types. A widget class basically + * + * Widget classes define predefined widget types. A widget class basically * specifies from a library the widget function to be used for the widget. - * Most widgets can be made right from classes. + * Most widgets can be made right from classes. * */ typedef int XPWidgetClass; -/* An unspecified widget class. Other widget classes are in * - * XPStandardWidgets.h */ -#define xpWidgetClass_None 0 +/* An unspecified widget class. Other widget classes are in * + * XPStandardWidgets.h */ +#define xpWidgetClass_None 0 /*************************************************************************** * WIDGET MESSAGES ***************************************************************************/ -/* - * - * - */ - /* * XPWidgetMessage - * + * * Widgets receive 32-bit messages indicating what action is to be taken or - * notifications of events. The list of messages may be expanded. + * notifications of events. The list of messages may be expanded. * */ enum { - /* No message, should not be sent. */ - xpMsg_None = 0 + /* No message, should not be sent. */ + xpMsg_None = 0, - /* The create message is sent once per widget that is created with your - * widget * function and once for any widget that has your widget function - * attached. * - * * - * Dispatching: Direct * - * * - * Param 1: 1 if you are being added as a subclass, 0 if the widget is first - * * being created. */ - , - xpMsg_Create = 1 + /* The create message is sent once per widget that is created with your widget* + * function and once for any widget that has your widget function attached. * + * * + * Dispatching: Direct * + * * + * Param 1: 1 if you are being added as a subclass, 0 if the widget is first * + * being created. */ + xpMsg_Create = 1, - /* The destroy message is sent once for each message that is destroyed that - * * has your widget function. * - * * - * Dispatching: Direct for all * - * * - * Param 1: 1 if being deleted by a recursive delete to the parent, 0 for * - * explicit deletion. */ - , - xpMsg_Destroy = 2 + /* The destroy message is sent once for each message that is destroyed that * + * has your widget function. * + * * + * Dispatching: Direct for all * + * * + * Param 1: 1 if being deleted by a recursive delete to the parent, 0 for * + * explicit deletion. */ + xpMsg_Destroy = 2, - /* The paint message is sent to your widget to draw itself. The paint - * message * is the bare-bones message; in response you must draw yourself, - * draw your * children, set up clipping and culling, check for - * visibility, etc. If you * don't want to do all of this, ignore the - * paint message and a draw message * (see below) will be sent to you. * - * * - * Dispatching: Direct */ - , - xpMsg_Paint = 3 + /* The paint message is sent to your widget to draw itself. The paint message * + * is the bare-bones message; in response you must draw yourself, draw your * + * children, set up clipping and culling, check for visibility, etc. If you * + * don't want to do all of this, ignore the paint message and a draw message * + * (see below) will be sent to you. * + * * + * Dispatching: Direct */ + xpMsg_Paint = 3, - /* The draw message is sent to your widget when it is time to draw yourself. - * * OpenGL will be set up to draw in 2-d global screen coordinates, but you - * * should use the XPLM to set up OpenGL state. * - * * - * Dispatching: Direct */ - , - xpMsg_Draw = 4 + /* The draw message is sent to your widget when it is time to draw yourself. * + * OpenGL will be set up to draw in 2-d global screen coordinates, but you * + * should use the XPLM to set up OpenGL state. * + * * + * Dispatching: Direct */ + xpMsg_Draw = 4, - /* The key press message is sent once per key that is pressed. The first * - * parameter is the type of key code (integer or char) and the second is the - * * code itself. By handling this event, you consume the key stroke. * - * * - * Handling this message 'consumes' the keystroke; not handling it passes it - * * to your parent widget. * - * * - * Dispatching: Up Chain * - * * - * : Param 1: A pointer to an XPKeyState_t structure with the keystroke. */ - , - xpMsg_KeyPress = 5 + /* The key press message is sent once per key that is pressed. The first * + * parameter is the type of key code (integer or char) and the second is the * + * code itself. By handling this event, you consume the key stroke. * + * * + * Handling this message 'consumes' the keystroke; not handling it passes it * + * to your parent widget. * + * * + * Dispatching: Up Chain * + * * + * Param 1: A pointer to an XPKeyState_t structure with the keystroke. */ + xpMsg_KeyPress = 5, - /* Keyboard focus is being given to you. By handling this message you - * accept * keyboard focus. The first parameter will be one if a child of - * yours gave * up focus to you, 0 if someone set focus on you explicitly. - * * - * * - * : Handling this message accepts focus; not handling refuses focus. * - * * - * Dispatching: direct * - * * - * Param 1: 1 if you are gaining focus because your child is giving it up, 0 - * * if someone is explicitly giving you focus. */ - , - xpMsg_KeyTakeFocus = 6 + /* Keyboard focus is being given to you. By handling this message you accept * + * keyboard focus. The first parameter will be one if a child of yours gave up* + * focus to you, 0 if someone set focus on you explicitly. * + * * + * Handling this message accepts focus; not handling refuses focus. * + * * + * Dispatching: direct * + * * + * Param 1: 1 if you are gaining focus because your child is giving it up, 0 * + * if someone is explicitly giving you focus. */ + xpMsg_KeyTakeFocus = 6, - /* Keyboard focus is being taken away from you. The first parameter will be - * * one if you are losing focus because another widget is taking it, or 0 - * if * someone called the API to make you lose focus explicitly. * - * * - * Dispatching: Direct * - * * - * Param 1: 1 if focus is being taken by another widget, 0 if code requested - * * to remove focus. */ - , - xpMsg_KeyLoseFocus = 7 + /* Keyboard focus is being taken away from you. The first parameter will be * + * one if you are losing focus because another widget is taking it, or 0 if * + * someone called the API to make you lose focus explicitly. * + * * + * Dispatching: Direct * + * * + * Param 1: 1 if focus is being taken by another widget, 0 if code requested * + * to remove focus. */ + xpMsg_KeyLoseFocus = 7, - /* You receive one mousedown event per click with a mouse-state structure * - * pointed to by parameter 1, by accepting this you eat the click, otherwise - * * your parent gets it. You will not receive drag and mouse up messages - * if * you do not accept the down message. * - * * - * Handling this message consumes the mouse click, not handling it passes it - * * to the next widget. You can act 'transparent' as a window by never - * handling * moues clicks to certain areas. * - * * - * Dispatching: Up chain NOTE: Technically this is direct dispatched, but - * the * widgets library will shop it to each widget until one consumes the - * click, * making it effectively "up chain". * - * * - * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ - , - xpMsg_MouseDown = 8 + /* You receive one mousedown event per click with a mouse-state structure * + * pointed to by parameter 1, by accepting this you eat the click, otherwise * + * your parent gets it. You will not receive drag and mouse up messages if you* + * do not accept the down message. * + * * + * Handling this message consumes the mouse click, not handling it passes it * + * to the next widget. You can act 'transparent' as a window by never handling* + * moues clicks to certain areas. * + * * + * Dispatching: Up chain NOTE: Technically this is direct dispatched, but the * + * widgets library will shop it to each widget until one consumes the click, * + * making it effectively "up chain". * + * * + * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ + xpMsg_MouseDown = 8, - /* You receive a series of mouse drag messages (typically one per frame in - * the * sim) as the mouse is moved once you have accepted a mouse down - * message. * Parameter one points to a mouse-state structure describing - * the mouse * location. You will continue to receive these until - * the mouse button is * released. You may receive multiple mouse state - * messages with the same mouse * position. You will receive mouse drag - * events even if the mouse is dragged * out of your current or original - * bounds at the time of the mouse down. * - * * - * Dispatching: Direct * - * * - * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ - , - xpMsg_MouseDrag = 9 + /* You receive a series of mouse drag messages (typically one per frame in the* + * sim) as the mouse is moved once you have accepted a mouse down message. * + * Parameter one points to a mouse-state structure describing the mouse * + * location. You will continue to receive these until the mouse button is * + * released. You may receive multiple mouse state messages with the same mouse* + * position. You will receive mouse drag events even if the mouse is dragged * + * out of your current or original bounds at the time of the mouse down. * + * * + * Dispatching: Direct * + * * + * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ + xpMsg_MouseDrag = 9, - /* The mouseup event is sent once when the mouse button is released after a - * * drag or click. You only receive this message if you accept the - * mouseDown * message. Parameter one points to a mouse state structure. - * * - * * - * Dispatching: Direct * - * * - * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ - , - xpMsg_MouseUp = 10 + /* The mouseup event is sent once when the mouse button is released after a * + * drag or click. You only receive this message if you accept the mouseDown * + * message. Parameter one points to a mouse state structure. * + * * + * Dispatching: Direct * + * * + * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ + xpMsg_MouseUp = 10, - /* Your geometry or a child's geometry is being changed. * - * * - * Dispatching: Up chain * - * * - * Param 1: The widget ID of the original reshaped target. * - * * - * Param 2: A pointer to a XPWidgetGeometryChange_t struct describing the * - * change. */ - , - xpMsg_Reshape = 11 + /* Your geometry or a child's geometry is being changed. * + * * + * Dispatching: Up chain * + * * + * Param 1: The widget ID of the original reshaped target. * + * * + * Param 2: A pointer to a XPWidgetGeometryChange_t struct describing the * + * change. */ + xpMsg_Reshape = 11, - /* Your exposed area has changed. * - * * - * Dispatching: Direct */ - , - xpMsg_ExposedChanged = 12 + /* Your exposed area has changed. * + * * + * Dispatching: Direct */ + xpMsg_ExposedChanged = 12, - /* A child has been added to you. The child's ID is passed in parameter - * one. * - * * - * * - * Dispatching: Direct * - * * - * Param 1: The Widget ID of the child being added. */ - , - xpMsg_AcceptChild = 13 + /* A child has been added to you. The child's ID is passed in parameter one. * + * * + * Dispatching: Direct * + * * + * Param 1: The Widget ID of the child being added. */ + xpMsg_AcceptChild = 13, - /* A child has been removed from to you. The child's ID is passed in * - * parameter one. * - * * - * Dispatching: Direct * - * * - * Param 1: The Widget ID of the child being removed. */ - , - xpMsg_LoseChild = 14 + /* A child has been removed from to you. The child's ID is passed in parameter* + * one. * + * * + * Dispatching: Direct * + * * + * Param 1: The Widget ID of the child being removed. */ + xpMsg_LoseChild = 14, - /* You now have a new parent, or have no parent. The parent's ID is passed - * * in, or 0 for no parent. * - * * - * Dispatching: Direct * - * * - * Param 1: The Widget ID of your parent */ - , - xpMsg_AcceptParent = 15 + /* You now have a new parent, or have no parent. The parent's ID is passed in,* + * or 0 for no parent. * + * * + * Dispatching: Direct * + * * + * Param 1: The Widget ID of your parent */ + xpMsg_AcceptParent = 15, - /* You or a child has been shown. Note that this does not include you being - * * shown because your parent was shown, you were put in a new parent, - * your * root was shown, etc. * - * * - * Dispatching: Up chain * - * * - * Param 1: The widget ID of the shown widget. */ - , - xpMsg_Shown = 16 + /* You or a child has been shown. Note that this does not include you being * + * shown because your parent was shown, you were put in a new parent, your * + * root was shown, etc. * + * * + * Dispatching: Up chain * + * * + * Param 1: The widget ID of the shown widget. */ + xpMsg_Shown = 16, - /* You have been hidden. See limitations above. * - * * - * Dispatching: Up chain * - * * - * Param 1: The widget ID of the hidden widget. */ - , - xpMsg_Hidden = 17 + /* You have been hidden. See limitations above. * + * * + * Dispatching: Up chain * + * * + * Param 1: The widget ID of the hidden widget. */ + xpMsg_Hidden = 17, - /* Your descriptor has changed. * - * * - * Dispatching: Direct */ - , - xpMsg_DescriptorChanged = 18 + /* Your descriptor has changed. * + * * + * Dispatching: Direct */ + xpMsg_DescriptorChanged = 18, - /* A property has changed. Param 1 contains the property ID. * - * * - * Dispatching: Direct * - * * - * Param 1: The Property ID being changed. * - * * - * Param 2: The new property value */ - , - xpMsg_PropertyChanged = 19 + /* A property has changed. Param 1 contains the property ID. * + * * + * Dispatching: Direct * + * * + * Param 1: The Property ID being changed. * + * * + * Param 2: The new property value */ + xpMsg_PropertyChanged = 19, #if defined(XPLM200) - /* The mouse wheel has moved. * - * * - * Return 1 to consume the mouse wheel move, or 0 to pass the message to a * - * parent. Dispatching: Up chain * - * * - * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ - , - xpMsg_MouseWheel = 20 + /* The mouse wheel has moved. * + * * + * Return 1 to consume the mouse wheel move, or 0 to pass the message to a * + * parent. Dispatching: Up chain * + * * + * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ + xpMsg_MouseWheel = 20, #endif /* XPLM200 */ #if defined(XPLM200) - /* The cursor is over your widget. If you consume this message, change the - * * XPLMCursorStatus value to indicate the desired result, with the same - * rules * as in XPLMDisplay.h. * - * * - * Return 1 to consume this message, 0 to pass it on. * - * * - * Dispatching: Up chain Param 1: A pointer to an XPMouseState_t struct * - * containing the mouse status. * - * * - * Param 2: A pointer to a XPLMCursorStatus - set this to the cursor result - * * you desire. */ - , - xpMsg_CursorAdjust = 21 + /* The cursor is over your widget. If you consume this message, change the * + * XPLMCursorStatus value to indicate the desired result, with the same rules * + * as in XPLMDisplay.h. * + * * + * Return 1 to consume this message, 0 to pass it on. * + * * + * Dispatching: Up chain Param 1: A pointer to an XPMouseState_t struct * + * containing the mouse status. * + * * + * Param 2: A pointer to a XPLMCursorStatus - set this to the cursor result * + * you desire. */ + xpMsg_CursorAdjust = 21, #endif /* XPLM200 */ - /* NOTE: Message IDs 1000 - 9999 are allocated to the standard widget - * classes * provided with the library with 1000 - 1099 for widget class - * 0, 1100 - 1199 * for widget class 1, etc. Message IDs 10,000 and - * beyond are for plugin use. */ - , - xpMsg_UserStart = 10000 + /* NOTE: Message IDs 1000 - 9999 are allocated to the standard widget classes * + * provided with the library with 1000 - 1099 for widget class 0, 1100 - 1199 * + * for widget class 1, etc. Message IDs 10,000 and beyond are for plugin use. */ + xpMsg_UserStart = 10000, }; @@ -496,27 +447,23 @@ typedef int XPWidgetMessage; /*************************************************************************** * WIDGET CALLBACK FUNCTION ***************************************************************************/ -/* - * - * - */ - /* * XPWidgetFunc_t - * - * This function defines your custom widget's behavior. It will be called by - * the widgets library to send messages to your widget. The message and - * widget ID are passed in, as well as two ptr-width signed parameters whose - * meaning varies with the message. Return 1 to indicate that you have - * processed the message, 0 to indicate that you have not. For any message - * that is not understood, return 0. + * + * This function defines your custom widget's behavior. It will be called by + * the widgets library to send messages to your widget. The message and widget + * ID are passed in, as well as two ptr-width signed parameters whose meaning + * varies with the message. Return 1 to indicate that you have processed the + * message, 0 to indicate that you have not. For any message that is not + * understood, return 0. * */ -typedef int (*XPWidgetFunc_t)(XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2); +typedef int (* XPWidgetFunc_t)( + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); #ifdef __cplusplus } diff --git a/XPSDK/CHeaders/Widgets/XPWidgetUtils.h b/XPSDK/CHeaders/Widgets/XPWidgetUtils.h index 3379491..ff757f7 100644 --- a/XPSDK/CHeaders/Widgets/XPWidgetUtils.h +++ b/XPSDK/CHeaders/Widgets/XPWidgetUtils.h @@ -2,35 +2,35 @@ #define _XPWidgetUtils_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPWidgetUtils + ***************************************************************************/ /* - * XPWidgetUtils - USAGE NOTES - * + * ## USAGE NOTES + * * The XPWidgetUtils library contains useful functions that make writing and - * using widgets less of a pain. - * - * One set of functions are the widget behavior functions. These functions - * each add specific useful behaviors to widgets. They can be used in two + * using widgets less of a pain. + * + * One set of functions are the widget behavior functions. These functions + * each add specific useful behaviors to widgets. They can be used in two * manners: - * + * * 1. You can add a widget behavior function to a widget as a callback proc - * using the XPAddWidgetCallback function. The widget will gain that - * behavior. Remember that the last function you add has highest priority. - * You can use this to change or augment the behavior of an existing finished - * widget. - * + * using the XPAddWidgetCallback function. The widget will gain that + * behavior. Remember that the last function you add has highest priority. + * You can use this to change or augment the behavior of an existing + * finished widget. * 2. You can call a widget function from inside your own widget function. - * This allows you to include useful behaviors in custom-built widgets. A - * number of the standard widgets get their behavior from this library. To do - * this, call the behavior function from your function first. If it returns - * 1, that means it handled the event and you don't need to; simply return 1. + * This allows you to include useful behaviors in custom-built widgets. A + * number of the standard widgets get their behavior from this library. To + * do this, call the behavior function from your function first. If it + * returns 1, that means it handled the event and you don't need to; simply + * return 1. * */ @@ -43,100 +43,104 @@ extern "C" { /*************************************************************************** * GENERAL UTILITIES ***************************************************************************/ -/* - * - * - */ + /* * Convenience accessors * * It can be clumsy accessing the variables passed in by pointer to a struct - * for mouse and reshape messages; these accessors let you simply pass in the - * param right from the arguments of your widget proc and get back the value you - * want. + * for mouse and reshape messages; these accessors let you simply pass in the param + * right from the arguments of your widget proc and get back the value you want. * */ -#define MOUSE_X(param) (((XPMouseState_t *)(param))->x) -#define MOUSE_Y(param) (((XPMouseState_t *)(param))->y) +#define MOUSE_X(param) (((XPMouseState_t *) (param))->x) +#define MOUSE_Y(param) (((XPMouseState_t *) (param))->y) -#define DELTA_X(param) (((XPWidgetGeometryChange_t *)(param))->dx) -#define DELTA_Y(param) (((XPWidgetGeometryChange_t *)(param))->dy) -#define DELTA_W(param) (((XPWidgetGeometryChange_t *)(param))->dwidth) -#define DELTA_H(param) (((XPWidgetGeometryChange_t *)(param))->dheight) +#define DELTA_X(param) (((XPWidgetGeometryChange_t *) (param))->dx) +#define DELTA_Y(param) (((XPWidgetGeometryChange_t *) (param))->dy) +#define DELTA_W(param) (((XPWidgetGeometryChange_t *) (param))->dwidth) +#define DELTA_H(param) (((XPWidgetGeometryChange_t *) (param))->dheight) -#define KEY_CHAR(param) (((XPKeyState_t *)(param))->key) -#define KEY_FLAGS(param) (((XPKeyState_t *)(param))->flags) -#define KEY_VKEY(param) (((XPKeyState_t *)(param))->vkey) +#define KEY_CHAR(param) (((XPKeyState_t *) (param))->key) +#define KEY_FLAGS(param) (((XPKeyState_t *) (param))->flags) +#define KEY_VKEY(param) (((XPKeyState_t *) (param))->vkey) -#define IN_RECT(x, y, l, t, r, b) \ - (((x) >= (l)) && ((x) <= (r)) && ((y) >= (b)) && ((y) <= (t))) +#define IN_RECT(x, y, l, t, r, b) \ + (((x) >= (l)) && ((x) <= (r)) && ((y) >= (b)) && ((y) <= (t))) /* * XPWidgetCreate_t - * + * * This structure contains all of the parameters needed to create a wiget. It - * is used with XPUCreateWidgets to create widgets in bulk from an array. All + * is used with XPUCreateWidgets to create widgets in bulk from an array. All * parameters correspond to those of XPCreateWidget except for the container - * index. If the container index is equal to the index of a widget in the - * array, the widget in the array passed to XPUCreateWidgets is used as the - * parent of this widget. Note that if you pass an index greater than your - * own position in the array, the parent you are requesting will not exist - * yet. If the container index is NO_PARENT, the parent widget is specified as + * index. + * + * If the container index is equal to the index of a widget in the array, the + * widget in the array passed to XPUCreateWidgets is used as the parent of + * this widget. Note that if you pass an index greater than your own position + * in the array, the parent you are requesting will not exist yet. + * + * If the container index is NO_PARENT, the parent widget is specified as * NULL. If the container index is PARAM_PARENT, the widget passed into - * XPUCreateWidgets is used. + * XPUCreateWidgets is used. * */ typedef struct { - int left; - int top; - int right; - int bottom; - int visible; - const char *descriptor; - int isRoot; - int containerIndex; - XPWidgetClass widgetClass; + int left; + int top; + int right; + int bottom; + int visible; + const char * descriptor; + /* Whether ethis widget is a root wiget */ + int isRoot; + /* The index of the widget to contain within, or a constant */ + int containerIndex; + XPWidgetClass widgetClass; } XPWidgetCreate_t; -#define NO_PARENT -1 +#define NO_PARENT -1 -#define PARAM_PARENT -2 +#define PARAM_PARENT -2 #define WIDGET_COUNT(x) ((sizeof(x) / sizeof(XPWidgetCreate_t))) - + /* * XPUCreateWidgets - * - * This function creates a series of widgets from a table...see - * XPCreateWidget_t above. Pass in an array of widget creation structures and + * + * This function creates a series of widgets from a table (see + * XPCreateWidget_t above). Pass in an array of widget creation structures and * an array of widget IDs that will receive each widget. - * + * * Widget parents are specified by index into the created widget table, - * allowing you to create nested widget structures. You can create multiple - * widget trees in one table. Generally you should create widget trees from + * allowing you to create nested widget structures. You can create multiple + * widget trees in one table. Generally you should create widget trees from * the top down. - * + * * You can also pass in a widget ID that will be used when the widget's parent * is listed as PARAM_PARENT; this allows you to embed widgets created with - * XPUCreateWidgets in a widget created previously. + * XPUCreateWidgets in a widget created previously. * */ -WIDGET_API void XPUCreateWidgets(const XPWidgetCreate_t *inWidgetDefs, - int inCount, - XPWidgetID inParamParent, - XPWidgetID *ioWidgets); +WIDGET_API void XPUCreateWidgets( + const XPWidgetCreate_t * inWidgetDefs, + int inCount, + XPWidgetID inParamParent, + XPWidgetID * ioWidgets); /* * XPUMoveWidgetBy - * + * * Simply moves a widget by an amount, +x = right, +y=up, without resizing the - * widget. + * widget. * */ -WIDGET_API void - XPUMoveWidgetBy(XPWidgetID inWidget, int inDeltaX, int inDeltaY); +WIDGET_API void XPUMoveWidgetBy( + XPWidgetID inWidget, + int inDeltaX, + int inDeltaY); /*************************************************************************** * LAYOUT MANAGERS @@ -144,23 +148,24 @@ WIDGET_API void /* * The layout managers are widget behavior functions for handling where * widgets move. Layout managers can be called from a widget function or - * attached to a widget later. + * attached to a widget later. * */ /* * XPUFixedLayout - * + * * This function causes the widget to maintain its children in fixed position - * relative to itself as it is resized. Use this on the top level 'window' - * widget for your window. + * relative to itself as it is resized. Use this on the top level 'window' + * widget for your window. * */ -WIDGET_API int XPUFixedLayout(XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2); +WIDGET_API int XPUFixedLayout( + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); /*************************************************************************** * WIDGET PROC BEHAVIORS @@ -168,54 +173,57 @@ WIDGET_API int XPUFixedLayout(XPWidgetMessage inMessage, /* * These widget behavior functions add other useful behaviors to widgets. * These functions cannot be attached to a widget; they must be called from - * your widget function. + * your widget function. * */ /* * XPUSelectIfNeeded - * + * * This causes the widget to bring its window to the foreground if it is not - * already. inEatClick specifies whether clicks in the background should be - * consumed by bringin the window to the foreground. + * already. inEatClick specifies whether clicks in the background should be + * consumed by bringin the window to the foreground. * */ -WIDGET_API int XPUSelectIfNeeded(XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2, - int inEatClick); +WIDGET_API int XPUSelectIfNeeded( + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2, + int inEatClick); /* * XPUDefocusKeyboard - * + * * This causes a click in the widget to send keyboard focus back to X-Plane. - * This stops editing of any text fields, etc. + * This stops editing of any text fields, etc. * */ -WIDGET_API int XPUDefocusKeyboard(XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2, - int inEatClick); +WIDGET_API int XPUDefocusKeyboard( + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2, + int inEatClick); /* * XPUDragWidget - * - * XPUDragWidget drags the widget in response to mouse clicks. Pass in not + * + * XPUDragWidget drags the widget in response to mouse clicks. Pass in not * only the event, but the global coordinates of the drag region, which might - * be a sub-region of your widget (for example, a title bar). + * be a sub-region of your widget (for example, a title bar). * */ -WIDGET_API int XPUDragWidget(XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2, - int inLeft, - int inTop, - int inRight, - int inBottom); +WIDGET_API int XPUDragWidget( + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2, + int inLeft, + int inTop, + int inRight, + int inBottom); #ifdef __cplusplus } diff --git a/XPSDK/CHeaders/Widgets/XPWidgets.h b/XPSDK/CHeaders/Widgets/XPWidgets.h index 6cfd277..f4423e2 100644 --- a/XPSDK/CHeaders/Widgets/XPWidgets.h +++ b/XPSDK/CHeaders/Widgets/XPWidgets.h @@ -2,84 +2,71 @@ #define _XPWidgets_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPWidgets + ***************************************************************************/ /* - * WIDGETS - THEORY OF OPERATION AND NOTES - * - * Widgets are persistent view 'objects' for X-Plane. A widget is an object - * referenced by its opaque handle (widget ID) and the APIs in this file. You - * cannot access the widget's guts directly. Every Widget has the following + * ## THEORY OF OPERATION AND NOTES + * + * Widgets are persistent view 'objects' for X-Plane. A widget is an object + * referenced by its opaque handle (widget ID) and the APIs in this file. You + * cannot access the widget's guts directly. Every Widget has the following * intrinsic data: - * + * * - A bounding box defined in global screen coordinates with 0,0 in the - * bottom left and +y = up, +x = right. - * + * bottom left and +y = up, +x = right. * - A visible box, which is the intersection of the bounding box with the - * widget's parents visible box. - * - * - Zero or one parent widgets. (Always zero if the widget is a root widget. - * - * + * widget's parents visible box. + * - Zero or one parent widgets. (Always zero if the widget is a root widget. * - Zero or more child widgets. - * - * - Whether the widget is a root. Root widgets are the top level plugin - * windows. - * + * - Whether the widget is a root. Root widgets are the top level plugin + * windows. * - Whether the widget is visible. - * * - A text string descriptor, whose meaning varies from widget to widget. - * * - An arbitrary set of 32 bit integral properties defined by 32-bit integral - * keys. This is how specific widgets - * - * store specific data. - * + * keys. This is how specific widgets store specific data. * - A list of widget callbacks proc that implements the widgets behaviors. - * + * * The Widgets library sends messages to widgets to request specific behaviors * or notify the widget of things. - * + * * Widgets may have more than one callback function, in which case messages * are sent to the most recently added callback function until the message is - * handled. Messages may also be sent to parents or children; see the + * handled. Messages may also be sent to parents or children; see the * XPWidgetDefs.h header file for the different widget message dispatching - * functions. By adding a callback function to a window you can 'subclass' - * its behavior. - * - * A set of standard widgets are provided that serve common UI purposes. You + * functions. By adding a callback function to a window you can 'subclass' its + * behavior. + * + * A set of standard widgets are provided that serve common UI purposes. You * can also customize or implement entirely custom widgets. - * + * * Widgets are different than other view hierarchies (most notably Win32, * which they bear a striking resemblance to) in the following ways: - * - * - Not all behavior can be patched. State that is managed by the XPWidgets - * DLL and not by individual widgets cannot be customized. - * - * - All coordinates are in global screen coordinates. Coordinates are not - * relative to an enclosing widget, nor are they relative to a display window. - * - * + * + * - Not all behavior can be patched. State that is managed by the XPWidgets + * DLL and not by individual widgets cannot be customized. + * - All coordinates are in global screen coordinates. Coordinates are not + * relative to an enclosing widget, nor are they relative to a display + * window. * - Widget messages are always dispatched synchronously, and there is no - * concept of scheduling an update or a dirty region. Messages originate from - * X-Plane as the sim cycle goes by. Since x-plane is constantly redrawing, - * so are widgets; there is no need to mark a part of a widget as 'needing - * redrawing' because redrawing happens frequently whether the widget needs it - * or not. - * + * concept of scheduling an update or a dirty region. Messages originate + * from X-Plane as the sim cycle goes by. Since X-Plane is constantly + * redrawing, so are widgets; there is no need to mark a part of a widget as + * 'needing redrawing' because redrawing happens frequently whether the + * widget needs it or not. * - Any widget may be a 'root' widget, causing it to be drawn; there is no - * relationship between widget class and rootness. Root widgets are - * imlemented as XPLMDisply windows. + * relationship between widget class and rootness. Root widgets are + * imlemented as XPLMDisply windows. * */ #include "XPWidgetDefs.h" +#include "XPLMDisplay.h" #ifdef __cplusplus extern "C" { @@ -88,410 +75,423 @@ extern "C" { /*************************************************************************** * WIDGET CREATION AND MANAGEMENT ***************************************************************************/ -/* - * - * - */ - /* * XPCreateWidget - * + * * This function creates a new widget and returns the new widget's ID to you. - * If the widget creation fails for some reason, it returns NULL. Widget + * If the widget creation fails for some reason, it returns NULL. Widget * creation will fail either if you pass a bad class ID or if there is not * adequate memory. - * + * * Input Parameters: - * + * * - Top, left, bottom, and right in global screen coordinates defining the - * widget's location on the screen. - * + * widget's location on the screen. * - inVisible is 1 if the widget should be drawn, 0 to start the widget as - * hidden. - * + * hidden. * - inDescriptor is a null terminated string that will become the widget's - * descriptor. - * + * descriptor. * - inIsRoot is 1 if this is going to be a root widget, 0 if it will not be. - * - * - inContainer is the ID of this widget's container. It must be 0 for a - * root widget. for a non-root widget, pass the widget ID of the widget to - * place this widget within. If this widget is not going to start inside - * another widget, pass 0; this new widget will then just be floating off in - * space (and will not be drawn until it is placed in a widget. - * - * - inClass is the class of the widget to draw. Use one of the predefined - * class-IDs to create a standard widget. - * + * - inContainer is the ID of this widget's container. It must be 0 for a root + * widget. for a non-root widget, pass the widget ID of the widget to place + * this widget within. If this widget is not going to start inside another + * widget, pass 0; this new widget will then just be floating off in space + * (and will not be drawn until it is placed in a widget. + * - inClass is the class of the widget to draw. Use one of the predefined + * class-IDs to create a standard widget. + * * A note on widget embedding: a widget is only called (and will be drawn, - * etc.) if it is placed within a widget that will be called. Root widgets - * are always called. So it is possible to have whole chains of widgets that - * are simply not called. You can preconstruct widget trees and then place - * them into root widgets later to activate them if you wish. + * etc.) if it is placed within a widget that will be called. Root widgets are + * always called. So it is possible to have whole chains of widgets that are + * simply not called. You can preconstruct widget trees and then place them + * into root widgets later to activate them if you wish. * */ -WIDGET_API XPWidgetID XPCreateWidget(int inLeft, - int inTop, - int inRight, - int inBottom, - int inVisible, - const char *inDescriptor, - int inIsRoot, - XPWidgetID inContainer, - XPWidgetClass inClass); +WIDGET_API XPWidgetID XPCreateWidget( + int inLeft, + int inTop, + int inRight, + int inBottom, + int inVisible, + const char * inDescriptor, + int inIsRoot, + XPWidgetID inContainer, + XPWidgetClass inClass); /* * XPCreateCustomWidget - * + * * This function is the same as XPCreateWidget except that instead of passing * a class ID, you pass your widget callback function pointer defining the - * widget. Use this function to define a custom widget. All parameters are - * the same as XPCreateWidget, except that the widget class has been replaced - * with the widget function. + * widget. Use this function to define a custom widget. All parameters are the + * same as XPCreateWidget, except that the widget class has been replaced with + * the widget function. * */ -WIDGET_API XPWidgetID XPCreateCustomWidget(int inLeft, - int inTop, - int inRight, - int inBottom, - int inVisible, - const char *inDescriptor, - int inIsRoot, - XPWidgetID inContainer, - XPWidgetFunc_t inCallback); +WIDGET_API XPWidgetID XPCreateCustomWidget( + int inLeft, + int inTop, + int inRight, + int inBottom, + int inVisible, + const char * inDescriptor, + int inIsRoot, + XPWidgetID inContainer, + XPWidgetFunc_t inCallback); /* * XPDestroyWidget - * - * This class destroys a widget. Pass in the ID of the widget to kill. If - * you pass 1 for inDestroyChilren, the widget's children will be destroyed - * first, then this widget will be destroyed. (Furthermore, the widget's - * children will be destroyed with the inDestroyChildren flag set to 1, so the - * destruction will recurse down the widget tree.) If you pass 0 for this - * flag, the child widgets will simply end up with their parent set to 0. + * + * This class destroys a widget. Pass in the ID of the widget to kill. If you + * pass 1 for inDestroyChilren, the widget's children will be destroyed first, + * then this widget will be destroyed. (Furthermore, the widget's children + * will be destroyed with the inDestroyChildren flag set to 1, so the + * destruction will recurse down the widget tree.) If you pass 0 for this + * flag, the child widgets will simply end up with their parent set to 0. * */ -WIDGET_API void XPDestroyWidget(XPWidgetID inWidget, int inDestroyChildren); +WIDGET_API void XPDestroyWidget( + XPWidgetID inWidget, + int inDestroyChildren); /* * XPSendMessageToWidget - * - * This sends any message to a widget. You should probably not go around + * + * This sends any message to a widget. You should probably not go around * simulating the predefined messages that the widgets library defines for - * you. You may however define custom messages for your widgets and send them + * you. You may however define custom messages for your widgets and send them * with this method. - * + * * This method supports several dispatching patterns; see XPDispatchMode for * more info. The function returns 1 if the message was handled, 0 if it was * not. - * + * * For each widget that receives the message (see the dispatching modes), each - * widget function from the most recently installed to the oldest one - * receives the message in order until it is handled. + * widget function from the most recently installed to the oldest one receives + * the message in order until it is handled. * */ -WIDGET_API int XPSendMessageToWidget(XPWidgetID inWidget, - XPWidgetMessage inMessage, - XPDispatchMode inMode, - intptr_t inParam1, - intptr_t inParam2); +WIDGET_API int XPSendMessageToWidget( + XPWidgetID inWidget, + XPWidgetMessage inMessage, + XPDispatchMode inMode, + intptr_t inParam1, + intptr_t inParam2); /*************************************************************************** * WIDGET POSITIONING AND VISIBILITY ***************************************************************************/ -/* - * - * - */ - /* * XPPlaceWidgetWithin - * - * This function changes which container a widget resides in. You may NOT use - * this function on a root widget! inSubWidget is the widget that will be - * moved. Pass a widget ID in inContainer to make inSubWidget be a child of - * inContainer. It will become the last/closest widget in the container. - * Pass 0 to remove the widget from any container. Any call to this other - * than passing the widget ID of the old parent of the affected widget will - * cause the widget to be removed from its old parent. Placing a widget within - * its own parent simply makes it the last widget. - * + * + * This function changes which container a widget resides in. You may NOT use + * this function on a root widget! inSubWidget is the widget that will be + * moved. Pass a widget ID in inContainer to make inSubWidget be a child of + * inContainer. It will become the last/closest widget in the container. Pass + * 0 to remove the widget from any container. Any call to this other than + * passing the widget ID of the old parent of the affected widget will cause + * the widget to be removed from its old parent. Placing a widget within its + * own parent simply makes it the last widget. + * * NOTE: this routine does not reposition the sub widget in global - * coordinates. If the container has layout management code, it will + * coordinates. If the container has layout management code, it will * reposition the subwidget for you, otherwise you must do it with - * SetWidgetGeometry. + * SetWidgetGeometry. * */ -WIDGET_API void XPPlaceWidgetWithin(XPWidgetID inSubWidget, - XPWidgetID inContainer); +WIDGET_API void XPPlaceWidgetWithin( + XPWidgetID inSubWidget, + XPWidgetID inContainer); /* * XPCountChildWidgets - * - * This routine returns the number of widgets another widget contains. + * + * This routine returns the number of widgets another widget contains. * */ -WIDGET_API int XPCountChildWidgets(XPWidgetID inWidget); +WIDGET_API int XPCountChildWidgets( + XPWidgetID inWidget); /* * XPGetNthChildWidget - * - * This routine returns the widget ID of a child widget by index. Indexes are + * + * This routine returns the widget ID of a child widget by index. Indexes are * 0 based, from 0 to one minus the number of widgets in the parent, - * inclusive. If the index is invalid, 0 is returned. + * inclusive. If the index is invalid, 0 is returned. * */ -WIDGET_API XPWidgetID XPGetNthChildWidget(XPWidgetID inWidget, int inIndex); +WIDGET_API XPWidgetID XPGetNthChildWidget( + XPWidgetID inWidget, + int inIndex); /* * XPGetParentWidget - * - * This routine returns the parent of a widget, or 0 if the widget has no - * parent. Root widgets never have parents and therefore always return 0. + * + * Returns the parent of a widget, or 0 if the widget has no parent. Root + * widgets never have parents and therefore always return 0. * */ -WIDGET_API XPWidgetID XPGetParentWidget(XPWidgetID inWidget); +WIDGET_API XPWidgetID XPGetParentWidget( + XPWidgetID inWidget); /* * XPShowWidget - * - * This routine makes a widget visible if it is not already. Note that if a + * + * This routine makes a widget visible if it is not already. Note that if a * widget is not in a rooted widget hierarchy or one of its parents is not - * visible, it will still not be visible to the user. + * visible, it will still not be visible to the user. * */ -WIDGET_API void XPShowWidget(XPWidgetID inWidget); +WIDGET_API void XPShowWidget( + XPWidgetID inWidget); /* * XPHideWidget - * - * Makes a widget invisible. See XPShowWidget for considerations of when a - * widget might not be visible despite its own visibility state. + * + * Makes a widget invisible. See XPShowWidget for considerations of when a + * widget might not be visible despite its own visibility state. * */ -WIDGET_API void XPHideWidget(XPWidgetID inWidget); +WIDGET_API void XPHideWidget( + XPWidgetID inWidget); /* * XPIsWidgetVisible - * - * This returns 1 if a widget is visible, 0 if it is not. Note that this - * routine takes into consideration whether a parent is invisible. Use this - * routine to tell if the user can see the widget. + * + * This returns 1 if a widget is visible, 0 if it is not. Note that this + * routine takes into consideration whether a parent is invisible. Use this + * routine to tell if the user can see the widget. * */ -WIDGET_API int XPIsWidgetVisible(XPWidgetID inWidget); +WIDGET_API int XPIsWidgetVisible( + XPWidgetID inWidget); /* * XPFindRootWidget - * - * XPFindRootWidget returns the Widget ID of the root widget that contains the - * passed in widget or NULL if the passed in widget is not in a rooted - * hierarchy. + * + * Returns the Widget ID of the root widget that contains the passed in widget + * or NULL if the passed in widget is not in a rooted hierarchy. * */ -WIDGET_API XPWidgetID XPFindRootWidget(XPWidgetID inWidget); +WIDGET_API XPWidgetID XPFindRootWidget( + XPWidgetID inWidget); /* * XPBringRootWidgetToFront - * + * * This routine makes the specified widget be in the front most widget * hierarchy. If this widget is a root widget, its widget hierarchy comes to - * front, otherwise the widget's root is brought to the front. If this widget + * front, otherwise the widget's root is brought to the front. If this widget * is not in an active widget hiearchy (e.g. there is no root widget at the - * top of the tree), this routine does nothing. + * top of the tree), this routine does nothing. * */ -WIDGET_API void XPBringRootWidgetToFront(XPWidgetID inWidget); +WIDGET_API void XPBringRootWidgetToFront( + XPWidgetID inWidget); /* * XPIsWidgetInFront - * + * * This routine returns true if this widget's hierarchy is the front most * hierarchy. It returns false if the widget's hierarchy is not in front, or - * if the widget is not in a rooted hierarchy. + * if the widget is not in a rooted hierarchy. * */ -WIDGET_API int XPIsWidgetInFront(XPWidgetID inWidget); +WIDGET_API int XPIsWidgetInFront( + XPWidgetID inWidget); /* * XPGetWidgetGeometry - * + * * This routine returns the bounding box of a widget in global coordinates. - * Pass NULL for any parameter you are not interested in. + * Pass NULL for any parameter you are not interested in. * */ -WIDGET_API void XPGetWidgetGeometry(XPWidgetID inWidget, - int *outLeft, /* Can be NULL */ - int *outTop, /* Can be NULL */ - int *outRight, /* Can be NULL */ - int *outBottom); /* Can be NULL */ +WIDGET_API void XPGetWidgetGeometry( + XPWidgetID inWidget, + int * outLeft, /* Can be NULL */ + int * outTop, /* Can be NULL */ + int * outRight, /* Can be NULL */ + int * outBottom); /* Can be NULL */ /* * XPSetWidgetGeometry - * - * This function changes the bounding box of a widget. + * + * This function changes the bounding box of a widget. * */ -WIDGET_API void XPSetWidgetGeometry(XPWidgetID inWidget, - int inLeft, - int inTop, - int inRight, - int inBottom); +WIDGET_API void XPSetWidgetGeometry( + XPWidgetID inWidget, + int inLeft, + int inTop, + int inRight, + int inBottom); /* * XPGetWidgetForLocation - * + * * Given a widget and a location, this routine returns the widget ID of the - * child of that widget that owns that location. If inRecursive is true then + * child of that widget that owns that location. If inRecursive is true then * this will return a child of a child of a widget as it tries to find the - * deepest widget at that location. If inVisibleOnly is true, then only - * visible widgets are considered, otherwise all widgets are considered. The + * deepest widget at that location. If inVisibleOnly is true, then only + * visible widgets are considered, otherwise all widgets are considered. The * widget ID passed for inContainer will be returned if the location is in - * that widget but not in a child widget. 0 is returned if the location is - * not in the container. - * + * that widget but not in a child widget. 0 is returned if the location is not + * in the container. + * * NOTE: if a widget's geometry extends outside its parents geometry, it will * not be returned by this call for mouse locations outside the parent - * geometry. The parent geometry limits the child's eligibility for mouse - * location. + * geometry. The parent geometry limits the child's eligibility for mouse + * location. * */ -WIDGET_API XPWidgetID XPGetWidgetForLocation(XPWidgetID inContainer, - int inXOffset, - int inYOffset, - int inRecursive, - int inVisibleOnly); +WIDGET_API XPWidgetID XPGetWidgetForLocation( + XPWidgetID inContainer, + int inXOffset, + int inYOffset, + int inRecursive, + int inVisibleOnly); /* * XPGetWidgetExposedGeometry - * + * * This routine returns the bounds of the area of a widget that is completely - * within its parent widgets. Since a widget's bounding box can be outside - * its parent, part of its area will not be elligible for mouse clicks and - * should not draw. Use XPGetWidgetGeometry to find out what area defines - * your widget's shape, but use this routine to find out what area to actually - * draw into. Note that the widget library does not use OpenGL clipping to - * keep frame rates up, although you could use it internally. + * within its parent widgets. Since a widget's bounding box can be outside its + * parent, part of its area will not be elligible for mouse clicks and should + * not draw. Use XPGetWidgetGeometry to find out what area defines your + * widget's shape, but use this routine to find out what area to actually draw + * into. Note that the widget library does not use OpenGL clipping to keep + * frame rates up, although you could use it internally. * */ -WIDGET_API void XPGetWidgetExposedGeometry(XPWidgetID inWidgetID, - int *outLeft, /* Can be NULL */ - int *outTop, /* Can be NULL */ - int *outRight, /* Can be NULL */ - int *outBottom); /* Can be NULL */ +WIDGET_API void XPGetWidgetExposedGeometry( + XPWidgetID inWidgetID, + int * outLeft, /* Can be NULL */ + int * outTop, /* Can be NULL */ + int * outRight, /* Can be NULL */ + int * outBottom); /* Can be NULL */ /*************************************************************************** * ACCESSING WIDGET DATA ***************************************************************************/ -/* - * - * - */ - /* * XPSetWidgetDescriptor - * - * Every widget has a descriptor, which is a text string. What the text - * string is used for varies from widget to widget; for example, a push - * button's text is its descriptor, a caption shows its descriptor, and a text - * field's descriptor is the text being edited. In other words, the usage for - * the text varies from widget to widget, but this API provides a universal - * and convenient way to get at it. While not all UI widgets need their - * descriptor, many do. + * + * Every widget has a descriptor, which is a text string. What the text string + * is used for varies from widget to widget; for example, a push button's text + * is its descriptor, a caption shows its descriptor, and a text field's + * descriptor is the text being edited. In other words, the usage for the text + * varies from widget to widget, but this API provides a universal and + * convenient way to get at it. While not all UI widgets need their + * descriptor, many do. * */ -WIDGET_API void XPSetWidgetDescriptor(XPWidgetID inWidget, - const char *inDescriptor); +WIDGET_API void XPSetWidgetDescriptor( + XPWidgetID inWidget, + const char * inDescriptor); /* * XPGetWidgetDescriptor - * - * This routine returns the widget's descriptor. Pass in the length of the - * buffer you are going to receive the descriptor in. The descriptor will be - * null terminated for you. This routine returns the length of the actual + * + * This routine returns the widget's descriptor. Pass in the length of the + * buffer you are going to receive the descriptor in. The descriptor will be + * null terminated for you. This routine returns the length of the actual * descriptor; if you pass NULL for outDescriptor, you can get the * descriptor's length without getting its text. If the length of the * descriptor exceeds your buffer length, the buffer will not be null - * terminated (this routine has 'strncpy' semantics). + * terminated (this routine has 'strncpy' semantics). * */ -WIDGET_API int XPGetWidgetDescriptor(XPWidgetID inWidget, - char *outDescriptor, - int inMaxDescLength); +WIDGET_API int XPGetWidgetDescriptor( + XPWidgetID inWidget, + char * outDescriptor, + int inMaxDescLength); + +/* + * XPGetWidgetUnderlyingWindow + * + * Returns the window (from the XPLMDisplay API) that backs your widget + * window. If you have opted in to modern windows, via a call to + * XPLMEnableFeature("XPLM_USE_NATIVE_WIDGET_WINDOWS", 1), you can use the + * returned window ID for display APIs like XPLMSetWindowPositioningMode(), + * allowing you to pop the widget window out into a real OS window, or move it + * into VR. + * + */ +WIDGET_API XPLMWindowID XPGetWidgetUnderlyingWindow( + XPWidgetID inWidget); /* * XPSetWidgetProperty - * - * This function sets a widget's property. Properties are arbitrary values - * associated by a widget by ID. + * + * This function sets a widget's property. Properties are arbitrary values + * associated by a widget by ID. * */ -WIDGET_API void XPSetWidgetProperty(XPWidgetID inWidget, - XPWidgetPropertyID inProperty, - intptr_t inValue); +WIDGET_API void XPSetWidgetProperty( + XPWidgetID inWidget, + XPWidgetPropertyID inProperty, + intptr_t inValue); /* * XPGetWidgetProperty - * + * * This routine returns the value of a widget's property, or 0 if the property - * is not defined. If you need to know whether the property is defined, pass - * a pointer to an int for inExists; the existence of that property will be - * returned in the int. Pass NULL for inExists if you do not need this - * information. + * is not defined. If you need to know whether the property is defined, pass a + * pointer to an int for inExists; the existence of that property will be + * returned in the int. Pass NULL for inExists if you do not need this + * information. * */ -WIDGET_API intptr_t XPGetWidgetProperty(XPWidgetID inWidget, - XPWidgetPropertyID inProperty, - int *inExists); /* Can be NULL */ +WIDGET_API intptr_t XPGetWidgetProperty( + XPWidgetID inWidget, + XPWidgetPropertyID inProperty, + int * inExists); /* Can be NULL */ /*************************************************************************** * KEYBOARD MANAGEMENT ***************************************************************************/ -/* - * - * - */ - /* * XPSetKeyboardFocus - * - * XPSetKeyboardFocus controls which widget will receive keystrokes. Pass the - * Widget ID of the widget to get the keys. Note that if the widget does not - * care about keystrokes, they will go to the parent widget, and if no widget - * cares about them, they go to X-Plane. - * - * If you set the keyboard focus to Widget ID 0, X-Plane gets keyboard focus. - * + * + * Controls which widget will receive keystrokes. Pass the widget ID of the + * widget to get the keys. Note that if the widget does not care about + * keystrokes, they will go to the parent widget, and if no widget cares about + * them, they go to X-Plane. + * + * If you set the keyboard focus to widget ID 0, X-Plane gets keyboard focus. + * * This routine returns the widget ID that ended up with keyboard focus, or 0 - * for x-plane. + * for X-Plane. + * + * Keyboard focus is not changed if the new widget will not accept it. For + * setting to X-Plane, keyboard focus is always accepted. * - * Keyboard focus is not changed if the new widget will not accept it. For - * setting to x-plane, keyboard focus is always accepted. - * - * * */ -WIDGET_API XPWidgetID XPSetKeyboardFocus(XPWidgetID inWidget); +WIDGET_API XPWidgetID XPSetKeyboardFocus( + XPWidgetID inWidget); /* * XPLoseKeyboardFocus - * + * * This causes the specified widget to lose focus; focus is passed to its - * parent, or the next parent that will accept it. This routine does nothing - * if this widget does not have focus. + * parent, or the next parent that will accept it. This routine does nothing + * if this widget does not have focus. * */ -WIDGET_API void XPLoseKeyboardFocus(XPWidgetID inWidget); +WIDGET_API void XPLoseKeyboardFocus( + XPWidgetID inWidget); /* * XPGetWidgetWithFocus - * + * * This routine returns the widget that has keyboard focus, or 0 if X-Plane * has keyboard focus or some other plugin window that does not have widgets - * has focus. + * has focus. * */ WIDGET_API XPWidgetID XPGetWidgetWithFocus(void); @@ -499,40 +499,37 @@ WIDGET_API XPWidgetID XPGetWidgetWithFocus(void); /*************************************************************************** * CREATING CUSTOM WIDGETS ***************************************************************************/ -/* - * - * - */ - /* * XPAddWidgetCallback - * - * This function adds a new widget callback to a widget. This widget callback + * + * This function adds a new widget callback to a widget. This widget callback * supercedes any existing ones and will receive messages first; if it does * not handle messages they will go on to be handled by pre-existing widgets. - * + * * The widget function will remain on the widget for the life of the widget. - * The creation message will be sent to the new callback immediately with the + * The creation message will be sent to the new callback immediately with the * widget ID, and the destruction message will be sent before the other widget * function receives a destruction message. - * - * This provides a way to 'subclass' an existing widget. By providing a - * second hook that only handles certain widget messages, you can customize or - * extend widget behavior. + * + * This provides a way to 'subclass' an existing widget. By providing a second + * hook that only handles certain widget messages, you can customize or extend + * widget behavior. * */ -WIDGET_API void XPAddWidgetCallback(XPWidgetID inWidget, - XPWidgetFunc_t inNewCallback); +WIDGET_API void XPAddWidgetCallback( + XPWidgetID inWidget, + XPWidgetFunc_t inNewCallback); /* * XPGetWidgetClassFunc - * + * * Given a widget class, this function returns the callbacks that power that - * widget class. + * widget class. * */ -WIDGET_API XPWidgetFunc_t XPGetWidgetClassFunc(XPWidgetClass inWidgetClass); +WIDGET_API XPWidgetFunc_t XPGetWidgetClassFunc( + XPWidgetClass inWidgetClass); #ifdef __cplusplus } diff --git a/XPSDK/CHeaders/Wrappers/XPCBroadcaster.cpp b/XPSDK/CHeaders/Wrappers/XPCBroadcaster.cpp index 97c14b9..5fe6218 100644 --- a/XPSDK/CHeaders/Wrappers/XPCBroadcaster.cpp +++ b/XPSDK/CHeaders/Wrappers/XPCBroadcaster.cpp @@ -1,45 +1,56 @@ #include "XPCBroadcaster.h" #include "XPCListener.h" -XPCBroadcaster::XPCBroadcaster() : mIterator(NULL) {} +XPCBroadcaster::XPCBroadcaster() : + mIterator(NULL) +{ +} XPCBroadcaster::~XPCBroadcaster() { - ListenerVector::iterator iter; - mIterator = &iter; - for (iter = mListeners.begin(); iter != mListeners.end(); ++iter) { - (*iter)->BroadcasterRemoved(this); - } + ListenerVector::iterator iter; + mIterator = &iter; + for (iter = mListeners.begin(); iter != mListeners.end(); ++iter) + { + (*iter)->BroadcasterRemoved(this); + } } -void XPCBroadcaster::AddListener(XPCListener *inListener) +void XPCBroadcaster::AddListener( + XPCListener * inListener) { - mListeners.push_back(inListener); - inListener->BroadcasterAdded(this); -} + mListeners.push_back(inListener); + inListener->BroadcasterAdded(this); +} -void XPCBroadcaster::RemoveListener(XPCListener *inListener) +void XPCBroadcaster::RemoveListener( + XPCListener * inListener) { - ListenerVector::iterator iter = - std::find(mListeners.begin(), mListeners.end(), inListener); - if (iter == mListeners.end()) - return; + ListenerVector::iterator iter = std::find + (mListeners.begin(), mListeners.end(), inListener); + if (iter == mListeners.end()) + return; + + if (mIterator != NULL) + { + if (*mIterator >= iter) + (*mIterator)--; + } + + mListeners.erase(iter); + inListener->BroadcasterRemoved(this); +} - if (mIterator != NULL) { - if (*mIterator >= iter) - (*mIterator)--; - } - - mListeners.erase(iter); - inListener->BroadcasterRemoved(this); -} - -void XPCBroadcaster::BroadcastMessage(int inMessage, void *inParam) +void XPCBroadcaster::BroadcastMessage( + int inMessage, + void * inParam) { - ListenerVector::iterator iter; - mIterator = &iter; - for (iter = mListeners.begin(); iter != mListeners.end(); ++iter) { - (*iter)->ListenToMessage(inMessage, inParam); - } - mIterator = NULL; -} + ListenerVector::iterator iter; + mIterator = &iter; + for (iter = mListeners.begin(); iter != mListeners.end(); ++iter) + { + (*iter)->ListenToMessage(inMessage, inParam); + } + mIterator = NULL; +} + diff --git a/XPSDK/CHeaders/Wrappers/XPCBroadcaster.h b/XPSDK/CHeaders/Wrappers/XPCBroadcaster.h index ae4f76f..8f34a05 100644 --- a/XPSDK/CHeaders/Wrappers/XPCBroadcaster.h +++ b/XPSDK/CHeaders/Wrappers/XPCBroadcaster.h @@ -1,31 +1,38 @@ #ifndef _XPCBroadcaster_h_ #define _XPCBroadcaster_h_ -#include #include +#include -class XPCListener; +class XPCListener; -class XPCBroadcaster -{ +class XPCBroadcaster { public: - XPCBroadcaster(); - virtual ~XPCBroadcaster(); - - void AddListener(XPCListener *inListener); - void RemoveListener(XPCListener *inListener); + XPCBroadcaster(); + virtual ~XPCBroadcaster(); + + void AddListener( + XPCListener * inListener); + void RemoveListener( + XPCListener * inListener); + protected: - void BroadcastMessage(int inMessage, void *inParam = 0); + + void BroadcastMessage( + int inMessage, + void * inParam=0); private: - typedef std::vector ListenerVector; - ListenerVector mListeners; + typedef std::vector ListenerVector; + + ListenerVector mListeners; - // Reentrancy support + // Reentrancy support + + ListenerVector::iterator * mIterator; - ListenerVector::iterator *mIterator; }; #endif \ No newline at end of file diff --git a/XPSDK/CHeaders/Wrappers/XPCDisplay.cpp b/XPSDK/CHeaders/Wrappers/XPCDisplay.cpp index ce39eb5..fc996ca 100644 --- a/XPSDK/CHeaders/Wrappers/XPCDisplay.cpp +++ b/XPSDK/CHeaders/Wrappers/XPCDisplay.cpp @@ -1,107 +1,104 @@ #include "XPCDisplay.h" -XPCKeySniffer::XPCKeySniffer(int inBeforeWindows) - : mBeforeWindows(inBeforeWindows) +XPCKeySniffer::XPCKeySniffer(int inBeforeWindows) : mBeforeWindows(inBeforeWindows) { - XPLMRegisterKeySniffer(KeySnifferCB, - mBeforeWindows, - reinterpret_cast(this)); -} + XPLMRegisterKeySniffer(KeySnifferCB, mBeforeWindows, reinterpret_cast(this)); +} XPCKeySniffer::~XPCKeySniffer() { - XPLMUnregisterKeySniffer(KeySnifferCB, - mBeforeWindows, - reinterpret_cast(this)); + XPLMUnregisterKeySniffer(KeySnifferCB, mBeforeWindows, reinterpret_cast(this)); } -int XPCKeySniffer::KeySnifferCB(char inCharKey, - XPLMKeyFlags inFlags, - char inVirtualKey, - void *inRefCon) +int XPCKeySniffer::KeySnifferCB( + char inCharKey, + XPLMKeyFlags inFlags, + char inVirtualKey, + void * inRefCon) { - XPCKeySniffer *me = reinterpret_cast(inRefCon); - return me->HandleKeyStroke(inCharKey, inFlags, inVirtualKey); -} + XPCKeySniffer * me = reinterpret_cast(inRefCon); + return me->HandleKeyStroke(inCharKey, inFlags, inVirtualKey); +} -XPCWindow::XPCWindow(int inLeft, - int inTop, - int inRight, - int inBottom, - int inIsVisible) +XPCWindow::XPCWindow( + int inLeft, + int inTop, + int inRight, + int inBottom, + int inIsVisible) { - mWindow = XPLMCreateWindow(inLeft, - inTop, - inRight, - inBottom, - inIsVisible, - DrawCB, - HandleKeyCB, - MouseClickCB, - reinterpret_cast(this)); + mWindow = XPLMCreateWindow(inLeft, inTop, inRight, inBottom, inIsVisible, + DrawCB, HandleKeyCB, MouseClickCB, + reinterpret_cast(this)); } -XPCWindow::~XPCWindow() { XPLMDestroyWindow(mWindow); } - -void XPCWindow::GetWindowGeometry(int *outLeft, - int *outTop, - int *outRight, - int *outBottom) +XPCWindow::~XPCWindow() { - XPLMGetWindowGeometry(mWindow, outLeft, outTop, outRight, outBottom); + XPLMDestroyWindow(mWindow); } -void XPCWindow::SetWindowGeometry(int inLeft, - int inTop, - int inRight, - int inBottom) +void XPCWindow::GetWindowGeometry( + int * outLeft, + int * outTop, + int * outRight, + int * outBottom) { - XPLMSetWindowGeometry(mWindow, inLeft, inTop, inRight, inBottom); + XPLMGetWindowGeometry(mWindow, outLeft, outTop, outRight, outBottom); } - -int XPCWindow::GetWindowIsVisible(void) + +void XPCWindow::SetWindowGeometry( + int inLeft, + int inTop, + int inRight, + int inBottom) { - return XPLMGetWindowIsVisible(mWindow); + XPLMSetWindowGeometry(mWindow, inLeft, inTop, inRight, inBottom); } -void XPCWindow::SetWindowIsVisible(int inIsVisible) +int XPCWindow::GetWindowIsVisible(void) { - XPLMSetWindowIsVisible(mWindow, inIsVisible); + return XPLMGetWindowIsVisible(mWindow); } -void XPCWindow::TakeKeyboardFocus(void) { XPLMTakeKeyboardFocus(mWindow); } - -void XPCWindow::BringWindowToFront(void) { XPLMBringWindowToFront(mWindow); } - -int XPCWindow::IsWindowInFront(void) { return XPLMIsWindowInFront(mWindow); } - -void XPCWindow::DrawCB(XPLMWindowID inWindowID, void *inRefcon) +void XPCWindow::SetWindowIsVisible( + int inIsVisible) { - XPCWindow *me = reinterpret_cast(inRefcon); - me->DoDraw(); + XPLMSetWindowIsVisible(mWindow, inIsVisible); +} + +void XPCWindow::TakeKeyboardFocus(void) +{ + XPLMTakeKeyboardFocus(mWindow); } -void XPCWindow::HandleKeyCB(XPLMWindowID inWindowID, - char inKey, - XPLMKeyFlags inFlags, - char inVirtualKey, - void *inRefcon, - int losingFocus) +void XPCWindow::BringWindowToFront(void) { - XPCWindow *me = reinterpret_cast(inRefcon); - if (losingFocus) - me->LoseFocus(); - else - me->HandleKey(inKey, inFlags, inVirtualKey); + XPLMBringWindowToFront(mWindow); } -int XPCWindow::MouseClickCB(XPLMWindowID inWindowID, - int x, - int y, - XPLMMouseStatus inMouse, - void *inRefcon) +int XPCWindow::IsWindowInFront(void) { - XPCWindow *me = reinterpret_cast(inRefcon); - return me->HandleClick(x, y, inMouse); + return XPLMIsWindowInFront(mWindow); +} + +void XPCWindow::DrawCB(XPLMWindowID inWindowID, void * inRefcon) +{ + XPCWindow * me = reinterpret_cast(inRefcon); + me->DoDraw(); +} + +void XPCWindow::HandleKeyCB(XPLMWindowID inWindowID, char inKey, XPLMKeyFlags inFlags, char inVirtualKey, void * inRefcon, int losingFocus) +{ + XPCWindow * me = reinterpret_cast(inRefcon); + if (losingFocus) + me->LoseFocus(); + else + me->HandleKey(inKey, inFlags, inVirtualKey); +} + +int XPCWindow::MouseClickCB(XPLMWindowID inWindowID, int x, int y, XPLMMouseStatus inMouse, void * inRefcon) +{ + XPCWindow * me = reinterpret_cast(inRefcon); + return me->HandleClick(x, y, inMouse); } diff --git a/XPSDK/CHeaders/Wrappers/XPCDisplay.h b/XPSDK/CHeaders/Wrappers/XPCDisplay.h index 13d1dc1..2465928 100644 --- a/XPSDK/CHeaders/Wrappers/XPCDisplay.h +++ b/XPSDK/CHeaders/Wrappers/XPCDisplay.h @@ -3,68 +3,71 @@ #include "XPLMDisplay.h" -class XPCKeySniffer -{ +class XPCKeySniffer { public: - XPCKeySniffer(int inBeforeWindows); - virtual ~XPCKeySniffer(); - virtual int HandleKeyStroke(char inCharKey, - XPLMKeyFlags inFlags, - char inVirtualKey) = 0; + XPCKeySniffer(int inBeforeWindows); + virtual ~XPCKeySniffer(); + + virtual int HandleKeyStroke( + char inCharKey, + XPLMKeyFlags inFlags, + char inVirtualKey)=0; private: - int mBeforeWindows; - static int KeySnifferCB(char inCharKey, - XPLMKeyFlags inFlags, - char inVirtualKey, - void *inRefCon); + int mBeforeWindows; + + static int KeySnifferCB( + char inCharKey, + XPLMKeyFlags inFlags, + char inVirtualKey, + void * inRefCon); }; -class XPCWindow -{ + +class XPCWindow { public: - XPCWindow(int inLeft, - int inTop, - int inRight, - int inBottom, - int inIsVisible); - virtual ~XPCWindow(); - virtual void DoDraw(void) = 0; - virtual void - HandleKey(char inKey, XPLMKeyFlags inFlags, char inVirtualKey) = 0; - virtual void LoseFocus(void) = 0; - virtual int HandleClick(int x, int y, XPLMMouseStatus inMouse) = 0; - - void GetWindowGeometry(int *outLeft, - int *outTop, - int *outRight, - int *outBottom); - void SetWindowGeometry(int inLeft, int inTop, int inRight, int inBottom); - int GetWindowIsVisible(void); - void SetWindowIsVisible(int inIsVisible); - void TakeKeyboardFocus(void); - void BringWindowToFront(void); - int IsWindowInFront(void); + XPCWindow( + int inLeft, + int inTop, + int inRight, + int inBottom, + int inIsVisible); + virtual ~XPCWindow(); + virtual void DoDraw(void)=0; + virtual void HandleKey(char inKey, XPLMKeyFlags inFlags, char inVirtualKey)=0; + virtual void LoseFocus(void)=0; + virtual int HandleClick(int x, int y, XPLMMouseStatus inMouse)=0; + + void GetWindowGeometry( + int * outLeft, + int * outTop, + int * outRight, + int * outBottom); + void SetWindowGeometry( + int inLeft, + int inTop, + int inRight, + int inBottom); + int GetWindowIsVisible(void); + void SetWindowIsVisible( + int inIsVisible); + void TakeKeyboardFocus(void); + void BringWindowToFront(void); + int IsWindowInFront(void); + private: - XPLMWindowID mWindow; - static void DrawCB(XPLMWindowID inWindowID, void *inRefcon); - static void HandleKeyCB(XPLMWindowID inWindowID, - char inKey, - XPLMKeyFlags inFlags, - char inVirtualKey, - void *inRefcon, - int losingFocus); - static int MouseClickCB(XPLMWindowID inWindowID, - int x, - int y, - XPLMMouseStatus inMouse, - void *inRefcon); + XPLMWindowID mWindow; + + static void DrawCB(XPLMWindowID inWindowID, void * inRefcon); + static void HandleKeyCB(XPLMWindowID inWindowID, char inKey, XPLMKeyFlags inFlags, char inVirtualKey, void * inRefcon, int losingFocus); + static int MouseClickCB(XPLMWindowID inWindowID, int x, int y, XPLMMouseStatus inMouse, void * inRefcon); + }; #endif \ No newline at end of file diff --git a/XPSDK/CHeaders/Wrappers/XPCListener.cpp b/XPSDK/CHeaders/Wrappers/XPCListener.cpp index 467b391..b4c77aa 100644 --- a/XPSDK/CHeaders/Wrappers/XPCListener.cpp +++ b/XPSDK/CHeaders/Wrappers/XPCListener.cpp @@ -1,23 +1,27 @@ #include "XPCListener.h" #include "XPCBroadcaster.h" -XPCListener::XPCListener() {} +XPCListener::XPCListener() +{ +} XPCListener::~XPCListener() { - while (!mBroadcasters.empty()) - mBroadcasters.front()->RemoveListener(this); + while (!mBroadcasters.empty()) + mBroadcasters.front()->RemoveListener(this); } - -void XPCListener::BroadcasterAdded(XPCBroadcaster *inBroadcaster) + +void XPCListener::BroadcasterAdded( + XPCBroadcaster * inBroadcaster) { - mBroadcasters.push_back(inBroadcaster); -} + mBroadcasters.push_back(inBroadcaster); +} -void XPCListener::BroadcasterRemoved(XPCBroadcaster *inBroadcaster) +void XPCListener::BroadcasterRemoved( + XPCBroadcaster * inBroadcaster) { - BroadcastVector::iterator iter = - std::find(mBroadcasters.begin(), mBroadcasters.end(), inBroadcaster); - if (iter != mBroadcasters.end()) - mBroadcasters.erase(iter); -} + BroadcastVector::iterator iter = std::find(mBroadcasters.begin(), + mBroadcasters.end(), inBroadcaster); + if (iter != mBroadcasters.end()) + mBroadcasters.erase(iter); +} diff --git a/XPSDK/CHeaders/Wrappers/XPCListener.h b/XPSDK/CHeaders/Wrappers/XPCListener.h index bc20826..dbdd2a0 100644 --- a/XPSDK/CHeaders/Wrappers/XPCListener.h +++ b/XPSDK/CHeaders/Wrappers/XPCListener.h @@ -1,30 +1,36 @@ #ifndef _XPCListener_h_ #define _XPCListener_h_ -#include #include +#include -class XPCBroadcaster; +class XPCBroadcaster; -class XPCListener -{ +class XPCListener { public: - XPCListener(); - virtual ~XPCListener(); - - virtual void ListenToMessage(int inMessage, void *inParam) = 0; + XPCListener(); + virtual ~XPCListener(); + + virtual void ListenToMessage( + int inMessage, + void * inParam)=0; + private: - typedef std::vector BroadcastVector; - BroadcastVector mBroadcasters; + typedef std::vector BroadcastVector; + + BroadcastVector mBroadcasters; - friend class XPCBroadcaster; + friend class XPCBroadcaster; + + void BroadcasterAdded( + XPCBroadcaster * inBroadcaster); - void BroadcasterAdded(XPCBroadcaster *inBroadcaster); - - void BroadcasterRemoved(XPCBroadcaster *inBroadcaster); -}; + void BroadcasterRemoved( + XPCBroadcaster * inBroadcaster); + +}; #endif \ No newline at end of file diff --git a/XPSDK/CHeaders/Wrappers/XPCProcessing.cpp b/XPSDK/CHeaders/Wrappers/XPCProcessing.cpp index 5e9552e..352c05f 100644 --- a/XPSDK/CHeaders/Wrappers/XPCProcessing.cpp +++ b/XPSDK/CHeaders/Wrappers/XPCProcessing.cpp @@ -1,60 +1,52 @@ #include "XPCProcessing.h" #include "XPLMUtilities.h" -XPCProcess::XPCProcess() : mInCallback(false), mCallbackTime(0) +XPCProcess::XPCProcess() : + mInCallback(false), + mCallbackTime(0) { - XPLMRegisterFlightLoopCallback(FlightLoopCB, - 0, - reinterpret_cast(this)); + XPLMRegisterFlightLoopCallback(FlightLoopCB, 0, reinterpret_cast(this)); } XPCProcess::~XPCProcess() { - XPLMUnregisterFlightLoopCallback(FlightLoopCB, - reinterpret_cast(this)); + XPLMUnregisterFlightLoopCallback(FlightLoopCB, reinterpret_cast(this)); +} + +void XPCProcess::StartProcessTime(float inSeconds) +{ + mCallbackTime = inSeconds; + if (!mInCallback) + XPLMSetFlightLoopCallbackInterval( + FlightLoopCB, mCallbackTime, 1/*relative to now*/, reinterpret_cast(this)); } -void XPCProcess::StartProcessTime(float inSeconds) +void XPCProcess::StartProcessCycles(int inCycles) { - mCallbackTime = inSeconds; - if (!mInCallback) - XPLMSetFlightLoopCallbackInterval(FlightLoopCB, - mCallbackTime, - 1 /*relative to now*/, - reinterpret_cast(this)); + mCallbackTime = -inCycles; + if (!mInCallback) + XPLMSetFlightLoopCallbackInterval( + FlightLoopCB, mCallbackTime, 1/*relative to now*/, reinterpret_cast(this)); } -void XPCProcess::StartProcessCycles(int inCycles) +void XPCProcess::StopProcess(void) { - mCallbackTime = -inCycles; - if (!mInCallback) - XPLMSetFlightLoopCallbackInterval(FlightLoopCB, - mCallbackTime, - 1 /*relative to now*/, - reinterpret_cast(this)); -} - -void XPCProcess::StopProcess(void) -{ - mCallbackTime = 0; - if (!mInCallback) - XPLMSetFlightLoopCallbackInterval(FlightLoopCB, - mCallbackTime, - 1 /*relative to now*/, - reinterpret_cast(this)); + mCallbackTime = 0; + if (!mInCallback) + XPLMSetFlightLoopCallbackInterval( + FlightLoopCB, mCallbackTime, 1/*relative to now*/, reinterpret_cast(this)); } -float XPCProcess::FlightLoopCB(float inElapsedSinceLastCall, - float inElapsedTimeSinceLastFlightLoop, - int inCounter, - void *inRefcon) +float XPCProcess::FlightLoopCB( + float inElapsedSinceLastCall, + float inElapsedTimeSinceLastFlightLoop, + int inCounter, + void * inRefcon) { - XPCProcess *me = reinterpret_cast(inRefcon); - me->mInCallback = true; - me->DoProcessing(inElapsedSinceLastCall, - inElapsedTimeSinceLastFlightLoop, - inCounter); - me->mInCallback = false; - return me->mCallbackTime; + XPCProcess * me = reinterpret_cast(inRefcon); + me->mInCallback = true; + me->DoProcessing(inElapsedSinceLastCall, inElapsedTimeSinceLastFlightLoop, inCounter); + me->mInCallback = false; + return me->mCallbackTime; } \ No newline at end of file diff --git a/XPSDK/CHeaders/Wrappers/XPCProcessing.h b/XPSDK/CHeaders/Wrappers/XPCProcessing.h index e963d49..cd735e5 100644 --- a/XPSDK/CHeaders/Wrappers/XPCProcessing.h +++ b/XPSDK/CHeaders/Wrappers/XPCProcessing.h @@ -3,31 +3,35 @@ #include "XPLMProcessing.h" -class XPCProcess -{ +class XPCProcess { public: - XPCProcess(); - virtual ~XPCProcess(); - void StartProcessTime(float inSeconds); - void StartProcessCycles(int inCycles); - void StopProcess(void); + XPCProcess(); + virtual ~XPCProcess(); + + void StartProcessTime(float inSeconds); + void StartProcessCycles(int inCycles); + void StopProcess(void); - virtual void DoProcessing(float inElapsedSinceLastCall, - float inElapsedTimeSinceLastFlightLoop, - int inCounter) = 0; + virtual void DoProcessing( + float inElapsedSinceLastCall, + float inElapsedTimeSinceLastFlightLoop, + int inCounter)=0; private: - static float FlightLoopCB(float inElapsedSinceLastCall, - float inElapsedTimeSinceLastFlightLoop, - int inCounter, - void *inRefcon); - bool mInCallback; - float mCallbackTime; + static float FlightLoopCB( + float inElapsedSinceLastCall, + float inElapsedTimeSinceLastFlightLoop, + int inCounter, + void * inRefcon); + + bool mInCallback; + float mCallbackTime; + + XPCProcess(const XPCProcess&); + XPCProcess& operator=(const XPCProcess&); - XPCProcess(const XPCProcess &); - XPCProcess &operator=(const XPCProcess &); }; #endif diff --git a/XPSDK/CHeaders/Wrappers/XPCWidget.cpp b/XPSDK/CHeaders/Wrappers/XPCWidget.cpp index be1e6a8..8ef8aa3 100644 --- a/XPSDK/CHeaders/Wrappers/XPCWidget.cpp +++ b/XPSDK/CHeaders/Wrappers/XPCWidget.cpp @@ -1,111 +1,123 @@ #include "XPCWidget.h" -XPCWidget::XPCWidget(int inLeft, - int inTop, - int inRight, - int inBottom, - bool inVisible, - const char *inDescriptor, - bool inIsRoot, - XPWidgetID inParent, - XPWidgetClass inClass) - : mWidget(NULL), mOwnsChildren(false), mOwnsWidget(true) +XPCWidget::XPCWidget( + int inLeft, + int inTop, + int inRight, + int inBottom, + bool inVisible, + const char * inDescriptor, + bool inIsRoot, + XPWidgetID inParent, + XPWidgetClass inClass) : + mWidget(NULL), + mOwnsChildren(false), + mOwnsWidget(true) { - mWidget = XPCreateWidget(inLeft, - inTop, - inRight, - inBottom, - inVisible ? 1 : 0, - inDescriptor, - inIsRoot ? 1 : 0, - inIsRoot ? NULL : inParent, - inClass); + mWidget = XPCreateWidget( + inLeft, inTop, inRight, inBottom, + inVisible ? 1 : 0, + inDescriptor, + inIsRoot ? 1 : 0, + inIsRoot ? NULL : inParent, + inClass); - XPSetWidgetProperty(mWidget, - xpProperty_Object, - reinterpret_cast(this)); - XPAddWidgetCallback(mWidget, WidgetCallback); -} - -XPCWidget::XPCWidget(XPWidgetID inWidget, bool inOwnsWidget) - : mWidget(inWidget), mOwnsChildren(false), mOwnsWidget(inOwnsWidget) + XPSetWidgetProperty(mWidget, xpProperty_Object, reinterpret_cast(this)); + XPAddWidgetCallback(mWidget, WidgetCallback); +} + +XPCWidget::XPCWidget( + XPWidgetID inWidget, + bool inOwnsWidget) : + mWidget(inWidget), + mOwnsChildren(false), + mOwnsWidget(inOwnsWidget) { - XPSetWidgetProperty(mWidget, - xpProperty_Object, - reinterpret_cast(this)); - XPAddWidgetCallback(mWidget, WidgetCallback); + XPSetWidgetProperty(mWidget, xpProperty_Object, reinterpret_cast(this)); + XPAddWidgetCallback(mWidget, WidgetCallback); } XPCWidget::~XPCWidget() { - if (mOwnsWidget) - XPDestroyWidget(mWidget, mOwnsChildren ? 1 : 0); + if (mOwnsWidget) + XPDestroyWidget(mWidget, mOwnsChildren ? 1 : 0); } - -void XPCWidget::SetOwnsWidget(bool inOwnsWidget) { mOwnsWidget = inOwnsWidget; } - -void XPCWidget::SetOwnsChildren(bool inOwnsChildren) + +void XPCWidget::SetOwnsWidget( + bool inOwnsWidget) { - mOwnsChildren = inOwnsChildren; + mOwnsWidget = inOwnsWidget; } -XPCWidget::operator XPWidgetID() const { return mWidget; } - -XPWidgetID XPCWidget::Get(void) const { return mWidget; } - -void XPCWidget::AddAttachment(XPCWidgetAttachment *inAttachment, - bool inOwnsAttachment, - bool inPrefilter) +void XPCWidget::SetOwnsChildren( + bool inOwnsChildren) { - if (inPrefilter) { - mAttachments.insert(mAttachments.begin(), - AttachmentInfo(inAttachment, inOwnsAttachment)); - } else { - mAttachments.push_back(AttachmentInfo(inAttachment, inOwnsAttachment)); - } -} + mOwnsChildren = inOwnsChildren; +} -void XPCWidget::RemoveAttachment(XPCWidgetAttachment *inAttachment) +XPCWidget::operator XPWidgetID () const { - for (AttachmentVector::iterator iter = mAttachments.begin(); - iter != mAttachments.end(); - ++iter) { - if (iter->first == inAttachment) { - mAttachments.erase(iter); - return; - } - } + return mWidget; } -int XPCWidget::HandleWidgetMessage(XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2) +XPWidgetID XPCWidget::Get(void) const { - return 0; + return mWidget; } -int XPCWidget::WidgetCallback(XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2) +void XPCWidget::AddAttachment( + XPCWidgetAttachment * inAttachment, + bool inOwnsAttachment, + bool inPrefilter) { - XPCWidget *me = reinterpret_cast( - XPGetWidgetProperty(inWidget, xpProperty_Object, NULL)); - if (me == NULL) - return 0; + if (inPrefilter) + { + mAttachments.insert(mAttachments.begin(), AttachmentInfo(inAttachment, inOwnsAttachment)); + } else { + mAttachments.push_back(AttachmentInfo(inAttachment, inOwnsAttachment)); + } +} - for (AttachmentVector::iterator iter = me->mAttachments.begin(); - iter != me->mAttachments.end(); - ++iter) { - int result = iter->first->HandleWidgetMessage(me, - inMessage, - inWidget, - inParam1, - inParam2); - if (result != 0) - return result; - } +void XPCWidget::RemoveAttachment( + XPCWidgetAttachment * inAttachment) +{ + for (AttachmentVector::iterator iter = mAttachments.begin(); + iter != mAttachments.end(); ++iter) + { + if (iter->first == inAttachment) + { + mAttachments.erase(iter); + return; + } + } +} - return me->HandleWidgetMessage(inMessage, inWidget, inParam1, inParam2); -} +int XPCWidget::HandleWidgetMessage( + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + return 0; +} + +int XPCWidget::WidgetCallback( + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + XPCWidget * me = reinterpret_cast(XPGetWidgetProperty(inWidget, xpProperty_Object, NULL)); + if (me == NULL) + return 0; + + for (AttachmentVector::iterator iter = me->mAttachments.begin(); iter != + me->mAttachments.end(); ++iter) + { + int result = iter->first->HandleWidgetMessage(me, inMessage, inWidget, inParam1, inParam2); + if (result != 0) + return result; + } + + return me->HandleWidgetMessage(inMessage, inWidget, inParam1, inParam2); +} diff --git a/XPSDK/CHeaders/Wrappers/XPCWidget.h b/XPSDK/CHeaders/Wrappers/XPCWidget.h index 584a5ee..788b56a 100644 --- a/XPSDK/CHeaders/Wrappers/XPCWidget.h +++ b/XPSDK/CHeaders/Wrappers/XPCWidget.h @@ -1,71 +1,84 @@ #ifndef _XPCWidget_h_ #define _XPCWidget_h_ -#include "XPWidgets.h" -#include #include +#include +#include "XPWidgets.h" -class XPCWidget; +class XPCWidget; -class XPCWidgetAttachment -{ +class XPCWidgetAttachment { public: - virtual int HandleWidgetMessage(XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2) = 0; + + virtual int HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2)=0; + }; -class XPCWidget -{ +class XPCWidget { public: - XPCWidget(int inLeft, - int inTop, - int inRight, - int inBottom, - bool inVisible, - const char *inDescriptor, - bool inIsRoot, - XPWidgetID inParent, - XPWidgetClass inClass); - XPCWidget(XPWidgetID inWidget, bool inOwnsWidget); - virtual ~XPCWidget(); - void SetOwnsWidget(bool inOwnsWidget); - void SetOwnsChildren(bool inOwnsChildren); + XPCWidget( + int inLeft, + int inTop, + int inRight, + int inBottom, + bool inVisible, + const char * inDescriptor, + bool inIsRoot, + XPWidgetID inParent, + XPWidgetClass inClass); + XPCWidget( + XPWidgetID inWidget, + bool inOwnsWidget); + virtual ~XPCWidget(); + + void SetOwnsWidget( + bool inOwnsWidget); + void SetOwnsChildren( + bool inOwnsChildren); - operator XPWidgetID() const; + operator XPWidgetID () const; + + XPWidgetID Get(void) const; - XPWidgetID Get(void) const; - - void AddAttachment(XPCWidgetAttachment *inAttachment, - bool inOwnsAttachment, - bool inPrefilter); - void RemoveAttachment(XPCWidgetAttachment *inAttachment); - - virtual int HandleWidgetMessage(XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2); + void AddAttachment( + XPCWidgetAttachment * inAttachment, + bool inOwnsAttachment, + bool inPrefilter); + void RemoveAttachment( + XPCWidgetAttachment * inAttachment); + virtual int HandleWidgetMessage( + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + private: - static int WidgetCallback(XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2); - typedef std::pair AttachmentInfo; - typedef std::vector AttachmentVector; + static int WidgetCallback( + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + + typedef std::pair AttachmentInfo; + typedef std::vector AttachmentVector; + + AttachmentVector mAttachments; + XPWidgetID mWidget; + bool mOwnsChildren; + bool mOwnsWidget; + + XPCWidget(); + XPCWidget(const XPCWidget&); + XPCWidget& operator=(const XPCWidget&); - AttachmentVector mAttachments; - XPWidgetID mWidget; - bool mOwnsChildren; - bool mOwnsWidget; - - XPCWidget(); - XPCWidget(const XPCWidget &); - XPCWidget &operator=(const XPCWidget &); }; #endif \ No newline at end of file diff --git a/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.cpp b/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.cpp index 9d3a03d..d87f105 100644 --- a/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.cpp +++ b/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.cpp @@ -2,234 +2,266 @@ #include "XPStandardWidgets.h" #include "XPWidgetUtils.h" -static void XPCGetOrderedSubWidgets(XPWidgetID inWidget, - std::vector &outChildren); +static void XPCGetOrderedSubWidgets( + XPWidgetID inWidget, + std::vector& outChildren); -XPCKeyFilterAttachment::XPCKeyFilterAttachment(const char *inValidKeys, - const char *outValidKeys) - : mInput(inValidKeys), mOutput(outValidKeys) +XPCKeyFilterAttachment::XPCKeyFilterAttachment( + const char * inValidKeys, + const char * outValidKeys) : + mInput(inValidKeys), + mOutput(outValidKeys) +{ +} + +XPCKeyFilterAttachment::~XPCKeyFilterAttachment() { } -XPCKeyFilterAttachment::~XPCKeyFilterAttachment() {} - -int XPCKeyFilterAttachment::HandleWidgetMessage(XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2) +int XPCKeyFilterAttachment::HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) { - if (inMessage == xpMsg_KeyPress) { - char &theKey = KEY_CHAR(inParam1); - std::string::size_type pos = mInput.find(theKey); - if (pos == std::string::npos) - return 1; // Not found; eat the key! - else { - theKey = mOutput[pos]; - return 0; - } // Let it live. - } - return 0; -} + if (inMessage == xpMsg_KeyPress) + { + char& theKey = KEY_CHAR(inParam1); + std::string::size_type pos = mInput.find(theKey); + if (pos == std::string::npos) + return 1; // Not found; eat the key! + else { + theKey = mOutput[pos]; + return 0; + } // Let it live. + } + return 0; +} -XPCKeyMessageAttachment::XPCKeyMessageAttachment(char inKey, - int inMessage, - void *inParam, - bool inConsume, - bool inVkey, - XPCListener *inListener) - : mKey(inKey), mMsg(inMessage), mParam(inParam), mConsume(inConsume), - mVkey(inVkey) +XPCKeyMessageAttachment::XPCKeyMessageAttachment( + char inKey, + int inMessage, + void * inParam, + bool inConsume, + bool inVkey, + XPCListener * inListener) : + mKey(inKey), mMsg(inMessage), mParam(inParam), mConsume(inConsume), + mVkey(inVkey) { - if (inListener != NULL) - this->AddListener(inListener); -} + if (inListener != NULL) + this->AddListener(inListener); +} -XPCKeyMessageAttachment::~XPCKeyMessageAttachment() {} - -int XPCKeyMessageAttachment::HandleWidgetMessage(XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2) +XPCKeyMessageAttachment::~XPCKeyMessageAttachment() { - if (inMessage == xpMsg_KeyPress) { - char theKey = mVkey ? KEY_VKEY(inParam1) : KEY_CHAR(inParam1); - if (theKey != mKey) - return 0; - if (!(KEY_FLAGS(inParam1) & xplm_DownFlag)) - return 0; - - BroadcastMessage(mMsg, mParam); - return mConsume ? 1 : 0; - } - return 0; } + +int XPCKeyMessageAttachment::HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + if (inMessage == xpMsg_KeyPress) + { + char theKey = mVkey ? KEY_VKEY(inParam1) : KEY_CHAR(inParam1); + if (theKey != mKey) + return 0; + if (!(KEY_FLAGS(inParam1) & xplm_DownFlag)) + return 0; + + BroadcastMessage(mMsg, mParam); + return mConsume ? 1 : 0; + } + return 0; +} XPCPushButtonMessageAttachment::XPCPushButtonMessageAttachment( - XPWidgetID inWidget, - int inMessage, - void *inParam, - XPCListener *inListener) - : mMsg(inMessage), mParam(inParam), mWidget(inWidget) + XPWidgetID inWidget, + int inMessage, + void * inParam, + XPCListener * inListener) : + mMsg(inMessage), mParam(inParam), mWidget(inWidget) { - if (inListener != NULL) - this->AddListener(inListener); + if (inListener != NULL) + this->AddListener(inListener); } -XPCPushButtonMessageAttachment::~XPCPushButtonMessageAttachment() {} - -int XPCPushButtonMessageAttachment::HandleWidgetMessage( - XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2) +XPCPushButtonMessageAttachment::~XPCPushButtonMessageAttachment() { - if ((inMessage == xpMsg_PushButtonPressed) && - ((XPWidgetID)inParam1 == mWidget)) { - BroadcastMessage(mMsg, mParam); - return 1; - } - - if ((inMessage == xpMsg_ButtonStateChanged) && - ((XPWidgetID)inParam1 == mWidget)) { - BroadcastMessage(mMsg, mParam); - return 1; - } - return 0; } -XPCSliderMessageAttachment::XPCSliderMessageAttachment(XPWidgetID inWidget, - int inMessage, - void *inParam, - XPCListener *inListener) - : mMsg(inMessage), mParam(inParam), mWidget(inWidget) +int XPCPushButtonMessageAttachment::HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) { - if (inListener != NULL) - this->AddListener(inListener); + if ((inMessage == xpMsg_PushButtonPressed) && ((XPWidgetID) inParam1 == mWidget)) + { + BroadcastMessage(mMsg, mParam); + return 1; + } + + if ((inMessage == xpMsg_ButtonStateChanged) && ((XPWidgetID) inParam1 == mWidget)) + { + BroadcastMessage(mMsg, mParam); + return 1; + } + return 0; +} + +XPCSliderMessageAttachment::XPCSliderMessageAttachment( + XPWidgetID inWidget, + int inMessage, + void * inParam, + XPCListener * inListener) : + mMsg(inMessage), mParam(inParam), mWidget(inWidget) +{ + if (inListener != NULL) + this->AddListener(inListener); } -XPCSliderMessageAttachment::~XPCSliderMessageAttachment() {} - -int XPCSliderMessageAttachment::HandleWidgetMessage(XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2) +XPCSliderMessageAttachment::~XPCSliderMessageAttachment() { - if ((inMessage == xpMsg_ScrollBarSliderPositionChanged) && - ((XPWidgetID)inParam1 == mWidget)) { - BroadcastMessage(mMsg, mParam); - return 1; - } - - return 0; } +int XPCSliderMessageAttachment::HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + if ((inMessage == xpMsg_ScrollBarSliderPositionChanged) && ((XPWidgetID) inParam1 == mWidget)) + { + BroadcastMessage(mMsg, mParam); + return 1; + } + + return 0; +} + XPCCloseButtonMessageAttachment::XPCCloseButtonMessageAttachment( - XPWidgetID inWidget, - int inMessage, - void *inParam, - XPCListener *inListener) - : mMsg(inMessage), mParam(inParam), mWidget(inWidget) + XPWidgetID inWidget, + int inMessage, + void * inParam, + XPCListener * inListener) : + mMsg(inMessage), mParam(inParam), mWidget(inWidget) { - if (inListener != NULL) - this->AddListener(inListener); + if (inListener != NULL) + this->AddListener(inListener); } -XPCCloseButtonMessageAttachment::~XPCCloseButtonMessageAttachment() {} - -int XPCCloseButtonMessageAttachment::HandleWidgetMessage( - XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2) +XPCCloseButtonMessageAttachment::~XPCCloseButtonMessageAttachment() { - if ((inMessage == xpMessage_CloseButtonPushed) && - ((XPWidgetID)inParam1 == mWidget)) { - BroadcastMessage(mMsg, mParam); - return 1; - } - - return 0; } -XPCTabGroupAttachment::XPCTabGroupAttachment() {} - -XPCTabGroupAttachment::~XPCTabGroupAttachment() {} - -int XPCTabGroupAttachment::HandleWidgetMessage(XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2) +int XPCCloseButtonMessageAttachment::HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) { - if ((inMessage == xpMsg_KeyPress) && (KEY_CHAR(inParam1) == XPLM_KEY_TAB) && - ((KEY_FLAGS(inParam1) & xplm_UpFlag) == 0)) { - bool backwards = (KEY_FLAGS(inParam1) & xplm_ShiftFlag) != 0; - std::vector widgets; - XPCGetOrderedSubWidgets(inWidget, widgets); - int n, index = 0; - XPWidgetID focusWidget = XPGetWidgetWithFocus(); - std::vector::iterator iter = - std::find(widgets.begin(), widgets.end(), focusWidget); - if (iter != widgets.end()) { - index = std::distance(widgets.begin(), iter); - if (backwards) - index--; - else - index++; - if (index < 0) - index = widgets.size() - 1; - if (index >= widgets.size()) - index = 0; - } + if ((inMessage == xpMessage_CloseButtonPushed) && ((XPWidgetID) inParam1 == mWidget)) + { + BroadcastMessage(mMsg, mParam); + return 1; + } - if (backwards) { - for (n = index; n >= 0; --n) { - if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) - if (XPSetKeyboardFocus(widgets[n]) != NULL) - return 1; - } - for (n = widgets.size() - 1; n > index; --n) { - if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) - if (XPSetKeyboardFocus(widgets[n]) != NULL) - return 1; - } - } else { - for (n = index; n < widgets.size(); ++n) { - if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) - if (XPSetKeyboardFocus(widgets[n]) != NULL) - return 1; - } - for (n = 0; n < index; ++n) { - if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) - if (XPSetKeyboardFocus(widgets[n]) != NULL) - return 1; - } - } - } - return 0; + return 0; +} + +XPCTabGroupAttachment::XPCTabGroupAttachment() +{ } - -static void XPCGetOrderedSubWidgets(XPWidgetID inWidget, - std::vector &outChildren) +XPCTabGroupAttachment::~XPCTabGroupAttachment() { - outChildren.clear(); - int count = XPCountChildWidgets(inWidget); - for (int n = 0; n < count; ++n) { - XPWidgetID child = XPGetNthChildWidget(inWidget, n); - outChildren.push_back(child); - std::vector grandChildren; - XPCGetOrderedSubWidgets(child, grandChildren); - - outChildren.insert(outChildren.end(), - grandChildren.begin(), - grandChildren.end()); - } } + +int XPCTabGroupAttachment::HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + if ((inMessage == xpMsg_KeyPress) && (KEY_CHAR(inParam1) == XPLM_KEY_TAB) && + ((KEY_FLAGS(inParam1) & xplm_UpFlag) == 0)) + { + bool backwards = (KEY_FLAGS(inParam1) & xplm_ShiftFlag) != 0; + std::vector widgets; + XPCGetOrderedSubWidgets(inWidget, widgets); + int n, index = 0; + XPWidgetID focusWidget = XPGetWidgetWithFocus(); + std::vector::iterator iter = std::find(widgets.begin(), widgets.end(), focusWidget); + if (iter != widgets.end()) + { + index = std::distance(widgets.begin(), iter); + if (backwards) + index--; + else + index++; + if (index < 0) + index = widgets.size() - 1; + if (index >= widgets.size()) + index = 0; + } + + if (backwards) + { + for (n = index; n >= 0; --n) + { + if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) + if (XPSetKeyboardFocus(widgets[n]) != NULL) + return 1; + } + for (n = widgets.size() - 1; n > index; --n) + { + if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) + if (XPSetKeyboardFocus(widgets[n]) != NULL) + return 1; + } + } else { + for (n = index; n < widgets.size(); ++n) + { + if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) + if (XPSetKeyboardFocus(widgets[n]) != NULL) + return 1; + } + for (n = 0; n < index; ++n) + { + if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) + if (XPSetKeyboardFocus(widgets[n]) != NULL) + return 1; + } + } + } + return 0; +} + + + +static void XPCGetOrderedSubWidgets( + XPWidgetID inWidget, + std::vector& outChildren) +{ + outChildren.clear(); + int count = XPCountChildWidgets(inWidget); + for (int n = 0; n < count; ++n) + { + XPWidgetID child = XPGetNthChildWidget(inWidget, n); + outChildren.push_back(child); + std::vector grandChildren; + XPCGetOrderedSubWidgets(child, grandChildren); + + outChildren.insert(outChildren.end(), grandChildren.begin(), grandChildren.end()); + } +} diff --git a/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.h b/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.h index 086d6ea..91fb587 100644 --- a/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.h +++ b/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.h @@ -3,130 +3,144 @@ #include -#include "XPCBroadcaster.h" #include "XPCWidget.h" +#include "XPCBroadcaster.h" -class XPCKeyFilterAttachment : public XPCWidgetAttachment -{ +class XPCKeyFilterAttachment : public XPCWidgetAttachment { public: - XPCKeyFilterAttachment(const char *inValidKeys, const char *outValidKeys); - virtual ~XPCKeyFilterAttachment(); - virtual int HandleWidgetMessage(XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2); + XPCKeyFilterAttachment( + const char * inValidKeys, + const char * outValidKeys); + virtual ~XPCKeyFilterAttachment(); + + virtual int HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); private: - std::string mInput; - std::string mOutput; + + std::string mInput; + std::string mOutput; + }; -class XPCKeyMessageAttachment : public XPCWidgetAttachment, - public XPCBroadcaster -{ +class XPCKeyMessageAttachment : public XPCWidgetAttachment, public XPCBroadcaster { public: - XPCKeyMessageAttachment(char inKey, - int inMessage, - void *inParam, - bool inConsume, - bool inVkey, - XPCListener *inListener); - virtual ~XPCKeyMessageAttachment(); - virtual int HandleWidgetMessage(XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2); + XPCKeyMessageAttachment( + char inKey, + int inMessage, + void * inParam, + bool inConsume, + bool inVkey, + XPCListener * inListener); + virtual ~XPCKeyMessageAttachment(); + + virtual int HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); private: - char mKey; - bool mVkey; - int mMsg; - void *mParam; - bool mConsume; + + char mKey; + bool mVkey; + int mMsg; + void * mParam; + bool mConsume; + }; -class XPCPushButtonMessageAttachment : public XPCWidgetAttachment, - XPCBroadcaster -{ +class XPCPushButtonMessageAttachment : public XPCWidgetAttachment, XPCBroadcaster { public: - XPCPushButtonMessageAttachment(XPWidgetID inWidget, - int inMessage, - void *inParam, - XPCListener *inListener); - virtual ~XPCPushButtonMessageAttachment(); - virtual int HandleWidgetMessage(XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2); + XPCPushButtonMessageAttachment( + XPWidgetID inWidget, + int inMessage, + void * inParam, + XPCListener * inListener); + virtual ~XPCPushButtonMessageAttachment(); + + virtual int HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); private: - XPWidgetID mWidget; - int mMsg; - void *mParam; + XPWidgetID mWidget; + int mMsg; + void * mParam; }; -class XPCSliderMessageAttachment : public XPCWidgetAttachment, XPCBroadcaster -{ +class XPCSliderMessageAttachment : public XPCWidgetAttachment, XPCBroadcaster { public: - XPCSliderMessageAttachment(XPWidgetID inWidget, - int inMessage, - void *inParam, - XPCListener *inListener); - virtual ~XPCSliderMessageAttachment(); - virtual int HandleWidgetMessage(XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2); + XPCSliderMessageAttachment( + XPWidgetID inWidget, + int inMessage, + void * inParam, + XPCListener * inListener); + virtual ~XPCSliderMessageAttachment(); + + virtual int HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); private: - XPWidgetID mWidget; - int mMsg; - void *mParam; + XPWidgetID mWidget; + int mMsg; + void * mParam; }; -class XPCCloseButtonMessageAttachment : public XPCWidgetAttachment, - XPCBroadcaster -{ +class XPCCloseButtonMessageAttachment : public XPCWidgetAttachment, XPCBroadcaster { public: - XPCCloseButtonMessageAttachment(XPWidgetID inWidget, - int inMessage, - void *inParam, - XPCListener *inListener); - virtual ~XPCCloseButtonMessageAttachment(); - virtual int HandleWidgetMessage(XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2); + XPCCloseButtonMessageAttachment( + XPWidgetID inWidget, + int inMessage, + void * inParam, + XPCListener * inListener); + virtual ~XPCCloseButtonMessageAttachment(); + + virtual int HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); private: - XPWidgetID mWidget; - int mMsg; - void *mParam; + XPWidgetID mWidget; + int mMsg; + void * mParam; }; -class XPCTabGroupAttachment : public XPCWidgetAttachment -{ +class XPCTabGroupAttachment : public XPCWidgetAttachment { public: - XPCTabGroupAttachment(); - virtual ~XPCTabGroupAttachment(); - virtual int HandleWidgetMessage(XPCWidget *inObject, - XPWidgetMessage inMessage, - XPWidgetID inWidget, - intptr_t inParam1, - intptr_t inParam2); + XPCTabGroupAttachment(); + virtual ~XPCTabGroupAttachment(); + + virtual int HandleWidgetMessage( + XPCWidget * inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + }; #endif \ No newline at end of file diff --git a/XPSDK/CHeaders/XPLM/XPLMCamera.h b/XPSDK/CHeaders/XPLM/XPLMCamera.h index f493525..db930ef 100644 --- a/XPSDK/CHeaders/XPLM/XPLMCamera.h +++ b/XPSDK/CHeaders/XPLM/XPLMCamera.h @@ -2,42 +2,46 @@ #define _XPLMCamera_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPLMCamera + ***************************************************************************/ /* - * XPLMCamera - THEORY OF OPERATION The XPLMCamera APIs allow plug-ins to - * control the camera angle in X-Plane. This has a number of applications, - * including but not limited to: - * + * The XPLMCamera APIs allow plug-ins to control the camera angle in X-Plane. + * This has a number of applications, including but not limited to: + * * - Creating new views (including dynamic/user-controllable views) for the - * user. - * + * user. * - Creating applications that use X-Plane as a renderer of scenery, - * aircrafts, or both. - * + * aircrafts, or both. + * * The camera is controlled via six parameters: a location in OpenGL * coordinates and pitch, roll and yaw, similar to an airplane's position. * OpenGL coordinate info is described in detail in the XPLMGraphics * documentation; generally you should use the XPLMGraphics routines to - * convert from world to local coordinates. The camera's orientation starts - * facing level with the ground directly up the negative-Z axis - * (approximately north) with the horizon horizontal. It is then rotated - * clockwise for yaw, pitched up for positive pitch, and rolled clockwise - * around the vector it is looking along for roll. - * + * convert from world to local coordinates. The camera's orientation starts + * facing level with the ground directly up the negative-Z axis (approximately + * north) with the horizon horizontal. It is then rotated clockwise for yaw, + * pitched up for positive pitch, and rolled clockwise around the vector it is + * looking along for roll. + * * You control the camera either either until the user selects a new view or - * permanently (the later being similar to how UDP camera control works). You + * permanently (the later being similar to how UDP camera control works). You * control the camera by registering a callback per frame from which you - * calculate the new camera positions. This guarantees smooth camera motion. - * + * calculate the new camera positions. This guarantees smooth camera motion. + * * Use the XPLMDataAccess APIs to get information like the position of the * aircraft, etc. for complex camera positioning. + * + * Note: if your goal is to move the virtual pilot in the cockpit, this API is + * not needed; simply update the datarefs for the pilot's head position. + * + * For custom exterior cameras, set the camera's mode to an external view + * first to get correct sound and 2-d panel behavior. * */ @@ -50,27 +54,21 @@ extern "C" { /*************************************************************************** * CAMERA CONTROL ***************************************************************************/ -/* - * - * - */ - /* * XPLMCameraControlDuration - * + * * This enumeration states how long you want to retain control of the camera. - * You can retain it indefinitely or until the user selects a new view. + * You can retain it indefinitely or until the user selects a new view. * */ enum { - /* Control the camera until the user picks a new view. */ - xplm_ControlCameraUntilViewChanges = 1 + /* Control the camera until the user picks a new view. */ + xplm_ControlCameraUntilViewChanges = 1, - /* Control the camera until your plugin is disabled or another plugin - * forcably * takes control. */ - , - xplm_ControlCameraForever = 2 + /* Control the camera until your plugin is disabled or another plugin forcably* + * takes control. */ + xplm_ControlCameraForever = 2, }; @@ -78,87 +76,89 @@ typedef int XPLMCameraControlDuration; /* * XPLMCameraPosition_t - * - * This structure contains a full specification of the camera. X, Y, and Z - * are the camera's position in OpenGL coordiantes; pitch, roll, and yaw are - * rotations from a camera facing flat north in degrees. Positive pitch means + * + * This structure contains a full specification of the camera. X, Y, and Z are + * the camera's position in OpenGL coordiantes; pitch, roll, and yaw are + * rotations from a camera facing flat north in degrees. Positive pitch means * nose up, positive roll means roll right, and positive yaw means yaw right, * all in degrees. Zoom is a zoom factor, with 1.0 meaning normal zoom and 2.0 - * magnifying by 2x (objects appear larger). + * magnifying by 2x (objects appear larger). * */ typedef struct { - float x; - float y; - float z; - float pitch; - float heading; - float roll; - float zoom; + float x; + float y; + float z; + float pitch; + float heading; + float roll; + float zoom; } XPLMCameraPosition_t; /* * XPLMCameraControl_f - * + * * You use an XPLMCameraControl function to provide continuous control over - * the camera. You are passed in a structure in which to put the new camera - * position; modify it and return 1 to reposition the camera. Return 0 to + * the camera. You are passed in a structure in which to put the new camera + * position; modify it and return 1 to reposition the camera. Return 0 to * surrender control of the camera; camera control will be handled by X-Plane * on this draw loop. The contents of the structure as you are called are * undefined. - * + * * If X-Plane is taking camera control away from you, this function will be - * called with inIsLosingControl set to 1 and ioCameraPosition NULL. + * called with inIsLosingControl set to 1 and ioCameraPosition NULL. * */ -typedef int (*XPLMCameraControl_f)( - XPLMCameraPosition_t *outCameraPosition, /* Can be NULL */ - int inIsLosingControl, - void *inRefcon); +typedef int (* XPLMCameraControl_f)( + XPLMCameraPosition_t * outCameraPosition, /* Can be NULL */ + int inIsLosingControl, + void * inRefcon); /* * XPLMControlCamera - * - * This function repositions the camera on the next drawing cycle. You must - * pass a non-null control function. Specify in inHowLong how long you'd like - * control (indefinitely or until a key is pressed). + * + * This function repositions the camera on the next drawing cycle. You must + * pass a non-null control function. Specify in inHowLong how long you'd like + * control (indefinitely or until a new view mode is set by the user). * */ -XPLM_API void XPLMControlCamera(XPLMCameraControlDuration inHowLong, - XPLMCameraControl_f inControlFunc, - void *inRefcon); +XPLM_API void XPLMControlCamera( + XPLMCameraControlDuration inHowLong, + XPLMCameraControl_f inControlFunc, + void * inRefcon); /* * XPLMDontControlCamera - * - * This function stops you from controlling the camera. If you have a camera + * + * This function stops you from controlling the camera. If you have a camera * control function, it will not be called with an inIsLosingControl flag. * X-Plane will control the camera on the next cycle. - * + * * For maximum compatibility you should not use this routine unless you are in - * posession of the camera. + * posession of the camera. * */ -XPLM_API void XPLMDontControlCamera(void); +XPLM_API void XPLMDontControlCamera(void); /* * XPLMIsCameraBeingControlled - * + * * This routine returns 1 if the camera is being controlled, zero if it is - * not. If it is and you pass in a pointer to a camera control duration, the - * current control duration will be returned. + * not. If it is and you pass in a pointer to a camera control duration, the + * current control duration will be returned. * */ -XPLM_API int XPLMIsCameraBeingControlled( - XPLMCameraControlDuration *outCameraControlDuration); /* Can be NULL */ +XPLM_API int XPLMIsCameraBeingControlled( + XPLMCameraControlDuration * outCameraControlDuration); /* Can be NULL */ /* * XPLMReadCameraPosition - * - * This function reads the current camera position. + * + * This function reads the current camera position. * */ -XPLM_API void XPLMReadCameraPosition(XPLMCameraPosition_t *outCameraPosition); +XPLM_API void XPLMReadCameraPosition( + XPLMCameraPosition_t * outCameraPosition); #ifdef __cplusplus } diff --git a/XPSDK/CHeaders/XPLM/XPLMDataAccess.h b/XPSDK/CHeaders/XPLM/XPLMDataAccess.h index ba37559..d8d1418 100644 --- a/XPSDK/CHeaders/XPLM/XPLMDataAccess.h +++ b/XPSDK/CHeaders/XPLM/XPLMDataAccess.h @@ -2,61 +2,82 @@ #define _XPLMDataAccess_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPLMDataAccess + ***************************************************************************/ /* - * XPLM Data Access API - Theory of Operation - * * The data access API gives you a generic, flexible, high performance way to - * read and write data to and from X-Plane and other plug-ins. For example, + * read and write data to and from X-Plane and other plug-ins. For example, * this API allows you to read and set the nav radios, get the plane location, * determine the current effective graphics frame rate, etc. - * + * * The data access APIs are the way that you read and write data from the sim * as well as other plugins. - * - * The API works using opaque data references. A data reference is a source - * of data; you do not know where it comes from, but once you have it you can - * read the data quickly and possibly write it. To get a data reference, you - * look it up. - * - * Data references are identified by verbose string names - * (sim/cockpit/radios/nav1_freq_hz). The actual numeric value of the data - * reference is implementation defined and is likely to change each time the - * simulator is run (or the plugin that provides the datareference is - * reloaded). - * + * + * The API works using opaque data references. A data reference is a source of + * data; you do not know where it comes from, but once you have it you can + * read the data quickly and possibly write it. + * + * Dataref Lookup + * -------------- + * + * Data references are identified by verbose, permanent string names; by + * convention these names use path separates to form a hierarchy of datarefs, + * e.g. (sim/cockpit/radios/nav1_freq_hz). The actual opaque numeric value of + * the data reference, as returned by the XPLM API, is implementation defined + * and changes each time X-Plane is launched; therefore you need to look up + * the dataref by path every time your plugin runs. + * * The task of looking up a data reference is relatively expensive; look up - * your data references once based on verbose strings, and save the opaque - * data reference value for the duration of your plugin's operation. Reading - * and writing data references is relatively fast (the cost is equivalent to - * two function calls through function pointers). - * - * This allows data access to be high performance, while leaving in - * abstraction; since data references are opaque and are searched for, the - * underlying data access system can be rebuilt. - * + * your data references once based on the verbose path strings, and save the + * opaque data reference value for the duration of your plugin's operation. + * Reading and writing data references is relatively fast (the cost is + * equivalent to two function calls through function pointers). + * + * X-Plane publishes over 4000 datarefs; a complete list may be found in the + * reference section of the SDK online documentation (from the SDK home page, + * choose Documentation). + * + * Dataref Types + * ------------- + * * A note on typing: you must know the correct data type to read and write. - * APIs are provided for reading and writing data in a number of ways. You - * can also double check the data type for a data ref. Note that automatic - * conversion is not done for you. - * + * APIs are provided for reading and writing data in a number of ways. You can + * also double check the data type for a data ref. Automatic type conversion + * is not done for you. + * + * Dataref types are a set, e.g. a dataref can be more than one type. When + * this happens, you can choose which API you want to use to read. For + * example, it is not uncommon for a dataref to be of type float and double. + * This means you can use either XPLMGetDatad or XPLMGetDataf to read it. + * + * Creating New Datarefs + * --------------------- + * + * X-Plane provides datarefs that come with the sim, but plugins can also + * create their own datarefs. A plugin creates a dataref by registering + * function callbacks to read and write the dataref. The XPLM will call your + * plugin each time some other plugin (or X-Plane) tries to read or write the + * dataref. You must provide a read (and optional write) callback for each + * data type you support. + * * A note for plugins sharing data with other plugins: the load order of - * plugins is not guaranteed. To make sure that every plugin publishing data + * plugins is not guaranteed. To make sure that every plugin publishing data * has published their data references before other plugins try to subscribe, * publish your data references in your start routine but resolve them the * first time your 'enable' routine is called, or the first time they are * needed in code. - * - * X-Plane publishes well over 1000 datarefs; a complete list may be found in - * the reference section of the SDK online documentation (from the SDK home - * page, choose Documentation). + * + * When a plugin that created a dataref is unloaded, it becomes "orphaned". + * The dataref handle continues to be usable, but the dataref is not writable, + * and reading it will always return 0 (or 0 items for arrays). If the plugin + * is reloaded and re-registers the dataref, the handle becomes un-orphaned + * and works again. * */ @@ -70,61 +91,57 @@ extern "C" { * READING AND WRITING DATA ***************************************************************************/ /* - * These routines allow you to access a wide variety of data from within - * x-plane and modify some of it. + * These routines allow you to access data from within X-Plane and sometimes + * modify it. * */ /* * XPLMDataRef - * + * * A data ref is an opaque handle to data provided by the simulator or another - * plugin. It uniquely identifies one variable (or array of variables) over - * the lifetime of your plugin. You never hard code these values; you always - * get them from XPLMFindDataRef. + * plugin. It uniquely identifies one variable (or array of variables) over + * the lifetime of your plugin. You never hard code these values; you always + * get them from XPLMFindDataRef. * */ -typedef void *XPLMDataRef; +typedef void * XPLMDataRef; /* * XPLMDataTypeID - * + * * This is an enumeration that defines the type of the data behind a data * reference. This allows you to sanity check that the data type matches what * you expect. But for the most part, you will know the type of data you are * expecting from the online documentation. - * - * Data types each take a bit field, so sets of data types may be formed. + * + * Data types each take a bit field; it is legal to have a single dataref be + * more than one type of data. Whe this happens, you can pick any matching + * get/set API. * */ enum { - /* Data of a type the current XPLM doesn't do. */ - xplmType_Unknown = 0 + /* Data of a type the current XPLM doesn't do. */ + xplmType_Unknown = 0, - /* A single 4-byte integer, native endian. */ - , - xplmType_Int = 1 + /* A single 4-byte integer, native endian. */ + xplmType_Int = 1, - /* A single 4-byte float, native endian. */ - , - xplmType_Float = 2 + /* A single 4-byte float, native endian. */ + xplmType_Float = 2, - /* A single 8-byte double, native endian. */ - , - xplmType_Double = 4 + /* A single 8-byte double, native endian. */ + xplmType_Double = 4, - /* An array of 4-byte floats, native endian. */ - , - xplmType_FloatArray = 8 + /* An array of 4-byte floats, native endian. */ + xplmType_FloatArray = 8, - /* An array of 4-byte integers, native endian. */ - , - xplmType_IntArray = 16 + /* An array of 4-byte integers, native endian. */ + xplmType_IntArray = 16, - /* A variable block of data. */ - , - xplmType_Data = 32 + /* A variable block of data. */ + xplmType_Data = 32, }; @@ -132,446 +149,472 @@ typedef int XPLMDataTypeID; /* * XPLMFindDataRef - * + * * Given a c-style string that names the data ref, this routine looks up the * actual opaque XPLMDataRef that you use to read and write the data. The - * string names for datarefs are published on the x-plane SDK web site. - * + * string names for datarefs are published on the X-Plane SDK web site. + * * This function returns NULL if the data ref cannot be found. - * + * * NOTE: this function is relatively expensive; save the XPLMDataRef this - * function returns for future use. Do not look up your data ref by string - * every time you need to read or write it. + * function returns for future use. Do not look up your data ref by string + * every time you need to read or write it. * */ -XPLM_API XPLMDataRef XPLMFindDataRef(const char *inDataRefName); +XPLM_API XPLMDataRef XPLMFindDataRef( + const char * inDataRefName); /* * XPLMCanWriteDataRef - * - * Given a data ref, this routine returns true if you can successfully set - * the data, false otherwise. Some datarefs are read-only. + * + * Given a data ref, this routine returns true if you can successfully set the + * data, false otherwise. Some datarefs are read-only. + * + * NOTE: even if a dataref is marked writable, it may not act writable. This + * can happen for datarefs that X-Plane writes to on every frame of + * simulation. In some cases, the dataref is writable but you have to set a + * separate "override" dataref to 1 to stop X-Plane from writing it. * */ -XPLM_API int XPLMCanWriteDataRef(XPLMDataRef inDataRef); +XPLM_API int XPLMCanWriteDataRef( + XPLMDataRef inDataRef); /* * XPLMIsDataRefGood - * - * WARNING: This function is deprecated and should not be used. Datarefs are - * valid until plugins are reloaded or the sim quits. Plugins sharing - * datarefs should support these semantics by not unregistering datarefs - * during operation. (You should however unregister datarefs when your plugin - * is unloaded, as part of general resource cleanup.) - * - * This function returns whether a data ref is still valid. If it returns - * false, you should refind the data ref from its original string. Calling an - * accessor function on a bad data ref will return a default value, typically - * 0 or 0-length data. + * + * This function returns true if the passed in handle is a valid dataref that + * is not orphaned. + * + * Note: there is normally no need to call this function; datarefs returned by + * XPLMFindDataRef remain valid (but possibly orphaned) unless there is a + * complete plugin reload (in which case your plugin is reloaded anyway). + * Orphaned datarefs can be safely read and return 0. Therefore you never need + * to call XPLMIsDataRefGood to 'check' the safety of a dataref. + * (XPLMIsDatarefGood performs some slow checking of the handle validity, so + * it has a perormance cost.) * */ -XPLM_API int XPLMIsDataRefGood(XPLMDataRef inDataRef); +XPLM_API int XPLMIsDataRefGood( + XPLMDataRef inDataRef); /* * XPLMGetDataRefTypes - * - * This routine returns the types of the data ref for accessor use. If a data - * ref is available in multiple data types, they will all be returned. + * + * This routine returns the types of the data ref for accessor use. If a data + * ref is available in multiple data types, the bit-wise OR of these types + * will be returned. * */ -XPLM_API XPLMDataTypeID XPLMGetDataRefTypes(XPLMDataRef inDataRef); +XPLM_API XPLMDataTypeID XPLMGetDataRefTypes( + XPLMDataRef inDataRef); /*************************************************************************** * DATA ACCESSORS ***************************************************************************/ /* - * These routines read and write the data references. For each supported data - * type there is a reader and a writer. - * - * If the data ref is invalid or the plugin that provides it is disabled or + * These routines read and write the data references. For each supported data + * type there is a reader and a writer. + * + * If the data ref is orphaned or the plugin that provides it is disabled or * there is a type mismatch, the functions that read data will return 0 as a * default value or not modify the passed in memory. The plugins that write * data will not write under these circumstances or if the data ref is - * read-only. NOTE: to keep the overhead of reading datarefs low, these - * routines do not do full validation of a dataref; passing a junk value for - * a dataref can result in crashing the sim. - * + * read-only. + * + * NOTE: to keep the overhead of reading datarefs low, these routines do not + * do full validation of a dataref; passing a junk value for a dataref can + * result in crashing the sim. The get/set APIs do check for NULL. + * * For array-style datarefs, you specify the number of items to read/write and * the offset into the array; the actual number of items read or written is - * returned. This may be less to prevent an array-out-of-bounds error. + * returned. This may be less to prevent an array-out-of-bounds error. * */ /* * XPLMGetDatai - * + * * Read an integer data ref and return its value. The return value is the - * dataref value or 0 if the dataref is invalid/NULL or the plugin is - * disabled. + * dataref value or 0 if the dataref is NULL or the plugin is disabled. * */ -XPLM_API int XPLMGetDatai(XPLMDataRef inDataRef); +XPLM_API int XPLMGetDatai( + XPLMDataRef inDataRef); /* * XPLMSetDatai - * - * Write a new value to an integer data ref. This routine is a no-op if the - * plugin publishing the dataref is disabled, the dataref is invalid, or the - * dataref is not writable. + * + * Write a new value to an integer data ref. This routine is a no-op if the + * plugin publishing the dataref is disabled, the dataref is NULL, or the + * dataref is not writable. * */ -XPLM_API void XPLMSetDatai(XPLMDataRef inDataRef, int inValue); +XPLM_API void XPLMSetDatai( + XPLMDataRef inDataRef, + int inValue); /* * XPLMGetDataf - * + * * Read a single precision floating point dataref and return its value. The - * return value is the dataref value or 0.0 if the dataref is invalid/NULL or - * the plugin is disabled. + * return value is the dataref value or 0.0 if the dataref is NULL or the + * plugin is disabled. * */ -XPLM_API float XPLMGetDataf(XPLMDataRef inDataRef); +XPLM_API float XPLMGetDataf( + XPLMDataRef inDataRef); /* * XPLMSetDataf - * - * Write a new value to a single precision floating point data ref. This + * + * Write a new value to a single precision floating point data ref. This * routine is a no-op if the plugin publishing the dataref is disabled, the - * dataref is invalid, or the dataref is not writable. + * dataref is NULL, or the dataref is not writable. * */ -XPLM_API void XPLMSetDataf(XPLMDataRef inDataRef, float inValue); +XPLM_API void XPLMSetDataf( + XPLMDataRef inDataRef, + float inValue); /* * XPLMGetDatad - * + * * Read a double precision floating point dataref and return its value. The - * return value is the dataref value or 0.0 if the dataref is invalid/NULL or - * the plugin is disabled. + * return value is the dataref value or 0.0 if the dataref is NULL or the + * plugin is disabled. * */ -XPLM_API double XPLMGetDatad(XPLMDataRef inDataRef); +XPLM_API double XPLMGetDatad( + XPLMDataRef inDataRef); /* * XPLMSetDatad - * - * Write a new value to a double precision floating point data ref. This + * + * Write a new value to a double precision floating point data ref. This * routine is a no-op if the plugin publishing the dataref is disabled, the - * dataref is invalid, or the dataref is not writable. + * dataref is NULL, or the dataref is not writable. * */ -XPLM_API void XPLMSetDatad(XPLMDataRef inDataRef, double inValue); +XPLM_API void XPLMSetDatad( + XPLMDataRef inDataRef, + double inValue); /* * XPLMGetDatavi - * - * Read a part of an integer array dataref. If you pass NULL for outVaules, + * + * Read a part of an integer array dataref. If you pass NULL for outValues, * the routine will return the size of the array, ignoring inOffset and inMax. - * - * + * * If outValues is not NULL, then up to inMax values are copied from the * dataref into outValues, starting at inOffset in the dataref. If inMax + * inOffset is larger than the size of the dataref, less than inMax values - * will be copied. The number of values copied is returned. - * + * will be copied. The number of values copied is returned. + * * Note: the semantics of array datarefs are entirely implemented by the * plugin (or X-Plane) that provides the dataref, not the SDK itself; the * above description is how these datarefs are intended to work, but a rogue - * plugin may have different behavior. + * plugin may have different behavior. * */ -XPLM_API int XPLMGetDatavi(XPLMDataRef inDataRef, - int *outValues, /* Can be NULL */ - int inOffset, - int inMax); +XPLM_API int XPLMGetDatavi( + XPLMDataRef inDataRef, + int * outValues, /* Can be NULL */ + int inOffset, + int inMax); /* * XPLMSetDatavi - * - * Write part or all of an integer array dataref. The values passed by - * inValues are written into the dataref starting at inOffset. Up to inCount + * + * Write part or all of an integer array dataref. The values passed by + * inValues are written into the dataref starting at inOffset. Up to inCount * values are written; however if the values would write "off the end" of the * dataref array, then fewer values are written. - * + * * Note: the semantics of array datarefs are entirely implemented by the * plugin (or X-Plane) that provides the dataref, not the SDK itself; the * above description is how these datarefs are intended to work, but a rogue - * plugin may have different behavior. + * plugin may have different behavior. * */ -XPLM_API void XPLMSetDatavi(XPLMDataRef inDataRef, - int *inValues, - int inoffset, - int inCount); +XPLM_API void XPLMSetDatavi( + XPLMDataRef inDataRef, + int * inValues, + int inoffset, + int inCount); /* * XPLMGetDatavf - * - * Read a part of a single precision floating point array dataref. If you - * pass NULL for outVaules, the routine will return the size of the array, - * ignoring inOffset and inMax. - * + * + * Read a part of a single precision floating point array dataref. If you pass + * NULL for outVaules, the routine will return the size of the array, ignoring + * inOffset and inMax. + * * If outValues is not NULL, then up to inMax values are copied from the * dataref into outValues, starting at inOffset in the dataref. If inMax + * inOffset is larger than the size of the dataref, less than inMax values - * will be copied. The number of values copied is returned. - * + * will be copied. The number of values copied is returned. + * * Note: the semantics of array datarefs are entirely implemented by the * plugin (or X-Plane) that provides the dataref, not the SDK itself; the * above description is how these datarefs are intended to work, but a rogue - * plugin may have different behavior. + * plugin may have different behavior. * */ -XPLM_API int XPLMGetDatavf(XPLMDataRef inDataRef, - float *outValues, /* Can be NULL */ - int inOffset, - int inMax); +XPLM_API int XPLMGetDatavf( + XPLMDataRef inDataRef, + float * outValues, /* Can be NULL */ + int inOffset, + int inMax); /* * XPLMSetDatavf - * - * Write part or all of a single precision floating point array dataref. The + * + * Write part or all of a single precision floating point array dataref. The * values passed by inValues are written into the dataref starting at - * inOffset. Up to inCount values are written; however if the values would + * inOffset. Up to inCount values are written; however if the values would * write "off the end" of the dataref array, then fewer values are written. - * + * * Note: the semantics of array datarefs are entirely implemented by the * plugin (or X-Plane) that provides the dataref, not the SDK itself; the * above description is how these datarefs are intended to work, but a rogue - * plugin may have different behavior. + * plugin may have different behavior. * */ -XPLM_API void XPLMSetDatavf(XPLMDataRef inDataRef, - float *inValues, - int inoffset, - int inCount); +XPLM_API void XPLMSetDatavf( + XPLMDataRef inDataRef, + float * inValues, + int inoffset, + int inCount); /* * XPLMGetDatab - * - * Read a part of a byte array dataref. If you pass NULL for outVaules, the + * + * Read a part of a byte array dataref. If you pass NULL for outVaules, the * routine will return the size of the array, ignoring inOffset and inMax. - * + * * If outValues is not NULL, then up to inMax values are copied from the * dataref into outValues, starting at inOffset in the dataref. If inMax + * inOffset is larger than the size of the dataref, less than inMax values - * will be copied. The number of values copied is returned. - * + * will be copied. The number of values copied is returned. + * * Note: the semantics of array datarefs are entirely implemented by the * plugin (or X-Plane) that provides the dataref, not the SDK itself; the * above description is how these datarefs are intended to work, but a rogue - * plugin may have different behavior. + * plugin may have different behavior. * */ -XPLM_API int XPLMGetDatab(XPLMDataRef inDataRef, - void *outValue, /* Can be NULL */ - int inOffset, - int inMaxBytes); +XPLM_API int XPLMGetDatab( + XPLMDataRef inDataRef, + void * outValue, /* Can be NULL */ + int inOffset, + int inMaxBytes); /* * XPLMSetDatab - * - * Write part or all of a byte array dataref. The values passed by inValues - * are written into the dataref starting at inOffset. Up to inCount values - * are written; however if the values would write "off the end" of the dataref + * + * Write part or all of a byte array dataref. The values passed by inValues + * are written into the dataref starting at inOffset. Up to inCount values are + * written; however if the values would write "off the end" of the dataref * array, then fewer values are written. - * + * * Note: the semantics of array datarefs are entirely implemented by the * plugin (or X-Plane) that provides the dataref, not the SDK itself; the * above description is how these datarefs are intended to work, but a rogue - * plugin may have different behavior. + * plugin may have different behavior. * */ -XPLM_API void XPLMSetDatab(XPLMDataRef inDataRef, - void *inValue, - int inOffset, - int inLength); +XPLM_API void XPLMSetDatab( + XPLMDataRef inDataRef, + void * inValue, + int inOffset, + int inLength); /*************************************************************************** - * PUBLISHING YOUR PLUGINS DATA + * PUBLISHING YOUR PLUGIN'S DATA ***************************************************************************/ /* - * These functions allow you to create data references that other plug-ins can - * access via the above data access APIs. Data references published by other - * plugins operate the same as ones published by x-plane in all manners except - * that your data reference will not be available to other plugins if/when - * your plugin is disabled. - * - * You share data by registering data provider callback functions. When a - * plug-in requests your data, these callbacks are then called. You provide + * These functions allow you to create data references that other plug-ins and + * X-Plane can access via the above data access APIs. Data references + * published by other plugins operate the same as ones published by X-Plane in + * all manners except that your data reference will not be available to other + * plugins if/when your plugin is disabled. + * + * You share data by registering data provider callback functions. When a + * plug-in requests your data, these callbacks are then called. You provide * one callback to return the value when a plugin 'reads' it and another to * change the value when a plugin 'writes' it. - * + * * Important: you must pick a prefix for your datarefs other than "sim/" - - * this prefix is reserved for X-Plane. The X-Plane SDK website contains a + * this prefix is reserved for X-Plane. The X-Plane SDK website contains a * registry where authors can select a unique first word for dataref names, to - * prevent dataref collisions between plugins. + * prevent dataref collisions between plugins. * */ /* * XPLMGetDatai_f - * + * * Data provider function pointers. - * - * These define the function pointers you provide to get or set data. Note - * that you are passed a generic pointer for each one. This is the same - * pointer you pass in your register routine; you can use it to find global + * + * These define the function pointers you provide to get or set data. Note + * that you are passed a generic pointer for each one. This is the same + * pointer you pass in your register routine; you can use it to locate plugin * variables, etc. - * + * * The semantics of your callbacks are the same as the dataref accessor above * - basically routines like XPLMGetDatai are just pass-throughs from a caller - * to your plugin. Be particularly mindful in implementing array dataref + * to your plugin. Be particularly mindful in implementing array dataref * read-write accessors; you are responsible for avoiding overruns, supporting - * offset read/writes, and handling a read with a NULL buffer. + * offset read/writes, and handling a read with a NULL buffer. * */ -typedef int (*XPLMGetDatai_f)(void *inRefcon); +typedef int (* XPLMGetDatai_f)( + void * inRefcon); /* - * XPLMSetDatai_f - * + * XPLMSetDatai_f * */ -typedef void (*XPLMSetDatai_f)(void *inRefcon, int inValue); +typedef void (* XPLMSetDatai_f)( + void * inRefcon, + int inValue); /* - * XPLMGetDataf_f - * + * XPLMGetDataf_f * */ -typedef float (*XPLMGetDataf_f)(void *inRefcon); +typedef float (* XPLMGetDataf_f)( + void * inRefcon); /* - * XPLMSetDataf_f - * + * XPLMSetDataf_f * */ -typedef void (*XPLMSetDataf_f)(void *inRefcon, float inValue); +typedef void (* XPLMSetDataf_f)( + void * inRefcon, + float inValue); /* - * XPLMGetDatad_f - * + * XPLMGetDatad_f * */ -typedef double (*XPLMGetDatad_f)(void *inRefcon); +typedef double (* XPLMGetDatad_f)( + void * inRefcon); /* - * XPLMSetDatad_f - * + * XPLMSetDatad_f * */ -typedef void (*XPLMSetDatad_f)(void *inRefcon, double inValue); +typedef void (* XPLMSetDatad_f)( + void * inRefcon, + double inValue); /* - * XPLMGetDatavi_f - * + * XPLMGetDatavi_f * */ -typedef int (*XPLMGetDatavi_f)(void *inRefcon, - int *outValues, /* Can be NULL */ - int inOffset, - int inMax); +typedef int (* XPLMGetDatavi_f)( + void * inRefcon, + int * outValues, /* Can be NULL */ + int inOffset, + int inMax); /* - * XPLMSetDatavi_f - * + * XPLMSetDatavi_f * */ -typedef void (*XPLMSetDatavi_f)(void *inRefcon, - int *inValues, - int inOffset, - int inCount); +typedef void (* XPLMSetDatavi_f)( + void * inRefcon, + int * inValues, + int inOffset, + int inCount); /* - * XPLMGetDatavf_f - * + * XPLMGetDatavf_f * */ -typedef int (*XPLMGetDatavf_f)(void *inRefcon, - float *outValues, /* Can be NULL */ - int inOffset, - int inMax); +typedef int (* XPLMGetDatavf_f)( + void * inRefcon, + float * outValues, /* Can be NULL */ + int inOffset, + int inMax); /* - * XPLMSetDatavf_f - * + * XPLMSetDatavf_f * */ -typedef void (*XPLMSetDatavf_f)(void *inRefcon, - float *inValues, - int inOffset, - int inCount); +typedef void (* XPLMSetDatavf_f)( + void * inRefcon, + float * inValues, + int inOffset, + int inCount); /* - * XPLMGetDatab_f - * + * XPLMGetDatab_f * */ -typedef int (*XPLMGetDatab_f)(void *inRefcon, - void *outValue, /* Can be NULL */ - int inOffset, - int inMaxLength); +typedef int (* XPLMGetDatab_f)( + void * inRefcon, + void * outValue, /* Can be NULL */ + int inOffset, + int inMaxLength); /* - * XPLMSetDatab_f - * + * XPLMSetDatab_f * */ -typedef void (*XPLMSetDatab_f)(void *inRefcon, - void *inValue, - int inOffset, - int inLength); +typedef void (* XPLMSetDatab_f)( + void * inRefcon, + void * inValue, + int inOffset, + int inLength); /* * XPLMRegisterDataAccessor - * - * This routine creates a new item of data that can be read and written. Pass + * + * This routine creates a new item of data that can be read and written. Pass * in the data's full name for searching, the type(s) of the data for - * accessing, and whether the data can be written to. For each data type you + * accessing, and whether the data can be written to. For each data type you * support, pass in a read accessor function and a write accessor function if - * necessary. Pass NULL for data types you do not support or write accessors + * necessary. Pass NULL for data types you do not support or write accessors * if you are read-only. - * - * You are returned a data ref for the new item of data created. You can use - * this data ref to unregister your data later or read or write from it. + * + * You are returned a data ref for the new item of data created. You can use + * this data ref to unregister your data later or read or write from it. * */ -XPLM_API XPLMDataRef XPLMRegisterDataAccessor(const char *inDataName, - XPLMDataTypeID inDataType, - int inIsWritable, - XPLMGetDatai_f inReadInt, - XPLMSetDatai_f inWriteInt, - XPLMGetDataf_f inReadFloat, - XPLMSetDataf_f inWriteFloat, - XPLMGetDatad_f inReadDouble, - XPLMSetDatad_f inWriteDouble, - XPLMGetDatavi_f inReadIntArray, - XPLMSetDatavi_f inWriteIntArray, - XPLMGetDatavf_f inReadFloatArray, - XPLMSetDatavf_f inWriteFloatArray, - XPLMGetDatab_f inReadData, - XPLMSetDatab_f inWriteData, - void *inReadRefcon, - void *inWriteRefcon); +XPLM_API XPLMDataRef XPLMRegisterDataAccessor( + const char * inDataName, + XPLMDataTypeID inDataType, + int inIsWritable, + XPLMGetDatai_f inReadInt, + XPLMSetDatai_f inWriteInt, + XPLMGetDataf_f inReadFloat, + XPLMSetDataf_f inWriteFloat, + XPLMGetDatad_f inReadDouble, + XPLMSetDatad_f inWriteDouble, + XPLMGetDatavi_f inReadIntArray, + XPLMSetDatavi_f inWriteIntArray, + XPLMGetDatavf_f inReadFloatArray, + XPLMSetDatavf_f inWriteFloatArray, + XPLMGetDatab_f inReadData, + XPLMSetDatab_f inWriteData, + void * inReadRefcon, + void * inWriteRefcon); /* * XPLMUnregisterDataAccessor - * + * * Use this routine to unregister any data accessors you may have registered. * You unregister a data ref by the XPLMDataRef you get back from * registration. Once you unregister a data ref, your function pointer will - * not be called anymore. - * - * For maximum compatibility, do not unregister your data accessors until - * final shutdown (when your XPluginStop routine is called). This allows - * other plugins to find your data reference once and use it for their entire - * time of operation. + * not be called anymore. * */ -XPLM_API void XPLMUnregisterDataAccessor(XPLMDataRef inDataRef); +XPLM_API void XPLMUnregisterDataAccessor( + XPLMDataRef inDataRef); /*************************************************************************** * SHARING DATA BETWEEN MULTIPLE PLUGINS @@ -579,89 +622,92 @@ XPLM_API void XPLMUnregisterDataAccessor(XPLMDataRef inDataRef); /* * The data reference registration APIs from the previous section allow a * plugin to publish data in a one-owner manner; the plugin that publishes the - * data reference owns the real memory that the data ref uses. This is + * data reference owns the real memory that the data ref uses. This is * satisfactory for most cases, but there are also cases where plugnis need to * share actual data. - * + * * With a shared data reference, no one plugin owns the actual memory for the - * data reference; the plugin SDK allocates that for you. When the first - * plugin asks to 'share' the data, the memory is allocated. When the data is + * data reference; the plugin SDK allocates that for you. When the first + * plugin asks to 'share' the data, the memory is allocated. When the data is * changed, every plugin that is sharing the data is notified. - * + * * Shared data references differ from the 'owned' data references from the * previous section in a few ways: - * - * - With shared data references, any plugin can create the data reference; - * with owned plugins one plugin must create the data reference and others - * subscribe. (This can be a problem if you don't know which set of plugins - * will be present). - * - * - With shared data references, every plugin that is sharing the data is - * notified when the data is changed. With owned data references, only the - * one owner is notified when the data is changed. - * - * - With shared data references, you cannot access the physical memory of the - * data reference; you must use the XPLMGet... and XPLMSet... APIs. With an - * owned data reference, the one owning data reference can manipulate the - * data reference's memory in any way it sees fit. - * + * + * * With shared data references, any plugin can create the data reference; + * with owned plugins one plugin must create the data reference and others + * subscribe. (This can be a problem if you don't know which set of plugins + * will be present). + * + * * With shared data references, every plugin that is sharing the data is + * notified when the data is changed. With owned data references, only the + * one owner is notified when the data is changed. + * + * * With shared data references, you cannot access the physical memory of the + * data reference; you must use the XPLMGet... and XPLMSet... APIs. With an + * owned data reference, the one owning data reference can manipulate the + * data reference's memory in any way it sees fit. + * * Shared data references solve two problems: if you need to have a data - * reference used by several plugins but do not know which plugins will be + * reference used by several plugins but do not know which plugins will be * installed, or if all plugins sharing data need to be notified when that - * data is changed, use shared data references. + * data is changed, use shared data references. * */ /* * XPLMDataChanged_f - * + * * An XPLMDataChanged_f is a callback that the XPLM calls whenever any other - * plug-in modifies shared data. A refcon you provide is passed back to help + * plug-in modifies shared data. A refcon you provide is passed back to help * identify which data is being changed. In response, you may want to call one - * of the XPLMGetDataxxx routines to find the new value of the data. + * of the XPLMGetDataxxx routines to find the new value of the data. * */ -typedef void (*XPLMDataChanged_f)(void *inRefcon); +typedef void (* XPLMDataChanged_f)( + void * inRefcon); /* * XPLMShareData - * + * * This routine connects a plug-in to shared data, creating the shared data if * necessary. inDataName is a standard path for the data ref, and inDataType * specifies the type. This function will create the data if it does not - * exist. If the data already exists but the type does not match, an error is - * returned, so it is important that plug-in authors collaborate to establish + * exist. If the data already exists but the type does not match, an error is + * returned, so it is important that plug-in authors collaborate to establish * public standards for shared data. - * + * * If a notificationFunc is passed in and is not NULL, that notification - * function will be called whenever the data is modified. The notification + * function will be called whenever the data is modified. The notification * refcon will be passed to it. This allows your plug-in to know which shared * data was changed if multiple shared data are handled by one callback, or if * the plug-in does not use global variables. - * + * * A one is returned for successfully creating or finding the shared data; a - * zero if the data already exists but is of the wrong type. + * zero if the data already exists but is of the wrong type. * */ -XPLM_API int XPLMShareData(const char *inDataName, - XPLMDataTypeID inDataType, - XPLMDataChanged_f inNotificationFunc, - void *inNotificationRefcon); +XPLM_API int XPLMShareData( + const char * inDataName, + XPLMDataTypeID inDataType, + XPLMDataChanged_f inNotificationFunc, + void * inNotificationRefcon); /* * XPLMUnshareData - * - * This routine removes your notification function for shared data. Call it - * when done with the data to stop receiving change notifications. Arguments + * + * This routine removes your notification function for shared data. Call it + * when done with the data to stop receiving change notifications. Arguments * must match XPLMShareData. The actual memory will not necessarily be freed, - * since other plug-ins could be using it. + * since other plug-ins could be using it. * */ -XPLM_API int XPLMUnshareData(const char *inDataName, - XPLMDataTypeID inDataType, - XPLMDataChanged_f inNotificationFunc, - void *inNotificationRefcon); +XPLM_API int XPLMUnshareData( + const char * inDataName, + XPLMDataTypeID inDataType, + XPLMDataChanged_f inNotificationFunc, + void * inNotificationRefcon); #ifdef __cplusplus } diff --git a/XPSDK/CHeaders/XPLM/XPLMDefs.h b/XPSDK/CHeaders/XPLM/XPLMDefs.h index c720e70..2e95b81 100644 --- a/XPSDK/CHeaders/XPLM/XPLMDefs.h +++ b/XPSDK/CHeaders/XPLM/XPLMDefs.h @@ -2,23 +2,23 @@ #define _XPLMDefs_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPLMDefs + ***************************************************************************/ /* * This file is contains the cross-platform and basic definitions for the * X-Plane SDK. - * + * * The preprocessor macros APL and IBM must be defined to specify the * compilation target; define APL to 1 and IBM 0 to compile on Macintosh and * APL to 0 and IBM to 1 for Windows. You must specify these macro definitions * before including XPLMDefs.h or any other XPLM headers. You can do this - * using the -D command line option or a preprocessor header. + * using the -D command line option or a preprocessor header. * */ @@ -38,160 +38,157 @@ extern "C" { /* * These definitions control the importing and exporting of functions within * the DLL. - * + * * You can prefix your five required callbacks with the PLUGIN_API macro to - * declare them as exported C functions. The XPLM_API macro identifies + * declare them as exported C functions. The XPLM_API macro identifies * functions that are provided to you via the plugin SDK. (Link against - * XPLM.lib to use these functions.) + * XPLM.lib to use these functions.) * */ #ifdef __cplusplus -#if APL -#if __GNUC__ >= 4 -#define PLUGIN_API extern "C" __attribute__((visibility("default"))) -#elif __MACH__ -#define PLUGIN_API extern "C" + #if APL + #if __GNUC__ >= 4 + #define PLUGIN_API extern "C" __attribute__((visibility("default"))) + #elif __MACH__ + #define PLUGIN_API extern "C" + #else + #define PLUGIN_API extern "C" __declspec(dllexport) + #endif + #elif IBM + #define PLUGIN_API extern "C" __declspec(dllexport) + #elif LIN + #if __GNUC__ >= 4 + #define PLUGIN_API extern "C" __attribute__((visibility("default"))) + #else + #define PLUGIN_API extern "C" + #endif + #else + #error "Platform not defined!" + #endif #else -#define PLUGIN_API extern "C" __declspec(dllexport) -#endif -#elif IBM -#define PLUGIN_API extern "C" __declspec(dllexport) -#elif LIN -#if __GNUC__ >= 4 -#define PLUGIN_API extern "C" __attribute__((visibility("default"))) -#else -#define PLUGIN_API extern "C" -#endif -#else -#error "Platform not defined!" -#endif -#else -#if APL -#if __GNUC__ >= 4 -#define PLUGIN_API __attribute__((visibility("default"))) -#elif __MACH__ -#define PLUGIN_API -#else -#define PLUGIN_API __declspec(dllexport) -#endif -#elif IBM -#define PLUGIN_API __declspec(dllexport) -#elif LIN -#if __GNUC__ >= 4 -#define PLUGIN_API __attribute__((visibility("default"))) -#else -#define PLUGIN_API -#endif -#else -#error "Platform not defined!" -#endif + #if APL + #if __GNUC__ >= 4 + #define PLUGIN_API __attribute__((visibility("default"))) + #elif __MACH__ + #define PLUGIN_API + #else + #define PLUGIN_API __declspec(dllexport) + #endif + #elif IBM + #define PLUGIN_API __declspec(dllexport) + #elif LIN + #if __GNUC__ >= 4 + #define PLUGIN_API __attribute__((visibility("default"))) + #else + #define PLUGIN_API + #endif + #else + #error "Platform not defined!" + #endif #endif #if APL -#if XPLM -#if __GNUC__ >= 4 -#define XPLM_API __attribute__((visibility("default"))) -#elif __MACH__ -#define XPLM_API -#else -#define XPLM_API __declspec(dllexport) -#endif -#else -#define XPLM_API -#endif + #if XPLM + #if __GNUC__ >= 4 + #define XPLM_API __attribute__((visibility("default"))) + #elif __MACH__ + #define XPLM_API + #else + #define XPLM_API __declspec(dllexport) + #endif + #else + #define XPLM_API + #endif #elif IBM -#if XPLM -#define XPLM_API __declspec(dllexport) -#else -#define XPLM_API __declspec(dllimport) -#endif + #if XPLM + #define XPLM_API __declspec(dllexport) + #else + #define XPLM_API __declspec(dllimport) + #endif #elif LIN -#if XPLM -#if __GNUC__ >= 4 -#define XPLM_API __attribute__((visibility("default"))) + #if XPLM + #if __GNUC__ >= 4 + #define XPLM_API __attribute__((visibility("default"))) + #else + #define XPLM_API + #endif + #else + #define XPLM_API + #endif #else -#define XPLM_API -#endif -#else -#define XPLM_API -#endif -#else -#error "Platform not defined!" + #error "Platform not defined!" #endif /*************************************************************************** * GLOBAL DEFINITIONS ***************************************************************************/ /* - * These definitions are used in all parts of the SDK. + * These definitions are used in all parts of the SDK. * */ /* * XPLMPluginID - * + * * Each plug-in is identified by a unique integer ID. This ID can be used to * disable or enable a plug-in, or discover what plug-in is 'running' at the * time. A plug-in ID is unique within the currently running instance of * X-Plane unless plug-ins are reloaded. Plug-ins may receive a different - * unique ID each time they are loaded. - * + * unique ID each time they are loaded. This includes the unloading and + * reloading of plugins that are part of the user's aircraft. + * * For persistent identification of plug-ins, use XPLMFindPluginBySignature in * XPLMUtiltiies.h - * - * -1 indicates no plug-in. + * + * -1 indicates no plug-in. * */ typedef int XPLMPluginID; -/* No plugin. */ -#define XPLM_NO_PLUGIN_ID (-1) +/* No plugin. */ +#define XPLM_NO_PLUGIN_ID (-1) -/* X-Plane itself */ -#define XPLM_PLUGIN_XPLANE (0) +/* X-Plane itself */ +#define XPLM_PLUGIN_XPLANE (0) -/* The current XPLM revision is 2.10 (210). */ -#define kXPLM_Version (210) +/* The current XPLM revision is 4.00 (400). */ +#define kXPLM_Version (400) /* * XPLMKeyFlags - * + * * These bitfields define modifier keys in a platform independent way. When a * key is pressed, a series of messages are sent to your plugin. The down - * flag is set in the first of these messages, and the up flag in the last. + * flag is set in the first of these messages, and the up flag in the last. * While the key is held down, messages are sent with neither to indicate that * the key is being held down as a repeated character. - * - * The control flag is mapped to the control flag on Macintosh and PC. + * + * The control flag is mapped to the control flag on Macintosh and PC. * Generally X-Plane uses the control key and not the command key on * Macintosh, providing a consistent interface across platforms that does not * necessarily match the Macintosh user interface guidelines. There is not * yet a way for plugins to access the Macintosh control keys without using - * #ifdefed code. + * #ifdefed code. * */ enum { - /* The shift key is down */ - xplm_ShiftFlag = 1 + /* The shift key is down */ + xplm_ShiftFlag = 1, - /* The option or alt key is down */ - , - xplm_OptionAltFlag = 2 + /* The option or alt key is down */ + xplm_OptionAltFlag = 2, - /* The control key is down* */ - , - xplm_ControlFlag = 4 + /* The control key is down* */ + xplm_ControlFlag = 4, - /* The key is being pressed down */ - , - xplm_DownFlag = 8 + /* The key is being pressed down */ + xplm_DownFlag = 8, - /* The key is being released */ - , - xplm_UpFlag = 16 + /* The key is being released */ + xplm_UpFlag = 16, }; @@ -205,52 +202,53 @@ typedef int XPLMKeyFlags; * codes. Not all key presses generate an ASCII value, so plugin code should * be prepared to see null characters come from the keyboard...this usually * represents a key stroke that has no equivalent ASCII, like a page-down - * press. Use virtual key codes to find these key strokes. ASCII key codes - * take into account modifier keys; shift keys will affect capitals and - * punctuation; control key combinations may have no vaild ASCII and produce - * NULL. To detect control-key combinations, use virtual key codes, not ASCII - * keys. + * press. Use virtual key codes to find these key strokes. + * + * ASCII key codes take into account modifier keys; shift keys will affect + * capitals and punctuation; control key combinations may have no vaild ASCII + * and produce NULL. To detect control-key combinations, use virtual key + * codes, not ASCII keys. * */ -#define XPLM_KEY_RETURN 13 +#define XPLM_KEY_RETURN 13 -#define XPLM_KEY_ESCAPE 27 +#define XPLM_KEY_ESCAPE 27 -#define XPLM_KEY_TAB 9 +#define XPLM_KEY_TAB 9 -#define XPLM_KEY_DELETE 8 +#define XPLM_KEY_DELETE 8 -#define XPLM_KEY_LEFT 28 +#define XPLM_KEY_LEFT 28 -#define XPLM_KEY_RIGHT 29 +#define XPLM_KEY_RIGHT 29 -#define XPLM_KEY_UP 30 +#define XPLM_KEY_UP 30 -#define XPLM_KEY_DOWN 31 +#define XPLM_KEY_DOWN 31 -#define XPLM_KEY_0 48 +#define XPLM_KEY_0 48 -#define XPLM_KEY_1 49 +#define XPLM_KEY_1 49 -#define XPLM_KEY_2 50 +#define XPLM_KEY_2 50 -#define XPLM_KEY_3 51 +#define XPLM_KEY_3 51 -#define XPLM_KEY_4 52 +#define XPLM_KEY_4 52 -#define XPLM_KEY_5 53 +#define XPLM_KEY_5 53 -#define XPLM_KEY_6 54 +#define XPLM_KEY_6 54 -#define XPLM_KEY_7 55 +#define XPLM_KEY_7 55 -#define XPLM_KEY_8 56 +#define XPLM_KEY_8 56 -#define XPLM_KEY_9 57 +#define XPLM_KEY_9 57 -#define XPLM_KEY_DECIMAL 46 +#define XPLM_KEY_DECIMAL 46 /*************************************************************************** * VIRTUAL KEY CODES @@ -258,258 +256,256 @@ typedef int XPLMKeyFlags; /* * These are cross-platform defines for every distinct keyboard press on the * computer. Every physical key on the keyboard has a virtual key code. So - * the "two" key on the top row of the main keyboard has a different code - * from the "two" key on the numeric key pad. But the 'w' and 'W' character - * are indistinguishable by virtual key code because they are the same - * physical key (one with and one without the shift key). - * + * the "two" key on the top row of the main keyboard has a different code from + * the "two" key on the numeric key pad. But the 'w' and 'W' character are + * indistinguishable by virtual key code because they are the same physical + * key (one with and one without the shift key). + * * Use virtual key codes to detect keystrokes that do not have ASCII * equivalents, allow the user to map the numeric keypad separately from the * main keyboard, and detect control key and other modifier-key combinations * that generate ASCII control key sequences (many of which are not available * directly via character keys in the SDK). - * + * * To assign virtual key codes we started with the Microsoft set but made some * additions and changes. A few differences: - * + * * 1. Modifier keys are not available as virtual key codes. You cannot get - * distinct modifier press and release messages. Please do not try to use - * modifier keys as regular keys; doing so will almost certainly interfere - * with users' abilities to use the native x-plane key bindings. - * + * distinct modifier press and release messages. Please do not try to use + * modifier keys as regular keys; doing so will almost certainly interfere + * with users' abilities to use the native X-Plane key bindings. * 2. Some keys that do not exist on both Mac and PC keyboards are removed. - * * 3. Do not assume that the values of these keystrokes are interchangeable - * with MS v-keys. + * with MS v-keys. * */ -#define XPLM_VK_BACK 0x08 +#define XPLM_VK_BACK 0x08 -#define XPLM_VK_TAB 0x09 +#define XPLM_VK_TAB 0x09 -#define XPLM_VK_CLEAR 0x0C +#define XPLM_VK_CLEAR 0x0C -#define XPLM_VK_RETURN 0x0D +#define XPLM_VK_RETURN 0x0D -#define XPLM_VK_ESCAPE 0x1B +#define XPLM_VK_ESCAPE 0x1B -#define XPLM_VK_SPACE 0x20 +#define XPLM_VK_SPACE 0x20 -#define XPLM_VK_PRIOR 0x21 +#define XPLM_VK_PRIOR 0x21 -#define XPLM_VK_NEXT 0x22 +#define XPLM_VK_NEXT 0x22 -#define XPLM_VK_END 0x23 +#define XPLM_VK_END 0x23 -#define XPLM_VK_HOME 0x24 +#define XPLM_VK_HOME 0x24 -#define XPLM_VK_LEFT 0x25 +#define XPLM_VK_LEFT 0x25 -#define XPLM_VK_UP 0x26 +#define XPLM_VK_UP 0x26 -#define XPLM_VK_RIGHT 0x27 +#define XPLM_VK_RIGHT 0x27 -#define XPLM_VK_DOWN 0x28 +#define XPLM_VK_DOWN 0x28 -#define XPLM_VK_SELECT 0x29 +#define XPLM_VK_SELECT 0x29 -#define XPLM_VK_PRINT 0x2A +#define XPLM_VK_PRINT 0x2A -#define XPLM_VK_EXECUTE 0x2B +#define XPLM_VK_EXECUTE 0x2B -#define XPLM_VK_SNAPSHOT 0x2C +#define XPLM_VK_SNAPSHOT 0x2C -#define XPLM_VK_INSERT 0x2D +#define XPLM_VK_INSERT 0x2D -#define XPLM_VK_DELETE 0x2E +#define XPLM_VK_DELETE 0x2E -#define XPLM_VK_HELP 0x2F +#define XPLM_VK_HELP 0x2F -/* XPLM_VK_0 thru XPLM_VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */ -#define XPLM_VK_0 0x30 +/* XPLM_VK_0 thru XPLM_VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */ +#define XPLM_VK_0 0x30 -#define XPLM_VK_1 0x31 +#define XPLM_VK_1 0x31 -#define XPLM_VK_2 0x32 +#define XPLM_VK_2 0x32 -#define XPLM_VK_3 0x33 +#define XPLM_VK_3 0x33 -#define XPLM_VK_4 0x34 +#define XPLM_VK_4 0x34 -#define XPLM_VK_5 0x35 +#define XPLM_VK_5 0x35 -#define XPLM_VK_6 0x36 +#define XPLM_VK_6 0x36 -#define XPLM_VK_7 0x37 +#define XPLM_VK_7 0x37 -#define XPLM_VK_8 0x38 +#define XPLM_VK_8 0x38 -#define XPLM_VK_9 0x39 +#define XPLM_VK_9 0x39 -/* XPLM_VK_A thru XPLM_VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */ -#define XPLM_VK_A 0x41 +/* XPLM_VK_A thru XPLM_VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */ +#define XPLM_VK_A 0x41 -#define XPLM_VK_B 0x42 +#define XPLM_VK_B 0x42 -#define XPLM_VK_C 0x43 +#define XPLM_VK_C 0x43 -#define XPLM_VK_D 0x44 +#define XPLM_VK_D 0x44 -#define XPLM_VK_E 0x45 +#define XPLM_VK_E 0x45 -#define XPLM_VK_F 0x46 +#define XPLM_VK_F 0x46 -#define XPLM_VK_G 0x47 +#define XPLM_VK_G 0x47 -#define XPLM_VK_H 0x48 +#define XPLM_VK_H 0x48 -#define XPLM_VK_I 0x49 +#define XPLM_VK_I 0x49 -#define XPLM_VK_J 0x4A +#define XPLM_VK_J 0x4A -#define XPLM_VK_K 0x4B +#define XPLM_VK_K 0x4B -#define XPLM_VK_L 0x4C +#define XPLM_VK_L 0x4C -#define XPLM_VK_M 0x4D +#define XPLM_VK_M 0x4D -#define XPLM_VK_N 0x4E +#define XPLM_VK_N 0x4E -#define XPLM_VK_O 0x4F +#define XPLM_VK_O 0x4F -#define XPLM_VK_P 0x50 +#define XPLM_VK_P 0x50 -#define XPLM_VK_Q 0x51 +#define XPLM_VK_Q 0x51 -#define XPLM_VK_R 0x52 +#define XPLM_VK_R 0x52 -#define XPLM_VK_S 0x53 +#define XPLM_VK_S 0x53 -#define XPLM_VK_T 0x54 +#define XPLM_VK_T 0x54 -#define XPLM_VK_U 0x55 +#define XPLM_VK_U 0x55 -#define XPLM_VK_V 0x56 +#define XPLM_VK_V 0x56 -#define XPLM_VK_W 0x57 +#define XPLM_VK_W 0x57 -#define XPLM_VK_X 0x58 +#define XPLM_VK_X 0x58 -#define XPLM_VK_Y 0x59 +#define XPLM_VK_Y 0x59 -#define XPLM_VK_Z 0x5A +#define XPLM_VK_Z 0x5A -#define XPLM_VK_NUMPAD0 0x60 +#define XPLM_VK_NUMPAD0 0x60 -#define XPLM_VK_NUMPAD1 0x61 +#define XPLM_VK_NUMPAD1 0x61 -#define XPLM_VK_NUMPAD2 0x62 +#define XPLM_VK_NUMPAD2 0x62 -#define XPLM_VK_NUMPAD3 0x63 +#define XPLM_VK_NUMPAD3 0x63 -#define XPLM_VK_NUMPAD4 0x64 +#define XPLM_VK_NUMPAD4 0x64 -#define XPLM_VK_NUMPAD5 0x65 +#define XPLM_VK_NUMPAD5 0x65 -#define XPLM_VK_NUMPAD6 0x66 +#define XPLM_VK_NUMPAD6 0x66 -#define XPLM_VK_NUMPAD7 0x67 +#define XPLM_VK_NUMPAD7 0x67 -#define XPLM_VK_NUMPAD8 0x68 +#define XPLM_VK_NUMPAD8 0x68 -#define XPLM_VK_NUMPAD9 0x69 +#define XPLM_VK_NUMPAD9 0x69 -#define XPLM_VK_MULTIPLY 0x6A +#define XPLM_VK_MULTIPLY 0x6A -#define XPLM_VK_ADD 0x6B +#define XPLM_VK_ADD 0x6B -#define XPLM_VK_SEPARATOR 0x6C +#define XPLM_VK_SEPARATOR 0x6C -#define XPLM_VK_SUBTRACT 0x6D +#define XPLM_VK_SUBTRACT 0x6D -#define XPLM_VK_DECIMAL 0x6E +#define XPLM_VK_DECIMAL 0x6E -#define XPLM_VK_DIVIDE 0x6F +#define XPLM_VK_DIVIDE 0x6F -#define XPLM_VK_F1 0x70 +#define XPLM_VK_F1 0x70 -#define XPLM_VK_F2 0x71 +#define XPLM_VK_F2 0x71 -#define XPLM_VK_F3 0x72 +#define XPLM_VK_F3 0x72 -#define XPLM_VK_F4 0x73 +#define XPLM_VK_F4 0x73 -#define XPLM_VK_F5 0x74 +#define XPLM_VK_F5 0x74 -#define XPLM_VK_F6 0x75 +#define XPLM_VK_F6 0x75 -#define XPLM_VK_F7 0x76 +#define XPLM_VK_F7 0x76 -#define XPLM_VK_F8 0x77 +#define XPLM_VK_F8 0x77 -#define XPLM_VK_F9 0x78 +#define XPLM_VK_F9 0x78 -#define XPLM_VK_F10 0x79 +#define XPLM_VK_F10 0x79 -#define XPLM_VK_F11 0x7A +#define XPLM_VK_F11 0x7A -#define XPLM_VK_F12 0x7B +#define XPLM_VK_F12 0x7B -#define XPLM_VK_F13 0x7C +#define XPLM_VK_F13 0x7C -#define XPLM_VK_F14 0x7D +#define XPLM_VK_F14 0x7D -#define XPLM_VK_F15 0x7E +#define XPLM_VK_F15 0x7E -#define XPLM_VK_F16 0x7F +#define XPLM_VK_F16 0x7F -#define XPLM_VK_F17 0x80 +#define XPLM_VK_F17 0x80 -#define XPLM_VK_F18 0x81 +#define XPLM_VK_F18 0x81 -#define XPLM_VK_F19 0x82 +#define XPLM_VK_F19 0x82 -#define XPLM_VK_F20 0x83 +#define XPLM_VK_F20 0x83 -#define XPLM_VK_F21 0x84 +#define XPLM_VK_F21 0x84 -#define XPLM_VK_F22 0x85 +#define XPLM_VK_F22 0x85 -#define XPLM_VK_F23 0x86 +#define XPLM_VK_F23 0x86 -#define XPLM_VK_F24 0x87 +#define XPLM_VK_F24 0x87 -/* The following definitions are extended and are not based on the Microsoft * - * key set. */ -#define XPLM_VK_EQUAL 0xB0 +/* The following definitions are extended and are not based on the Microsoft * + * key set. */ +#define XPLM_VK_EQUAL 0xB0 -#define XPLM_VK_MINUS 0xB1 +#define XPLM_VK_MINUS 0xB1 -#define XPLM_VK_RBRACE 0xB2 +#define XPLM_VK_RBRACE 0xB2 -#define XPLM_VK_LBRACE 0xB3 +#define XPLM_VK_LBRACE 0xB3 -#define XPLM_VK_QUOTE 0xB4 +#define XPLM_VK_QUOTE 0xB4 -#define XPLM_VK_SEMICOLON 0xB5 +#define XPLM_VK_SEMICOLON 0xB5 -#define XPLM_VK_BACKSLASH 0xB6 +#define XPLM_VK_BACKSLASH 0xB6 -#define XPLM_VK_COMMA 0xB7 +#define XPLM_VK_COMMA 0xB7 -#define XPLM_VK_SLASH 0xB8 +#define XPLM_VK_SLASH 0xB8 -#define XPLM_VK_PERIOD 0xB9 +#define XPLM_VK_PERIOD 0xB9 -#define XPLM_VK_BACKQUOTE 0xBA +#define XPLM_VK_BACKQUOTE 0xBA -#define XPLM_VK_ENTER 0xBB +#define XPLM_VK_ENTER 0xBB -#define XPLM_VK_NUMPAD_ENT 0xBC +#define XPLM_VK_NUMPAD_ENT 0xBC -#define XPLM_VK_NUMPAD_EQ 0xBD +#define XPLM_VK_NUMPAD_EQ 0xBD #ifdef __cplusplus } diff --git a/XPSDK/CHeaders/XPLM/XPLMDisplay.h b/XPSDK/CHeaders/XPLM/XPLMDisplay.h index c2f16bc..db5006d 100644 --- a/XPSDK/CHeaders/XPLM/XPLMDisplay.h +++ b/XPSDK/CHeaders/XPLM/XPLMDisplay.h @@ -2,70 +2,89 @@ #define _XPLMDisplay_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPLMDisplay + ***************************************************************************/ /* - * XPLM Display APIs - THEORY OF OPERATION - * * This API provides the basic hooks to draw in X-Plane and create user - * interface. All X-Plane drawing is done in OpenGL. The X-Plane plug-in - * manager takes care of properly setting up the OpenGL context and matrices. - * You do not decide when in your code's execution to draw; X-Plane tells you - * when it is ready to have your plugin draw. - * + * interface. All X-Plane drawing is done in OpenGL. The X-Plane plug-in + * manager takes care of properly setting up the OpenGL context and matrices. + * You do not decide when in your code's execution to draw; X-Plane tells you + * (via callbacks) when it is ready to have your plugin draw. + * * X-Plane's drawing strategy is straightforward: every "frame" the screen is - * rendered by drawing the 3-d scene (dome, ground, objects, airplanes, etc.) + * rendered by drawing the 3-D scene (dome, ground, objects, airplanes, etc.) * and then drawing the cockpit on top of it. Alpha blending is used to * overlay the cockpit over the world (and the gauges over the panel, etc.). - * + * X-Plane user interface elements (including windows like the map, the main + * menu, etc.) are then drawn on top of the cockpit. + * * There are two ways you can draw: directly and in a window. - * - * Direct drawing involves drawing to the screen before or after X-Plane - * finishes a phase of drawing. When you draw directly, you can specify - * whether x-plane is to complete this phase or not. This allows you to do - * three things: draw before x-plane does (under it), draw after x-plane does - * (over it), or draw instead of x-plane. - * - * To draw directly, you register a callback and specify what phase you want + * + * Direct drawing (deprecated!---more on that below) involves drawing to the + * screen before or after X-Plane finishes a phase of drawing. When you draw + * directly, you can specify whether X-Plane is to complete this phase or not. + * This allows you to do three things: draw before X-Plane does (under it), + * draw after X-Plane does (over it), or draw instead of X-Plane. + * + * To draw directly, you register a callback and specify which phase you want * to intercept. The plug-in manager will call you over and over to draw that * phase. - * + * * Direct drawing allows you to override scenery, panels, or anything. Note - * that you cannot assume that you are the only plug-in drawing at this - * phase. - * - * Window drawing provides slightly higher level functionality. With window - * drawing you create a window that takes up a portion of the screen. Window - * drawing is always two dimensional. Window drawing is front-to-back - * controlled; you can specify that you want your window to be brought on - * top, and other plug-ins may put their window on top of you. Window drawing - * also allows you to sign up for key presses and receive mouse clicks. - * + * that you cannot assume that you are the only plug-in drawing at this phase. + * + * Direct drawing is deprecated; at some point in the X-Plane 11 run, it will + * likely become unsupported entirely as X-Plane transitions from OpenGL to + * modern graphics API backends (e.g., Vulkan, Metal, etc.). In the long term, + * plugins should use the XPLMInstance API for drawing 3-D objects---this will + * be much more efficient than general 3-D OpenGL drawing, and it will + * actually be supported by the new graphics backends. We do not yet know what + * the post-transition API for generic 3-D drawing will look like (if it + * exists at all). + * + * In contrast to direct drawing, window drawing provides a higher level + * functionality. With window drawing, you create a 2-D window that takes up a + * portion of the screen. Window drawing is always two dimensional. Window + * drawing is front-to-back controlled; you can specify that you want your + * window to be brought on top, and other plug-ins may put their window on top + * of you. Window drawing also allows you to sign up for key presses and + * receive mouse clicks. + * + * Drawing into the screen of an avionics device, like a GPS or a Primary + * Flight Display, is a way to extend or replace X-Plane's avionics. Most + * screens can be displayed both in a 3d cockpit or + * 2d panel, and also in separate popup windows. By installing drawing + * callbacks for a certain avionics device, you can change or extend the + * appearance of that device regardless whether it's installed in a 3d + * cockpit or used in a separate display for home cockpits because you leave + * the window managing to X-Plane. + * * There are three ways to get keystrokes: - * - * If you create a window, the window can take keyboard focus. It will then - * receive all keystrokes. If no window has focus, X-Plane receives - * keystrokes. Use this to implement typing in dialog boxes, etc. Only one - * window may have focus at a time; your window will be notified if it loses - * focus. - * - * If you need to associate key strokes with commands/functions in your - * plug-in, use a hot key. A hoy is a key-specific callback. Hotkeys are - * sent based on virtual key strokes, so any key may be distinctly mapped with - * any modifiers. Hot keys can be remapped by other plug-ins. As a plug-in, - * you don't have to worry about what your hot key ends up mapped to; other - * plug-ins may provide a UI for remapping keystrokes. So hotkeys allow a - * user to resolve conflicts and customize keystrokes. - * - * If you need low level access to the keystroke stream, install a key - * sniffer. Key sniffers can be installed above everything or right in front - * of the sim. + * + * 1. If you create a window, the window can take keyboard focus. It will + * then receive all keystrokes. If no window has focus, X-Plane receives + * keystrokes. Use this to implement typing in dialog boxes, etc. Only + * one window may have focus at a time; your window will be notified if it + * loses focus. + * 2. If you need low level access to the keystroke stream, install a key + * sniffer. Key sniffers can be installed above everything or right in + * front of the sim. + * 3. If you would like to associate key strokes with commands/functions in + * your plug-in, you should simply register a command (via + * XPLMCreateCommand()) and allow users to bind whatever key they choose to + * that command. Another (now deprecated) method of doing so is to use a + * hot key---a key-specific callback. Hotkeys are sent based on virtual + * key strokes, so any key may be distinctly mapped with any modifiers. + * Hot keys can be remapped by other plug-ins. As a plug-in, you don't + * have to worry about what your hot key ends up mapped to; other plug-ins + * may provide a UI for remapping keystrokes. So hotkeys allow a user to + * resolve conflicts and customize keystrokes. * */ @@ -79,97 +98,120 @@ extern "C" { * DRAWING CALLBACKS ***************************************************************************/ /* - * Basic drawing callbacks, for low level intercepting of render loop. The - * purpose of drawing callbacks is to provide targeted additions or - * replacements to x-plane's graphics environment (for example, to add extra + * Basic drawing callbacks, for low level intercepting of X-Plane's render + * loop. The purpose of drawing callbacks is to provide targeted additions or + * replacements to X-Plane's graphics environment (for example, to add extra * custom objects, or replace drawing of the AI aircraft). Do not assume that * the drawing callbacks will be called in the order implied by the * enumerations. Also do not assume that each drawing phase ends before * another begins; they may be nested. + * + * Note that all APIs in this section are deprecated, and will likely be + * removed during the X-Plane 11 run as part of the transition to + * Vulkan/Metal/etc. See the XPLMInstance API for future-proof drawing of 3-D + * objects. * */ /* * XPLMDrawingPhase - * + * * This constant indicates which part of drawing we are in. Drawing is done * from the back to the front. We get a callback before or after each item. - * Metaphases provide access to the beginning and end of the 3d (scene) and 2d - * (cockpit) drawing in a manner that is independent of new phases added via - * x-plane implementation. - * - * WARNING: As X-Plane's scenery evolves, some drawing phases may cease to - * exist and new ones may be invented. If you need a particularly specific - * use of these codes, consult Austin and/or be prepared to revise your code - * as X-Plane evolves. + * Metaphases provide access to the beginning and end of the 3d (scene) and + * 2d (cockpit) drawing in a manner that is independent of new phases added + * via X-Plane implementation. + * + * **NOTE**: As of XPLM302 the legacy 3D drawing phases (xplm_Phase_FirstScene + * to xplm_Phase_LastScene) are deprecated. When running under X-Plane 11.50 + * with the modern Vulkan or Metal backend, X-Plane will no longer call + * these drawing phases. There is a new drawing phase, xplm_Phase_Modern3D, + * which is supported under OpenGL and Vulkan which is called out roughly + * where the old before xplm_Phase_Airplanes phase was for blending. This + * phase is *NOT* supported under Metal and comes with potentially + * substantial performance overhead. Please do *NOT* opt into this phase if + * you don't do any actual drawing that requires the depth buffer in some + * way! + * + * **WARNING**: As X-Plane's scenery evolves, some drawing phases may cease to + * exist and new ones may be invented. If you need a particularly specific + * use of these codes, consult Austin and/or be prepared to revise your code + * as X-Plane evolves. * */ enum { - /* This is the earliest point at which you can draw in 3-d. */ - xplm_Phase_FirstScene = 0 +#if defined(XPLM_DEPRECATED) + /* Deprecated as of XPLM302. This is the earliest point at which you can draw * + * in 3-d. */ + xplm_Phase_FirstScene = 0, - /* Drawing of land and water. */ - , - xplm_Phase_Terrain = 5 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated as of XPLM302. Drawing of land and water. */ + xplm_Phase_Terrain = 5, - /* Drawing runways and other airport detail. */ - , - xplm_Phase_Airports = 10 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated as of XPLM302. Drawing runways and other airport detail. */ + xplm_Phase_Airports = 10, - /* Drawing roads, trails, trains, etc. */ - , - xplm_Phase_Vectors = 15 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated as of XPLM302. Drawing roads, trails, trains, etc. */ + xplm_Phase_Vectors = 15, - /* 3-d objects (houses, smokestacks, etc. */ - , - xplm_Phase_Objects = 20 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated as of XPLM302. 3-d objects (houses, smokestacks, etc. */ + xplm_Phase_Objects = 20, - /* External views of airplanes, both yours and the AI aircraft. */ - , - xplm_Phase_Airplanes = 25 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated as of XPLM302. External views of airplanes, both yours and the * + * AI aircraft. */ + xplm_Phase_Airplanes = 25, - /* This is the last point at which you can draw in 3-d. */ - , - xplm_Phase_LastScene = 30 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated as of XPLM302. This is the last point at which you can draw in * + * 3-d. */ + xplm_Phase_LastScene = 30, - /* This is the first phase where you can draw in 2-d. */ - , - xplm_Phase_FirstCockpit = 35 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM302) + /* A chance to do modern 3D drawing. */ + xplm_Phase_Modern3D = 31, - /* The non-moving parts of the aircraft panel. */ - , - xplm_Phase_Panel = 40 +#endif /* XPLM302 */ + /* This is the first phase where you can draw in 2-d. */ + xplm_Phase_FirstCockpit = 35, - /* The moving parts of the aircraft panel. */ - , - xplm_Phase_Gauges = 45 + /* The non-moving parts of the aircraft panel. */ + xplm_Phase_Panel = 40, - /* Floating windows from plugins. */ - , - xplm_Phase_Window = 50 + /* The moving parts of the aircraft panel. */ + xplm_Phase_Gauges = 45, - /* The last change to draw in 2d. */ - , - xplm_Phase_LastCockpit = 55 + /* Floating windows from plugins. */ + xplm_Phase_Window = 50, + + /* The last chance to draw in 2d. */ + xplm_Phase_LastCockpit = 55, #if defined(XPLM200) - /* 3-d Drawing for the local map. Use regular OpenGL coordinates to draw in - * * this phase. */ - , - xplm_Phase_LocalMap3D = 100 + /* Removed as of XPLM300; Use the full-blown XPLMMap API instead. */ + xplm_Phase_LocalMap3D = 100, #endif /* XPLM200 */ #if defined(XPLM200) - /* 2-d Drawing of text over the local map. */ - , - xplm_Phase_LocalMap2D = 101 + /* Removed as of XPLM300; Use the full-blown XPLMMap API instead. */ + xplm_Phase_LocalMap2D = 101, #endif /* XPLM200 */ #if defined(XPLM200) - /* Drawing of the side-profile view in the local map screen. */ - , - xplm_Phase_LocalMapProfile = 102 + /* Removed as of XPLM300; Use the full-blown XPLMMap API instead. */ + xplm_Phase_LocalMapProfile = 102, #endif /* XPLM200 */ @@ -178,563 +220,1436 @@ typedef int XPLMDrawingPhase; /* * XPLMDrawCallback_f - * + * * This is the prototype for a low level drawing callback. You are passed in * the phase and whether it is before or after. If you are before the phase, - * return 1 to let x-plane draw or 0 to suppress x-plane drawing. If you are + * return 1 to let X-Plane draw or 0 to suppress X-Plane drawing. If you are * after the phase the return value is ignored. - * + * * Refcon is a unique value that you specify when registering the callback, * allowing you to slip a pointer to your own data to the callback. - * + * * Upon entry the OpenGL context will be correctly set up for you and OpenGL * will be in 'local' coordinates for 3d drawing and panel coordinates for 2d - * drawing. The OpenGL state (texturing, etc.) will be unknown. + * drawing. The OpenGL state (texturing, etc.) will be unknown. * */ -typedef int (*XPLMDrawCallback_f)(XPLMDrawingPhase inPhase, - int inIsBefore, - void *inRefcon); - -/* - * XPLMKeySniffer_f - * - * This is the prototype for a low level key-sniffing function. Window-based - * UI _should not use this_! The windowing system provides high-level - * mediated keyboard access. By comparison, the key sniffer provides low - * level keyboard access. - * - * Key sniffers are provided to allow libraries to provide non-windowed user - * interaction. For example, the MUI library uses a key sniffer to do pop-up - * text entry. - * - * inKey is the character pressed, inRefCon is a value you supply during - * registration. Return 1 to pass the key on to the next sniffer, the window - * mgr, x-plane, or whomever is down stream. Return 0 to consume the key. - * - * Warning: this API declares virtual keys as a signed character; however the - * VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values - * (that is 0x80 instead of -0x80). So you may need to cast the incoming vkey - * to an unsigned char to get correct comparisons in C. - * - */ -typedef int (*XPLMKeySniffer_f)(char inChar, - XPLMKeyFlags inFlags, - char inVirtualKey, - void *inRefcon); +typedef int (* XPLMDrawCallback_f)( + XPLMDrawingPhase inPhase, + int inIsBefore, + void * inRefcon); /* * XPLMRegisterDrawCallback - * + * * This routine registers a low level drawing callback. Pass in the phase you - * want to be called for and whether you want to be called before or after. + * want to be called for and whether you want to be called before or after. * This routine returns 1 if the registration was successful, or 0 if the - * phase does not exist in this version of x-plane. You may register a + * phase does not exist in this version of X-Plane. You may register a * callback multiple times for the same or different phases as long as the * refcon is unique each time. + * + * Note that this function will likely be removed during the X-Plane 11 run as + * part of the transition to Vulkan/Metal/etc. See the XPLMInstance API for + * future-proof drawing of 3-D objects. * */ -XPLM_API int XPLMRegisterDrawCallback(XPLMDrawCallback_f inCallback, - XPLMDrawingPhase inPhase, - int inWantsBefore, - void *inRefcon); +XPLM_API int XPLMRegisterDrawCallback( + XPLMDrawCallback_f inCallback, + XPLMDrawingPhase inPhase, + int inWantsBefore, + void * inRefcon); /* * XPLMUnregisterDrawCallback - * + * * This routine unregisters a draw callback. You must unregister a callback - * for each time you register a callback if you have registered it multiple + * for each time you register a callback if you have registered it multiple * times with different refcons. The routine returns 1 if it can find the * callback to unregister, 0 otherwise. + * + * Note that this function will likely be removed during the X-Plane 11 run as + * part of the transition to Vulkan/Metal/etc. See the XPLMInstance API for + * future-proof drawing of 3-D objects. * */ -XPLM_API int XPLMUnregisterDrawCallback(XPLMDrawCallback_f inCallback, - XPLMDrawingPhase inPhase, - int inWantsBefore, - void *inRefcon); +XPLM_API int XPLMUnregisterDrawCallback( + XPLMDrawCallback_f inCallback, + XPLMDrawingPhase inPhase, + int inWantsBefore, + void * inRefcon); + +#if defined(XPLM400) +/*************************************************************************** + * AVIONICS API + ***************************************************************************/ +/* + * Drawing callbacks for before and after X-Plane draws the instrument screen + * can be registered for every cockpit device. If the user plane does not + * have the device installed, your callback will not be called! Use the + * return value to enable or disable X-Plane's drawing. By drawing into the + * framebuffer of the avionics device, your modifications will be visible + * regardless whether the device's screen is in a 3d cockpit or a popup + * window. + * + */ + /* - * XPLMRegisterKeySniffer - * - * This routine registers a key sniffing callback. You specify whether you - * want to sniff before the window system, or only sniff keys the window - * system does not consume. You should ALMOST ALWAYS sniff non-control keys - * after the window system. When the window system consumes a key, it is - * because the user has "focused" a window. Consuming the key or taking - * action based on the key will produce very weird results. Returns 1 if - * successful. + * XPLMDeviceID + * + * This constant indicates the device we want to override or enhance. We can + * get a callback before or after each item. * */ -XPLM_API int XPLMRegisterKeySniffer(XPLMKeySniffer_f inCallback, - int inBeforeWindows, - void *inRefcon); +enum { + /* GNS430, pilot side. */ + xplm_device_GNS430_1 = 0, + + /* GNS430, copilot side. */ + xplm_device_GNS430_2 = 1, + + /* GNS530, pilot side. */ + xplm_device_GNS530_1 = 2, + + /* GNS530, copilot side. */ + xplm_device_GNS530_2 = 3, + + /* generic airliner CDU, pilot side. */ + xplm_device_CDU739_1 = 4, + + /* generic airliner CDU, copilot side. */ + xplm_device_CDU739_2 = 5, + + /* G1000 Primary Flight Display, pilot side. */ + xplm_device_G1000_PFD_1 = 6, + + /* G1000 Multifunction Display. */ + xplm_device_G1000_MFD = 7, + + /* G1000 Primary Flight Display, copilot side. */ + xplm_device_G1000_PFD_2 = 8, + + /* Primus CDU, pilot side. */ + xplm_device_CDU815_1 = 9, + + /* Primus CDU, copilot side. */ + xplm_device_CDU815_2 = 10, + + /* Primus Primary Flight Display, pilot side. */ + xplm_device_Primus_PFD_1 = 11, + + /* Primus Primary Flight Display, copilot side. */ + xplm_device_Primus_PFD_2 = 12, + + /* Primus Multifunction Display, pilot side. */ + xplm_device_Primus_MFD_1 = 13, + + /* Primus Multifunction Display, copilot side. */ + xplm_device_Primus_MFD_2 = 14, + + /* Primus Multifunction Display, central. */ + xplm_device_Primus_MFD_3 = 15, + + /* Primus Radio Management Unit, pilot side. */ + xplm_device_Primus_RMU_1 = 16, + + /* Primus Radio Management Unit, copilot side. */ + xplm_device_Primus_RMU_2 = 17, + + +}; +typedef int XPLMDeviceID; /* - * XPLMUnregisterKeySniffer - * - * This routine unregisters a key sniffer. You must unregister a key sniffer - * for every time you register one with the exact same signature. Returns 1 - * if successful. + * XPLMAvionicsCallback_f + * + * This is the prototype for your drawing callback. You are passed in the + * device you are enhancing/replacing, and whether it is before or after + * X-Plane drawing. If you are before X-Plane, return 1 to let X-Plane draw or + * 0 to suppress X-Plane drawing. If you are after the phase the return value + * is ignored. + * + * Refcon is a unique value that you specify when registering the callback, + * allowing you to slip a pointer to your own data to the callback. + * + * Upon entry the OpenGL context will be correctly set up for you and OpenGL + * will be in panel coordinates for 2d drawing. The OpenGL state (texturing, + * etc.) will be unknown. * */ -XPLM_API int XPLMUnregisterKeySniffer(XPLMKeySniffer_f inCallback, - int inBeforeWindows, - void *inRefcon); +typedef int (* XPLMAvionicsCallback_f)( + XPLMDeviceID inDeviceID, + int inIsBefore, + void * inRefcon); +/* + * XPLMAvionicsID + * + * This is an opaque identifier for an avionics display that you enhance or + * replace. When you register your callbacks (via + * XPLMRegisterAvionicsCallbacksEx()), you will specify callbacks to handle + * drawing, and get back such a handle. + * + */ +typedef void * XPLMAvionicsID; + +/* + * XPLMCustomizeAvionics_t + * + * The XPLMCustomizeAvionics_t structure defines all of the parameters used to + * replace or enhance avionics for using XPLMRegisterAvionicsCallbacksEx(). + * The structure will be expanded in future SDK APIs to include more features. + * Always set the structSize member to the size of your struct in bytes! + * + */ +typedef struct { + /* Used to inform XPLMRegisterAvionicsCallbacksEx() of the SDK version you * + * compiled against; should always be set to sizeof(XPLMCustomizeAvionics_t) */ + int structSize; + /* Which avionics device you want your drawing applied to. */ + XPLMDeviceID deviceId; + /* The draw callback to be called before X-Plane draws. */ + XPLMAvionicsCallback_f drawCallbackBefore; + /* The draw callback to be called after X-Plane has drawn. */ + XPLMAvionicsCallback_f drawCallbackAfter; + /* A reference which will be passed into each of your draw callbacks. Use this* + * to pass information to yourself as needed. */ + void * refcon; +} XPLMCustomizeAvionics_t; + +/* + * XPLMRegisterAvionicsCallbacksEx + * + * This routine registers your callbacks for a device. This returns a handle. + * If the returned handle is NULL, there was a problem interpreting your + * input, most likely the struct size was wrong for your SDK version. If the + * returned handle is not NULL, your callbacks will be called according to + * schedule as long as your plugin is not deactivated, or unloaded, or your + * call XPLMUnregisterAvionicsCallbacks(). + * + */ +XPLM_API XPLMAvionicsID XPLMRegisterAvionicsCallbacksEx( + XPLMCustomizeAvionics_t * inParams); + +/* + * XPLMUnregisterAvionicsCallbacks + * + * This routine unregisters your callbacks for a device. They will no longer + * be called. + * + */ +XPLM_API void XPLMUnregisterAvionicsCallbacks( + XPLMAvionicsID inAvionicsId); + +#endif /* XPLM400 */ /*************************************************************************** * WINDOW API ***************************************************************************/ /* - * Window API, for higher level drawing with UI interaction. - * - * Note: all 2-d (and thus all window drawing) is done in 'cockpit pixels'. - * Even when the OpenGL window contains more than 1024x768 pixels, the cockpit - * drawing is magnified so that only 1024x768 pixels are available. + * The window API provides a high-level abstraction for drawing with UI + * interaction. + * + * Windows may operate in one of two modes: legacy (for plugins compiled + * against old versions of the XPLM, as well as windows created via the + * deprecated XPLMCreateWindow() function, rather than XPLMCreateWindowEx()), + * or modern (for windows compiled against the XPLM300 or newer API, and + * created via XPLMCreateWindowEx()). + * + * Modern windows have access to new X-Plane 11 windowing features, like + * support for new positioning modes (including being "popped out" into their + * own first-class window in the operating system). They can also optionally + * be decorated in the style of X-Plane 11 windows (like the map). + * + * Modern windows operate in "boxel" units. A boxel ("box of pixels") is a + * unit of virtual pixels which, depending on X-Plane's scaling, may + * correspond to an arbitrary NxN "box" of real pixels on screen. Because + * X-Plane handles this scaling automatically, you can effectively treat the + * units as though you were simply drawing in pixels, and know that when + * X-Plane is running with 150% or 200% scaling, your drawing will be + * automatically scaled (and likewise all mouse coordinates, screen bounds, + * etc. will also be auto-scaled). + * + * In contrast, legacy windows draw in true screen pixels, and thus tend to + * look quite small when X-Plane is operating in a scaled mode. + * + * Legacy windows have their origin in the lower left of the main X-Plane + * window. In contrast, since modern windows are not constrained to the main + * window, they have their origin in the lower left of the entire global + * desktop space, and the lower left of the main X-Plane window is not + * guaranteed to be (0, 0). In both cases, x increases as you move left, and y + * increases as you move up. * */ /* - * XPLMMouseStatus + * XPLMWindowID + * + * This is an opaque identifier for a window. You use it to control your + * window. When you create a window (via either XPLMCreateWindow() or + * XPLMCreateWindowEx()), you will specify callbacks to handle drawing, mouse + * interaction, etc. * - * When the mouse is clicked, your mouse click routine is called repeatedly. + */ +typedef void * XPLMWindowID; + +/* + * XPLMDrawWindow_f + * + * A callback to handle 2-D drawing of your window. You are passed in your + * window and its refcon. Draw the window. You can use other XPLM functions + * from this header to find the current dimensions of your window, etc. When + * this callback is called, the OpenGL context will be set properly for 2-D + * window drawing. + * + * **Note**: Because you are drawing your window over a background, you can + * make a translucent window easily by simply not filling in your entire + * window's bounds. + * + */ +typedef void (* XPLMDrawWindow_f)( + XPLMWindowID inWindowID, + void * inRefcon); + +/* + * XPLMHandleKey_f + * + * This function is called when a key is pressed or keyboard focus is taken + * away from your window. If losingFocus is 1, you are losing the keyboard + * focus, otherwise a key was pressed and inKey contains its character. + * + * The window ID passed in will be your window for key presses, or the other + * window taking focus when losing focus. Note that in the modern plugin + * system, often focus is taken by the window manager itself; for this resaon, + * the window ID may be zero when losing focus, and you should not write code + * that depends onit. + * + * The refcon passed in will be the one from registration, for both key + * presses and losing focus. + * + * Warning: this API declares virtual keys as a signed character; however the + * VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values + * (that is 0x80 instead of -0x80). So you may need to cast the incoming vkey + * to an unsigned char to get correct comparisons in C. + * + */ +typedef void (* XPLMHandleKey_f)( + XPLMWindowID inWindowID, + char inKey, + XPLMKeyFlags inFlags, + char inVirtualKey, + void * inRefcon, + int losingFocus); + +/* + * XPLMMouseStatus + * + * When the mouse is clicked, your mouse click routine is called repeatedly. * It is first called with the mouse down message. It is then called zero or * more times with the mouse-drag message, and finally it is called once with * the mouse up message. All of these messages will be directed to the same - * window. + * window; you are guaranteed to not receive a drag or mouse-up event without + * first receiving the corresponding mouse-down. * */ enum { - xplm_MouseDown = 1 + xplm_MouseDown = 1, - , - xplm_MouseDrag = 2 + xplm_MouseDrag = 2, - , - xplm_MouseUp = 3 + xplm_MouseUp = 3, }; typedef int XPLMMouseStatus; +/* + * XPLMHandleMouseClick_f + * + * You receive this call for one of three events: + * + * - when the user clicks the mouse button down + * - (optionally) when the user drags the mouse after a down-click, but before + * the up-click + * - when the user releases the down-clicked mouse button. + * + * You receive the x and y of the click, your window, and a refcon. Return 1 + * to consume the click, or 0 to pass it through. + * + * WARNING: passing clicks through windows (as of this writing) causes mouse + * tracking problems in X-Plane; do not use this feature! + * + * The units for x and y values match the units used in your window. Thus, for + * "modern" windows (those created via XPLMCreateWindowEx() and compiled + * against the XPLM300 library), the units are boxels, while legacy windows + * will get pixels. Legacy windows have their origin in the lower left of the + * main X-Plane window, while modern windows have their origin in the lower + * left of the global desktop space. In both cases, x increases as you move + * right, and y increases as you move up. + * + */ +typedef int (* XPLMHandleMouseClick_f)( + XPLMWindowID inWindowID, + int x, + int y, + XPLMMouseStatus inMouse, + void * inRefcon); + #if defined(XPLM200) /* * XPLMCursorStatus - * + * * XPLMCursorStatus describes how you would like X-Plane to manage the cursor. - * See XPLMHandleCursor_f for more info. + * See XPLMHandleCursor_f for more info. * */ enum { - /* X-Plane manages the cursor normally, plugin does not affect the cusrsor. - */ - xplm_CursorDefault = 0 + /* X-Plane manages the cursor normally, plugin does not affect the cusrsor. */ + xplm_CursorDefault = 0, - /* X-Plane hides the cursor. */ - , - xplm_CursorHidden = 1 + /* X-Plane hides the cursor. */ + xplm_CursorHidden = 1, - /* X-Plane shows the cursor as the default arrow. */ - , - xplm_CursorArrow = 2 + /* X-Plane shows the cursor as the default arrow. */ + xplm_CursorArrow = 2, - /* X-Plane shows the cursor but lets you select an OS cursor. */ - , - xplm_CursorCustom = 3 + /* X-Plane shows the cursor but lets you select an OS cursor. */ + xplm_CursorCustom = 3, }; typedef int XPLMCursorStatus; #endif /* XPLM200 */ -/* - * XPLMWindowID - * - * This is an opaque identifier for a window. You use it to control your - * window. When you create a window, you will specify callbacks to handle - * drawing and mouse interaction, etc. - * - */ -typedef void *XPLMWindowID; - -/* - * XPLMDrawWindow_f - * - * This function handles drawing. You are passed in your window and its - * refcon. Draw the window. You can use XPLM functions to find the current - * dimensions of your window, etc. When this callback is called, the OpenGL - * context will be set properly for cockpit drawing. NOTE: Because you are - * drawing your window over a background, you can make a translucent window - * easily by simply not filling in your entire window's bounds. - * - */ -typedef void (*XPLMDrawWindow_f)(XPLMWindowID inWindowID, void *inRefcon); - -/* - * XPLMHandleKey_f - * - * This function is called when a key is pressed or keyboard focus is taken - * away from your window. If losingFocus is 1, you are losign the keyboard - * focus, otherwise a key was pressed and inKey contains its character. You - * are also passewd your window and a refcon. Warning: this API declares - * virtual keys as a signed character; however the VKEY #define macros in - * XPLMDefs.h define the vkeys using unsigned values (that is 0x80 instead of - * -0x80). So you may need to cast the incoming vkey to an unsigned char to - * get correct comparisons in C. - * - */ -typedef void (*XPLMHandleKey_f)(XPLMWindowID inWindowID, - char inKey, - XPLMKeyFlags inFlags, - char inVirtualKey, - void *inRefcon, - int losingFocus); - -/* - * XPLMHandleMouseClick_f - * - * You receive this call when the mouse button is pressed down or released. - * Between then these two calls is a drag. You receive the x and y of the - * click, your window, and a refcon. Return 1 to consume the click, or 0 to - * pass it through. - * - * WARNING: passing clicks through windows (as of this writing) causes mouse - * tracking problems in X-Plane; do not use this feature! - * - */ -typedef int (*XPLMHandleMouseClick_f)(XPLMWindowID inWindowID, - int x, - int y, - XPLMMouseStatus inMouse, - void *inRefcon); - #if defined(XPLM200) /* * XPLMHandleCursor_f - * + * * The SDK calls your cursor status callback when the mouse is over your * plugin window. Return a cursor status code to indicate how you would like * X-Plane to manage the cursor. If you return xplm_CursorDefault, the SDK * will try lower-Z-order plugin windows, then let the sim manage the cursor. - * - * Note: you should never show or hide the cursor yourself - these APIs are - * typically reference-counted and thus cannot safely and predictably be used + * + * Note: you should never show or hide the cursor yourself---these APIs are + * typically reference-counted and thus cannot safely and predictably be used * by the SDK. Instead return one of xplm_CursorHidden to hide the cursor or * xplm_CursorArrow/xplm_CursorCustom to show the cursor. - * + * * If you want to implement a custom cursor by drawing a cursor in OpenGL, use * xplm_CursorHidden to hide the OS cursor and draw the cursor using a 2-d - * drawing callback (after xplm_Phase_Window is probably a good choice). If - * you want to use a custom OS-based cursor, use xplm_CursorCustom to ask - * X-Plane to show the cursor but not affect its image. You can then use an - * OS specific call like SetThemeCursor (Mac) or SetCursor/LoadCursor - * (Windows). + * drawing callback (after xplm_Phase_Window is probably a good choice, but + * see deprecation warnings on the drawing APIs!). If you want to use a + * custom OS-based cursor, use xplm_CursorCustom to ask X-Plane to show the + * cursor but not affect its image. You can then use an OS specific call like + * SetThemeCursor (Mac) or SetCursor/LoadCursor (Windows). + * + * The units for x and y values match the units used in your window. Thus, for + * "modern" windows (those created via XPLMCreateWindowEx() and compiled + * against the XPLM300 library), the units are boxels, while legacy windows + * will get pixels. Legacy windows have their origin in the lower left of the + * main X-Plane window, while modern windows have their origin in the lower + * left of the global desktop space. In both cases, x increases as you move + * right, and y increases as you move up. * */ -typedef XPLMCursorStatus (*XPLMHandleCursor_f)(XPLMWindowID inWindowID, - int x, - int y, - void *inRefcon); +typedef XPLMCursorStatus (* XPLMHandleCursor_f)( + XPLMWindowID inWindowID, + int x, + int y, + void * inRefcon); #endif /* XPLM200 */ #if defined(XPLM200) /* * XPLMHandleMouseWheel_f - * + * * The SDK calls your mouse wheel callback when one of the mouse wheels is - * turned within your window. Return 1 to consume the mouse wheel clicks or - * 0 to pass them on to a lower window. (You should consume mouse wheel - * clicks even if they do nothing if your window appears opaque to the user.) - * The number of clicks indicates how far the wheel was turned since the last - * callback. The wheel is 0 for the vertical axis or 1 for the horizontal axis - * (for OS/mouse combinations that support this). + * scrolled within your window. Return 1 to consume the mouse wheel movement + * or 0 to pass them on to a lower window. (If your window appears opaque to + * the user, you should consume mouse wheel scrolling even if it does + * nothing.) The number of "clicks" indicates how far the wheel was turned + * since the last callback. The wheel is 0 for the vertical axis or 1 for the + * horizontal axis (for OS/mouse combinations that support this). + * + * The units for x and y values match the units used in your window. Thus, for + * "modern" windows (those created via XPLMCreateWindowEx() and compiled + * against the XPLM300 library), the units are boxels, while legacy windows + * will get pixels. Legacy windows have their origin in the lower left of the + * main X-Plane window, while modern windows have their origin in the lower + * left of the global desktop space. In both cases, x increases as you move + * right, and y increases as you move up. * */ -typedef int (*XPLMHandleMouseWheel_f)(XPLMWindowID inWindowID, - int x, - int y, - int wheel, - int clicks, - void *inRefcon); +typedef int (* XPLMHandleMouseWheel_f)( + XPLMWindowID inWindowID, + int x, + int y, + int wheel, + int clicks, + void * inRefcon); #endif /* XPLM200 */ +#if defined(XPLM300) +/* + * XPLMWindowLayer + * + * XPLMWindowLayer describes where in the ordering of windows X-Plane should + * place a particular window. Windows in higher layers cover windows in lower + * layers. So, a given window might be at the top of its particular layer, but + * it might still be obscured by a window in a higher layer. (This happens + * frequently when floating windows, like X-Plane's map, are covered by a + * modal alert.) + * + * Your window's layer can only be specified when you create the window (in + * the XPLMCreateWindow_t you pass to XPLMCreateWindowEx()). For this reason, + * layering only applies to windows created with new X-Plane 11 GUI features. + * (Windows created using the older XPLMCreateWindow(), or windows compiled + * against a pre-XPLM300 version of the SDK will simply be placed in the + * flight overlay window layer.) + * + */ +enum { + /* The lowest layer, used for HUD-like displays while flying. */ + xplm_WindowLayerFlightOverlay = 0, + + /* Windows that "float" over the sim, like the X-Plane 11 map does. If you are* + * not sure which layer to create your window in, choose floating. */ + xplm_WindowLayerFloatingWindows = 1, + + /* An interruptive modal that covers the sim with a transparent black overlay * + * to draw the user's focus to the alert */ + xplm_WindowLayerModal = 2, + + /* "Growl"-style notifications that are visible in a corner of the screen, * + * even over modals */ + xplm_WindowLayerGrowlNotifications = 3, + + +}; +typedef int XPLMWindowLayer; +#endif /* XPLM300 */ + +#if defined(XPLM301) +/* + * XPLMWindowDecoration + * + * XPLMWindowDecoration describes how "modern" windows will be displayed. This + * impacts both how X-Plane draws your window as well as certain mouse + * handlers. + * + * Your window's decoration can only be specified when you create the window + * (in the XPLMCreateWindow_t you pass to XPLMCreateWindowEx()). + * + */ +enum { + /* X-Plane will draw no decoration for your window, and apply no automatic * + * click handlers. The window will not stop click from passing through its * + * bounds. This is suitable for "windows" which request, say, the full screen * + * bounds, then only draw in a small portion of the available area. */ + xplm_WindowDecorationNone = 0, + + /* The default decoration for "native" windows, like the map. Provides a solid* + * background, as well as click handlers for resizing and dragging the window.*/ + xplm_WindowDecorationRoundRectangle = 1, + + /* X-Plane will draw no decoration for your window, nor will it provide resize* + * handlers for your window edges, but it will stop clicks from passing * + * through your windows bounds. */ + xplm_WindowDecorationSelfDecorated = 2, + + /* Like self-decorated, but with resizing; X-Plane will draw no decoration for* + * your window, but it will stop clicks from passing through your windows * + * bounds, and provide automatic mouse handlers for resizing. */ + xplm_WindowDecorationSelfDecoratedResizable = 3, + + +}; +typedef int XPLMWindowDecoration; +#endif /* XPLM301 */ + #if defined(XPLM200) /* * XPLMCreateWindow_t - * + * * The XPMCreateWindow_t structure defines all of the parameters used to - * create a window using XPLMCreateWindowEx. The structure will be expanded - * in future SDK APIs to include more features. Always set the structSize - * member to the size of your struct in bytes! + * create a modern window using XPLMCreateWindowEx(). The structure will be + * expanded in future SDK APIs to include more features. Always set the + * structSize member to the size of your struct in bytes! + * + * All windows created by this function in the XPLM300 version of the API are + * created with the new X-Plane 11 GUI features. This means your plugin will + * get to "know" about the existence of X-Plane windows other than the main + * window. All drawing and mouse callbacks for your window will occur in + * "boxels," giving your windows automatic support for high-DPI scaling in + * X-Plane. In addition, your windows can opt-in to decoration with the + * X-Plane 11 window styling, and you can use the + * XPLMSetWindowPositioningMode() API to make your window "popped out" into a + * first-class operating system window. + * + * Note that this requires dealing with your window's bounds in "global + * desktop" positioning units, rather than the traditional panel coordinate + * system. In global desktop coordinates, the main X-Plane window may not have + * its origin at coordinate (0, 0), and your own window may have negative + * coordinates. Assuming you don't implicitly assume (0, 0) as your origin, + * the only API change you should need is to start using + * XPLMGetMouseLocationGlobal() rather than XPLMGetMouseLocation(), and + * XPLMGetScreenBoundsGlobal() instead of XPLMGetScreenSize(). + * + * If you ask to be decorated as a floating window, you'll get the blue window + * control bar and blue backing that you see in X-Plane 11's normal "floating" + * windows (like the map). * */ typedef struct { - int structSize; - int left; - int top; - int right; - int bottom; - int visible; - XPLMDrawWindow_f drawWindowFunc; - XPLMHandleMouseClick_f handleMouseClickFunc; - XPLMHandleKey_f handleKeyFunc; - XPLMHandleCursor_f handleCursorFunc; - XPLMHandleMouseWheel_f handleMouseWheelFunc; - void *refcon; + /* Used to inform XPLMCreateWindowEx() of the SDK version you compiled * + * against; should always be set to sizeof(XPLMCreateWindow_t) */ + int structSize; + /* Left bound, in global desktop boxels */ + int left; + /* Top bound, in global desktop boxels */ + int top; + /* Right bound, in global desktop boxels */ + int right; + /* Bottom bound, in global desktop boxels */ + int bottom; + int visible; + XPLMDrawWindow_f drawWindowFunc; + /* A callback to handle the user left-clicking within your window (or NULL to * + * ignore left clicks) */ + XPLMHandleMouseClick_f handleMouseClickFunc; + XPLMHandleKey_f handleKeyFunc; + XPLMHandleCursor_f handleCursorFunc; + XPLMHandleMouseWheel_f handleMouseWheelFunc; + /* A reference which will be passed into each of your window callbacks. Use * + * this to pass information to yourself as needed. */ + void * refcon; +#if defined(XPLM301) + /* Specifies the type of X-Plane 11-style "wrapper" you want around your * + * window, if any */ + XPLMWindowDecoration decorateAsFloatingWindow; +#endif /* XPLM301 */ +#if defined(XPLM300) + XPLMWindowLayer layer; +#endif /* XPLM300 */ +#if defined(XPLM300) + /* A callback to handle the user right-clicking within your window (or NULL to* + * ignore right clicks) */ + XPLMHandleMouseClick_f handleRightClickFunc; +#endif /* XPLM300 */ } XPLMCreateWindow_t; #endif /* XPLM200 */ -/* - * XPLMGetScreenSize - * - * This routine returns the size of the size of the X-Plane OpenGL window in - * pixels. Please note that this is not the size of the screen when doing - * 2-d drawing (the 2-d screen is currently always 1024x768, and graphics are - * scaled up by OpenGL when doing 2-d drawing for higher-res monitors). This - * number can be used to get a rough idea of the amount of detail the user - * will be able to see when drawing in 3-d. - * - */ -XPLM_API void XPLMGetScreenSize(int *outWidth, /* Can be NULL */ - int *outHeight); /* Can be NULL */ - -/* - * XPLMGetMouseLocation - * - * This routine returns the current mouse location in cockpit pixels. The - * bottom left corner of the display is 0,0. Pass NULL to not receive info - * about either parameter. - * - */ -XPLM_API void XPLMGetMouseLocation(int *outX, /* Can be NULL */ - int *outY); /* Can be NULL */ - -/* - * XPLMCreateWindow - * - * This routine creates a new window. Pass in the dimensions and offsets to - * the window's bottom left corner from the bottom left of the screen. You - * can specify whether the window is initially visible or not. Also, you pass - * in three callbacks to run the window and a refcon. This function returns a - * window ID you can use to refer to the new window. - * - * NOTE: windows do not have "frames"; you are responsible for drawing the - * background and frame of the window. Higher level libraries have routines - * which make this easy. - * - */ -XPLM_API XPLMWindowID XPLMCreateWindow(int inLeft, - int inTop, - int inRight, - int inBottom, - int inIsVisible, - XPLMDrawWindow_f inDrawCallback, - XPLMHandleKey_f inKeyCallback, - XPLMHandleMouseClick_f inMouseCallback, - void *inRefcon); - #if defined(XPLM200) /* * XPLMCreateWindowEx - * - * This routine creates a new window - you pass in an XPLMCreateWindow_t - * structure with all of the fields set in. You must set the structSize of - * the structure to the size of the actual structure you used. Also, you - * must provide funtions for every callback - you may not leave them null! - * (If you do not support the cursor or mouse wheel, use functions that return - * the default values.) The numeric values of the XPMCreateWindow_t structure - * correspond to the parameters of XPLMCreateWindow. + * + * This routine creates a new "modern" window. You pass in an + * XPLMCreateWindow_t structure with all of the fields set in. You must set + * the structSize of the structure to the size of the actual structure you + * used. Also, you must provide functions for every callback---you may not + * leave them null! (If you do not support the cursor or mouse wheel, use + * functions that return the default values.) * */ -XPLM_API XPLMWindowID XPLMCreateWindowEx(XPLMCreateWindow_t *inParams); +XPLM_API XPLMWindowID XPLMCreateWindowEx( + XPLMCreateWindow_t * inParams); #endif /* XPLM200 */ /* - * XPLMDestroyWindow - * - * This routine destroys a window. The callbacks are not called after this - * call. Keyboard focus is removed from the window before destroying it. + * XPLMCreateWindow + * + * Deprecated as of XPLM300. + * + * This routine creates a new legacy window. Unlike modern windows (created + * via XPLMCreateWindowEx()), legacy windows do not have access to X-Plane 11 + * features like automatic scaling for high-DPI screens, native window styles, + * or support for being "popped out" into first-class operating system + * windows. + * + * Pass in the dimensions and offsets to the window's bottom left corner from + * the bottom left of the screen. You can specify whether the window is + * initially visible or not. Also, you pass in three callbacks to run the + * window and a refcon. This function returns a window ID you can use to + * refer to the new window. + * + * NOTE: Legacy windows do not have "frames"; you are responsible for drawing + * the background and frame of the window. Higher level libraries have + * routines which make this easy. * */ -XPLM_API void XPLMDestroyWindow(XPLMWindowID inWindowID); +XPLM_API XPLMWindowID XPLMCreateWindow( + int inLeft, + int inTop, + int inRight, + int inBottom, + int inIsVisible, + XPLMDrawWindow_f inDrawCallback, + XPLMHandleKey_f inKeyCallback, + XPLMHandleMouseClick_f inMouseCallback, + void * inRefcon); + +/* + * XPLMDestroyWindow + * + * This routine destroys a window. The window's callbacks are not called + * after this call. Keyboard focus is removed from the window before + * destroying it. + * + */ +XPLM_API void XPLMDestroyWindow( + XPLMWindowID inWindowID); + +/* + * XPLMGetScreenSize + * + * This routine returns the size of the main X-Plane OpenGL window in pixels. + * This number can be used to get a rough idea of the amount of detail the + * user will be able to see when drawing in 3-d. + * + */ +XPLM_API void XPLMGetScreenSize( + int * outWidth, /* Can be NULL */ + int * outHeight); /* Can be NULL */ + +#if defined(XPLM300) +/* + * XPLMGetScreenBoundsGlobal + * + * This routine returns the bounds of the "global" X-Plane desktop, in boxels. + * Unlike the non-global version XPLMGetScreenSize(), this is multi-monitor + * aware. There are three primary consequences of multimonitor awareness. + * + * First, if the user is running X-Plane in full-screen on two or more + * monitors (typically configured using one full-screen window per monitor), + * the global desktop will be sized to include all X-Plane windows. + * + * Second, the origin of the screen coordinates is not guaranteed to be (0, + * 0). Suppose the user has two displays side-by-side, both running at 1080p. + * Suppose further that they've configured their OS to make the left display + * their "primary" monitor, and that X-Plane is running in full-screen on + * their right monitor only. In this case, the global desktop bounds would be + * the rectangle from (1920, 0) to (3840, 1080). If the user later asked + * X-Plane to draw on their primary monitor as well, the bounds would change + * to (0, 0) to (3840, 1080). + * + * Finally, if the usable area of the virtual desktop is not a perfect + * rectangle (for instance, because the monitors have different resolutions or + * because one monitor is configured in the operating system to be above and + * to the right of the other), the global desktop will include any wasted + * space. Thus, if you have two 1080p monitors, and monitor 2 is configured to + * have its bottom left touch monitor 1's upper right, your global desktop + * area would be the rectangle from (0, 0) to (3840, 2160). + * + * Note that popped-out windows (windows drawn in their own operating system + * windows, rather than "floating" within X-Plane) are not included in these + * bounds. + * + */ +XPLM_API void XPLMGetScreenBoundsGlobal( + int * outLeft, /* Can be NULL */ + int * outTop, /* Can be NULL */ + int * outRight, /* Can be NULL */ + int * outBottom); /* Can be NULL */ +#endif /* XPLM300 */ + +#if defined(XPLM300) +/* + * XPLMReceiveMonitorBoundsGlobal_f + * + * This function is informed of the global bounds (in boxels) of a particular + * monitor within the X-Plane global desktop space. Note that X-Plane must be + * running in full screen on a monitor in order for that monitor to be passed + * to you in this callback. + * + */ +typedef void (* XPLMReceiveMonitorBoundsGlobal_f)( + int inMonitorIndex, + int inLeftBx, + int inTopBx, + int inRightBx, + int inBottomBx, + void * inRefcon); +#endif /* XPLM300 */ + +#if defined(XPLM300) +/* + * XPLMGetAllMonitorBoundsGlobal + * + * This routine immediately calls you back with the bounds (in boxels) of each + * full-screen X-Plane window within the X-Plane global desktop space. Note + * that if a monitor is *not* covered by an X-Plane window, you cannot get its + * bounds this way. Likewise, monitors with only an X-Plane window (not in + * full-screen mode) will not be included. + * + * If X-Plane is running in full-screen and your monitors are of the same size + * and configured contiguously in the OS, then the combined global bounds of + * all full-screen monitors will match the total global desktop bounds, as + * returned by XPLMGetScreenBoundsGlobal(). (Of course, if X-Plane is running + * in windowed mode, this will not be the case. Likewise, if you have + * differently sized monitors, the global desktop space will include wasted + * space.) + * + * Note that this function's monitor indices match those provided by + * XPLMGetAllMonitorBoundsOS(), but the coordinates are different (since the + * X-Plane global desktop may not match the operating system's global desktop, + * and one X-Plane boxel may be larger than one pixel due to 150% or 200% + * scaling). + * + */ +XPLM_API void XPLMGetAllMonitorBoundsGlobal( + XPLMReceiveMonitorBoundsGlobal_f inMonitorBoundsCallback, + void * inRefcon); +#endif /* XPLM300 */ + +#if defined(XPLM300) +/* + * XPLMReceiveMonitorBoundsOS_f + * + * This function is informed of the global bounds (in pixels) of a particular + * monitor within the operating system's global desktop space. Note that a + * monitor index being passed to you here does not indicate that X-Plane is + * running in full screen on this monitor, or even that any X-Plane windows + * exist on this monitor. + * + */ +typedef void (* XPLMReceiveMonitorBoundsOS_f)( + int inMonitorIndex, + int inLeftPx, + int inTopPx, + int inRightPx, + int inBottomPx, + void * inRefcon); +#endif /* XPLM300 */ + +#if defined(XPLM300) +/* + * XPLMGetAllMonitorBoundsOS + * + * This routine immediately calls you back with the bounds (in pixels) of each + * monitor within the operating system's global desktop space. Note that + * unlike XPLMGetAllMonitorBoundsGlobal(), this may include monitors that have + * no X-Plane window on them. + * + * Note that this function's monitor indices match those provided by + * XPLMGetAllMonitorBoundsGlobal(), but the coordinates are different (since + * the X-Plane global desktop may not match the operating system's global + * desktop, and one X-Plane boxel may be larger than one pixel). + * + */ +XPLM_API void XPLMGetAllMonitorBoundsOS( + XPLMReceiveMonitorBoundsOS_f inMonitorBoundsCallback, + void * inRefcon); +#endif /* XPLM300 */ + +/* + * XPLMGetMouseLocation + * + * Deprecated in XPLM300. Modern windows should use + * XPLMGetMouseLocationGlobal() instead. + * + * This routine returns the current mouse location in pixels relative to the + * main X-Plane window. The bottom left corner of the main window is (0, 0). + * Pass NULL to not receive info about either parameter. + * + * Because this function gives the mouse position relative to the main X-Plane + * window (rather than in global bounds), this function should only be used by + * legacy windows. Modern windows should instead get the mouse position in + * global desktop coordinates using XPLMGetMouseLocationGlobal(). + * + * Note that unlike XPLMGetMouseLocationGlobal(), if the mouse goes outside + * the user's main monitor (for instance, to a pop out window or a secondary + * monitor), this function will not reflect it. + * + */ +XPLM_API void XPLMGetMouseLocation( + int * outX, /* Can be NULL */ + int * outY); /* Can be NULL */ + +#if defined(XPLM300) +/* + * XPLMGetMouseLocationGlobal + * + * Returns the current mouse location in global desktop boxels. Unlike + * XPLMGetMouseLocation(), the bottom left of the main X-Plane window is not + * guaranteed to be (0, 0)---instead, the origin is the lower left of the + * entire global desktop space. In addition, this routine gives the real mouse + * location when the mouse goes to X-Plane windows other than the primary + * display. Thus, it can be used with both pop-out windows and secondary + * monitors. + * + * This is the mouse location function to use with modern windows (i.e., those + * created by XPLMCreateWindowEx()). + * + * Pass NULL to not receive info about either parameter. + * + */ +XPLM_API void XPLMGetMouseLocationGlobal( + int * outX, /* Can be NULL */ + int * outY); /* Can be NULL */ +#endif /* XPLM300 */ /* * XPLMGetWindowGeometry - * - * This routine returns the position and size of a window in cockpit pixels. - * Pass NULL to not receive any paramter. + * + * This routine returns the position and size of a window. The units and + * coordinate system vary depending on the type of window you have. + * + * If this is a legacy window (one compiled against a pre-XPLM300 version of + * the SDK, or an XPLM300 window that was not created using + * XPLMCreateWindowEx()), the units are pixels relative to the main X-Plane + * display. + * + * If, on the other hand, this is a new X-Plane 11-style window (compiled + * against the XPLM300 SDK and created using XPLMCreateWindowEx()), the units + * are global desktop boxels. + * + * Pass NULL to not receive any paramter. * */ -XPLM_API void XPLMGetWindowGeometry(XPLMWindowID inWindowID, - int *outLeft, /* Can be NULL */ - int *outTop, /* Can be NULL */ - int *outRight, /* Can be NULL */ - int *outBottom); /* Can be NULL */ +XPLM_API void XPLMGetWindowGeometry( + XPLMWindowID inWindowID, + int * outLeft, /* Can be NULL */ + int * outTop, /* Can be NULL */ + int * outRight, /* Can be NULL */ + int * outBottom); /* Can be NULL */ /* * XPLMSetWindowGeometry - * - * This routine allows you to set the position or height aspects of a window. + * + * This routine allows you to set the position and size of a window. + * + * The units and coordinate system match those of XPLMGetWindowGeometry(). + * That is, modern windows use global desktop boxel coordinates, while legacy + * windows use pixels relative to the main X-Plane display. + * + * Note that this only applies to "floating" windows (that is, windows that + * are drawn within the X-Plane simulation windows, rather than being "popped + * out" into their own first-class operating system windows). To set the + * position of windows whose positioning mode is xplm_WindowPopOut, you'll + * need to instead use XPLMSetWindowGeometryOS(). * */ -XPLM_API void XPLMSetWindowGeometry(XPLMWindowID inWindowID, - int inLeft, - int inTop, - int inRight, - int inBottom); +XPLM_API void XPLMSetWindowGeometry( + XPLMWindowID inWindowID, + int inLeft, + int inTop, + int inRight, + int inBottom); + +#if defined(XPLM300) +/* + * XPLMGetWindowGeometryOS + * + * This routine returns the position and size of a "popped out" window (i.e., + * a window whose positioning mode is xplm_WindowPopOut), in operating system + * pixels. Pass NULL to not receive any parameter. + * + */ +XPLM_API void XPLMGetWindowGeometryOS( + XPLMWindowID inWindowID, + int * outLeft, /* Can be NULL */ + int * outTop, /* Can be NULL */ + int * outRight, /* Can be NULL */ + int * outBottom); /* Can be NULL */ +#endif /* XPLM300 */ + +#if defined(XPLM300) +/* + * XPLMSetWindowGeometryOS + * + * This routine allows you to set the position and size, in operating system + * pixel coordinates, of a popped out window (that is, a window whose + * positioning mode is xplm_WindowPopOut, which exists outside the X-Plane + * simulation window, in its own first-class operating system window). + * + * Note that you are responsible for ensuring both that your window is popped + * out (using XPLMWindowIsPoppedOut()) and that a monitor really exists at the + * OS coordinates you provide (using XPLMGetAllMonitorBoundsOS()). + * + */ +XPLM_API void XPLMSetWindowGeometryOS( + XPLMWindowID inWindowID, + int inLeft, + int inTop, + int inRight, + int inBottom); +#endif /* XPLM300 */ + +#if defined(XPLM301) +/* + * XPLMGetWindowGeometryVR + * + * Returns the width and height, in boxels, of a window in VR. Note that you + * are responsible for ensuring your window is in VR (using + * XPLMWindowIsInVR()). + * + */ +XPLM_API void XPLMGetWindowGeometryVR( + XPLMWindowID inWindowID, + int * outWidthBoxels, /* Can be NULL */ + int * outHeightBoxels); /* Can be NULL */ +#endif /* XPLM301 */ + +#if defined(XPLM301) +/* + * XPLMSetWindowGeometryVR + * + * This routine allows you to set the size, in boxels, of a window in VR (that + * is, a window whose positioning mode is xplm_WindowVR). + * + * Note that you are responsible for ensuring your window is in VR (using + * XPLMWindowIsInVR()). + * + */ +XPLM_API void XPLMSetWindowGeometryVR( + XPLMWindowID inWindowID, + int widthBoxels, + int heightBoxels); +#endif /* XPLM301 */ /* * XPLMGetWindowIsVisible - * - * This routine returns whether a window is visible. + * + * Returns true (1) if the specified window is visible. * */ -XPLM_API int XPLMGetWindowIsVisible(XPLMWindowID inWindowID); +XPLM_API int XPLMGetWindowIsVisible( + XPLMWindowID inWindowID); /* * XPLMSetWindowIsVisible - * - * This routine shows or hides a window. + * + * This routine shows or hides a window. * */ -XPLM_API void XPLMSetWindowIsVisible(XPLMWindowID inWindowID, int inIsVisible); +XPLM_API void XPLMSetWindowIsVisible( + XPLMWindowID inWindowID, + int inIsVisible); + +#if defined(XPLM300) +/* + * XPLMWindowIsPoppedOut + * + * True if this window has been popped out (making it a first-class window in + * the operating system), which in turn is true if and only if you have set + * the window's positioning mode to xplm_WindowPopOut. + * + * Only applies to modern windows. (Windows created using the deprecated + * XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of + * the SDK cannot be popped out.) + * + */ +XPLM_API int XPLMWindowIsPoppedOut( + XPLMWindowID inWindowID); +#endif /* XPLM300 */ + +#if defined(XPLM301) +/* + * XPLMWindowIsInVR + * + * True if this window has been moved to the virtual reality (VR) headset, + * which in turn is true if and only if you have set the window's positioning + * mode to xplm_WindowVR. + * + * Only applies to modern windows. (Windows created using the deprecated + * XPLMCreateWindow(), or windows compiled against a pre-XPLM301 version of + * the SDK cannot be moved to VR.) + * + */ +XPLM_API int XPLMWindowIsInVR( + XPLMWindowID inWindowID); +#endif /* XPLM301 */ + +#if defined(XPLM300) +/* + * XPLMSetWindowGravity + * + * A window's "gravity" controls how the window shifts as the whole X-Plane + * window resizes. A gravity of 1 means the window maintains its positioning + * relative to the right or top edges, 0 the left/bottom, and 0.5 keeps it + * centered. + * + * Default gravity is (0, 1, 0, 1), meaning your window will maintain its + * position relative to the top left and will not change size as its + * containing window grows. + * + * If you wanted, say, a window that sticks to the top of the screen (with a + * constant height), but which grows to take the full width of the window, you + * would pass (0, 1, 1, 1). Because your left and right edges would maintain + * their positioning relative to their respective edges of the screen, the + * whole width of your window would change with the X-Plane window. + * + * Only applies to modern windows. (Windows created using the deprecated + * XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of + * the SDK will simply get the default gravity.) + * + */ +XPLM_API void XPLMSetWindowGravity( + XPLMWindowID inWindowID, + float inLeftGravity, + float inTopGravity, + float inRightGravity, + float inBottomGravity); +#endif /* XPLM300 */ + +#if defined(XPLM300) +/* + * XPLMSetWindowResizingLimits + * + * Sets the minimum and maximum size of the client rectangle of the given + * window. (That is, it does not include any window styling that you might + * have asked X-Plane to apply on your behalf.) All resizing operations are + * constrained to these sizes. + * + * Only applies to modern windows. (Windows created using the deprecated + * XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of + * the SDK will have no minimum or maximum size.) + * + */ +XPLM_API void XPLMSetWindowResizingLimits( + XPLMWindowID inWindowID, + int inMinWidthBoxels, + int inMinHeightBoxels, + int inMaxWidthBoxels, + int inMaxHeightBoxels); +#endif /* XPLM300 */ + +#if defined(XPLM300) +/* + * XPLMWindowPositioningMode + * + * XPLMWindowPositionMode describes how X-Plane will position your window on + * the user's screen. X-Plane will maintain this positioning mode even as the + * user resizes their window or adds/removes full-screen monitors. + * + * Positioning mode can only be set for "modern" windows (that is, windows + * created using XPLMCreateWindowEx() and compiled against the XPLM300 SDK). + * Windows created using the deprecated XPLMCreateWindow(), or windows + * compiled against a pre-XPLM300 version of the SDK will simply get the + * "free" positioning mode. + * + */ +enum { + /* The default positioning mode. Set the window geometry and its future * + * position will be determined by its window gravity, resizing limits, and * + * user interactions. */ + xplm_WindowPositionFree = 0, + + /* Keep the window centered on the monitor you specify */ + xplm_WindowCenterOnMonitor = 1, + + /* Keep the window full screen on the monitor you specify */ + xplm_WindowFullScreenOnMonitor = 2, + + /* Like gui_window_full_screen_on_monitor, but stretches over *all* monitors * + * and popout windows. This is an obscure one... unless you have a very good * + * reason to need it, you probably don't! */ + xplm_WindowFullScreenOnAllMonitors = 3, + + /* A first-class window in the operating system, completely separate from the * + * X-Plane window(s) */ + xplm_WindowPopOut = 4, + +#if defined(XPLM301) + /* A floating window visible on the VR headset */ + xplm_WindowVR = 5, + +#endif /* XPLM301 */ + +}; +typedef int XPLMWindowPositioningMode; +#endif /* XPLM300 */ + +#if defined(XPLM300) +/* + * XPLMSetWindowPositioningMode + * + * Sets the policy for how X-Plane will position your window. + * + * Some positioning modes apply to a particular monitor. For those modes, you + * can pass a negative monitor index to position the window on the main + * X-Plane monitor (the screen with the X-Plane menu bar at the top). Or, if + * you have a specific monitor you want to position your window on, you can + * pass a real monitor index as received from, e.g., + * XPLMGetAllMonitorBoundsOS(). + * + * Only applies to modern windows. (Windows created using the deprecated + * XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of + * the SDK will always use xplm_WindowPositionFree.) + * + */ +XPLM_API void XPLMSetWindowPositioningMode( + XPLMWindowID inWindowID, + XPLMWindowPositioningMode inPositioningMode, + int inMonitorIndex); +#endif /* XPLM300 */ + +#if defined(XPLM300) +/* + * XPLMSetWindowTitle + * + * Sets the name for a window. This only applies to windows that opted-in to + * styling as an X-Plane 11 floating window (i.e., with styling mode + * xplm_WindowDecorationRoundRectangle) when they were created using + * XPLMCreateWindowEx(). + * + */ +XPLM_API void XPLMSetWindowTitle( + XPLMWindowID inWindowID, + const char * inWindowTitle); +#endif /* XPLM300 */ /* * XPLMGetWindowRefCon - * - * This routine returns a windows refcon, the unique value you can use for - * your own purposes. + * + * Returns a window's reference constant, the unique value you can use for + * your own purposes. * */ -XPLM_API void *XPLMGetWindowRefCon(XPLMWindowID inWindowID); +XPLM_API void * XPLMGetWindowRefCon( + XPLMWindowID inWindowID); /* * XPLMSetWindowRefCon - * - * This routine sets a window's reference constant. Use this to pass data to - * yourself in the callbacks. + * + * Sets a window's reference constant. Use this to pass data to yourself in + * the callbacks. * */ -XPLM_API void XPLMSetWindowRefCon(XPLMWindowID inWindowID, void *inRefcon); +XPLM_API void XPLMSetWindowRefCon( + XPLMWindowID inWindowID, + void * inRefcon); /* * XPLMTakeKeyboardFocus - * + * * This routine gives a specific window keyboard focus. Keystrokes will be - * sent to that window. Pass a window ID of 0 to pass keyboard strokes - * directly to X-Plane. + * sent to that window. Pass a window ID of 0 to remove keyboard focus from + * any plugin-created windows and instead pass keyboard strokes directly to + * X-Plane. * */ -XPLM_API void XPLMTakeKeyboardFocus(XPLMWindowID inWindow); +XPLM_API void XPLMTakeKeyboardFocus( + XPLMWindowID inWindow); + +/* + * XPLMHasKeyboardFocus + * + * Returns true (1) if the indicated window has keyboard focus. Pass a window + * ID of 0 to see if no plugin window has focus, and all keystrokes will go + * directly to X-Plane. + * + */ +XPLM_API int XPLMHasKeyboardFocus( + XPLMWindowID inWindow); /* * XPLMBringWindowToFront - * - * This routine brings the window to the front of the Z-order. Windows are - * brought to the front when they are created...beyond that you should make - * sure you are front before handling mouse clicks. + * + * This routine brings the window to the front of the Z-order for its layer. + * Windows are brought to the front automatically when they are created. + * Beyond that, you should make sure you are front before handling mouse + * clicks. + * + * Note that this only brings your window to the front of its layer + * (XPLMWindowLayer). Thus, if you have a window in the floating window layer + * (xplm_WindowLayerFloatingWindows), but there is a modal window (in layer + * xplm_WindowLayerModal) above you, you would still not be the true frontmost + * window after calling this. (After all, the window layers are strictly + * ordered, and no window in a lower layer can ever be above any window in a + * higher one.) * */ -XPLM_API void XPLMBringWindowToFront(XPLMWindowID inWindow); +XPLM_API void XPLMBringWindowToFront( + XPLMWindowID inWindow); /* * XPLMIsWindowInFront - * - * This routine returns true if you pass inthe ID of the frontmost visible - * window. + * + * This routine returns true if the window you passed in is the frontmost + * visible window in its layer (XPLMWindowLayer). + * + * Thus, if you have a window at the front of the floating window layer + * (xplm_WindowLayerFloatingWindows), this will return true even if there is a + * modal window (in layer xplm_WindowLayerModal) above you. (Not to worry, + * though: in such a case, X-Plane will not pass clicks or keyboard input down + * to your layer until the window above stops "eating" the input.) + * + * Note that legacy windows are always placed in layer + * xplm_WindowLayerFlightOverlay, while modern-style windows default to + * xplm_WindowLayerFloatingWindows. This means it's perfectly consistent to + * have two different plugin-created windows (one legacy, one modern) *both* + * be in the front (of their different layers!) at the same time. * */ -XPLM_API int XPLMIsWindowInFront(XPLMWindowID inWindow); +XPLM_API int XPLMIsWindowInFront( + XPLMWindowID inWindow); + +/*************************************************************************** + * KEY SNIFFERS + ***************************************************************************/ +/* + * Low-level keyboard handlers. Allows for intercepting keystrokes outside the + * normal rules of the user interface. + * + */ + + +/* + * XPLMKeySniffer_f + * + * This is the prototype for a low level key-sniffing function. Window-based + * UI _should not use this_! The windowing system provides high-level + * mediated keyboard access, via the callbacks you attach to your + * XPLMCreateWindow_t. By comparison, the key sniffer provides low level + * keyboard access. + * + * Key sniffers are provided to allow libraries to provide non-windowed user + * interaction. For example, the MUI library uses a key sniffer to do pop-up + * text entry. + * + * Return 1 to pass the key on to the next sniffer, the window manager, + * X-Plane, or whomever is down stream. Return 0 to consume the key. + * + * Warning: this API declares virtual keys as a signed character; however the + * VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values + * (that is 0x80 instead of -0x80). So you may need to cast the incoming vkey + * to an unsigned char to get correct comparisons in C. + * + */ +typedef int (* XPLMKeySniffer_f)( + char inChar, + XPLMKeyFlags inFlags, + char inVirtualKey, + void * inRefcon); + +/* + * XPLMRegisterKeySniffer + * + * This routine registers a key sniffing callback. You specify whether you + * want to sniff before the window system, or only sniff keys the window + * system does not consume. You should ALMOST ALWAYS sniff non-control keys + * after the window system. When the window system consumes a key, it is + * because the user has "focused" a window. Consuming the key or taking + * action based on the key will produce very weird results. Returns + * 1 if successful. + * + */ +XPLM_API int XPLMRegisterKeySniffer( + XPLMKeySniffer_f inCallback, + int inBeforeWindows, + void * inRefcon); + +/* + * XPLMUnregisterKeySniffer + * + * This routine unregisters a key sniffer. You must unregister a key sniffer + * for every time you register one with the exact same signature. Returns 1 + * if successful. + * + */ +XPLM_API int XPLMUnregisterKeySniffer( + XPLMKeySniffer_f inCallback, + int inBeforeWindows, + void * inRefcon); /*************************************************************************** * HOT KEYS ***************************************************************************/ /* - * Hot Keys - keystrokes that can be managed by others. + * Keystrokes that can be managed by others. These are lower-level than window + * keyboard handlers (i.e., callbacks you attach to your XPLMCreateWindow_t), + * but higher level than key sniffers. * */ /* * XPLMHotKey_f - * - * Your hot key callback simply takes a pointer of your choosing. + * + * Your hot key callback simply takes a pointer of your choosing. * */ -typedef void (*XPLMHotKey_f)(void *inRefcon); +typedef void (* XPLMHotKey_f)( + void * inRefcon); /* * XPLMHotKeyID - * - * Hot keys are identified by opaque IDs. + * + * An opaque ID used to identify a hot key. * */ -typedef void *XPLMHotKeyID; +typedef void * XPLMHotKeyID; /* * XPLMRegisterHotKey - * + * * This routine registers a hot key. You specify your preferred key stroke * virtual key/flag combination, a description of what your callback does (so * other plug-ins can describe the plug-in to the user for remapping) and a * callback function and opaque pointer to pass in). A new hot key ID is * returned. During execution, the actual key associated with your hot key - * may change, but you are insulated from this. + * may change, but you are insulated from this. * */ -XPLM_API XPLMHotKeyID XPLMRegisterHotKey(char inVirtualKey, - XPLMKeyFlags inFlags, - const char *inDescription, - XPLMHotKey_f inCallback, - void *inRefcon); +XPLM_API XPLMHotKeyID XPLMRegisterHotKey( + char inVirtualKey, + XPLMKeyFlags inFlags, + const char * inDescription, + XPLMHotKey_f inCallback, + void * inRefcon); /* * XPLMUnregisterHotKey - * - * This API unregisters a hot key. You can only register your own hot keys. + * + * Unregisters a hot key. You can only unregister your own hot keys. * */ -XPLM_API void XPLMUnregisterHotKey(XPLMHotKeyID inHotKey); +XPLM_API void XPLMUnregisterHotKey( + XPLMHotKeyID inHotKey); /* * XPLMCountHotKeys - * - * Returns the number of current hot keys. + * + * Returns the number of current hot keys. * */ -XPLM_API int XPLMCountHotKeys(void); +XPLM_API int XPLMCountHotKeys(void); /* * XPLMGetNthHotKey - * - * Returns a hot key by index, for iteration on all hot keys. + * + * Returns a hot key by index, for iteration on all hot keys. * */ -XPLM_API XPLMHotKeyID XPLMGetNthHotKey(int inIndex); +XPLM_API XPLMHotKeyID XPLMGetNthHotKey( + int inIndex); /* * XPLMGetHotKeyInfo - * - * Returns information about the hot key. Return NULL for any parameter you - * don't want info about. The description should be at least 512 chars long. + * + * Returns information about the hot key. Return NULL for any parameter you + * don't want info about. The description should be at least 512 chars long. * */ -XPLM_API void XPLMGetHotKeyInfo(XPLMHotKeyID inHotKey, - char *outVirtualKey, /* Can be NULL */ - XPLMKeyFlags *outFlags, /* Can be NULL */ - char *outDescription, /* Can be NULL */ - XPLMPluginID *outPlugin); /* Can be NULL */ +XPLM_API void XPLMGetHotKeyInfo( + XPLMHotKeyID inHotKey, + char * outVirtualKey, /* Can be NULL */ + XPLMKeyFlags * outFlags, /* Can be NULL */ + char * outDescription, /* Can be NULL */ + XPLMPluginID * outPlugin); /* Can be NULL */ /* * XPLMSetHotKeyCombination - * - * XPLMSetHotKeyCombination remaps a hot keys keystrokes. You may remap - * another plugin's keystrokes. + * + * Remaps a hot key's keystrokes. You may remap another plugin's keystrokes. * */ -XPLM_API void XPLMSetHotKeyCombination(XPLMHotKeyID inHotKey, - char inVirtualKey, - XPLMKeyFlags inFlags); +XPLM_API void XPLMSetHotKeyCombination( + XPLMHotKeyID inHotKey, + char inVirtualKey, + XPLMKeyFlags inFlags); #ifdef __cplusplus } diff --git a/XPSDK/CHeaders/XPLM/XPLMGraphics.h b/XPSDK/CHeaders/XPLM/XPLMGraphics.h index 0eb3630..d7aef52 100644 --- a/XPSDK/CHeaders/XPLM/XPLMGraphics.h +++ b/XPSDK/CHeaders/XPLM/XPLMGraphics.h @@ -2,44 +2,43 @@ #define _XPLMGraphics_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPLMGraphics + ***************************************************************************/ /* - * Graphics routines for X-Plane and OpenGL. - * * A few notes on coordinate systems: - * + * * X-Plane uses three kinds of coordinates. Global coordinates are specified * as latitude, longitude and elevation. This coordinate system never changes * but is not very precise. - * - * OpenGL (or 'local') coordinates are cartesian and shift with the plane. + * + * OpenGL (or 'local') coordinates are cartesian and shift with the plane. * They offer more precision and are used for 3-d OpenGL drawing. The X axis * is aligned east-west with positive X meaning east. The Y axis is aligned * straight up and down at the point 0,0,0 (but since the earth is round it is * not truly straight up and down at other points). The Z axis is aligned * north-south at 0, 0, 0 with positive Z pointing south (but since the earth * is round it isn't exactly north-south as you move east or west of 0, 0, 0). - * One unit is one meter and the point 0,0,0 is on the surface of the earth - * at sea level for some latitude and longitude picked by the sim such that - * the user's aircraft is reasonably nearby. - * - * Cockpit coordinates are 2d, with the X axis horizontal and the Y axis - * vertical. The point 0,0 is the bottom left and 1024,768 is the upper right - * of the screen. This is true no matter what resolution the user's monitor is - * in; when running in higher resolution, graphics will be scaled. - * + * One unit is one meter and the point 0,0,0 is on the surface of the earth at + * sea level for some latitude and longitude picked by the sim such that the + * user's aircraft is reasonably nearby. + * + * 2-d Panel coordinates are 2d, with the X axis horizontal and the Y axis + * vertical. The point 0,0 is the bottom left and 1024,768 is the upper + * right of the screen. This is true no matter what resolution the user's + * monitor is in; when running in higher resolution, graphics will be + * scaled. + * * Use X-Plane's routines to convert between global and local coordinates. Do * not attempt to do this conversion yourself; the precise 'roundness' of - * X-Plane's physics model may not match your own, and (to make things + * X-Plane's physics model may not match your own, and (to make things * weirder) the user can potentially customize the physics of the current - * planet. + * planet. * */ @@ -53,286 +52,306 @@ extern "C" { * X-PLANE GRAPHICS ***************************************************************************/ /* - * These routines allow you to use OpenGL with X-Plane. + * These routines allow you to use OpenGL with X-Plane. * */ /* * XPLMTextureID - * + * * XPLM Texture IDs name well-known textures in the sim for you to use. This * allows you to recycle textures from X-Plane, saving VRAM. + * + * *Warning*: do not use these enums. The only remaining use they have is to + * access the legacy compatibility v10 UI texture; if you need this, get it + * via the Widgets library. * */ enum { - /* The bitmap that contains window outlines, button outlines, fonts, etc. */ - xplm_Tex_GeneralInterface = 0 + /* The bitmap that contains window outlines, button outlines, fonts, etc. */ + xplm_Tex_GeneralInterface = 0, - /* The exterior paint for the user's aircraft (daytime). */ - , - xplm_Tex_AircraftPaint = 1 +#if defined(XPLM_DEPRECATED) + /* The exterior paint for the user's aircraft (daytime). */ + xplm_Tex_AircraftPaint = 1, - /* The exterior light map for the user's aircraft. */ - , - xplm_Tex_AircraftLiteMap = 2 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* The exterior light map for the user's aircraft. */ + xplm_Tex_AircraftLiteMap = 2, +#endif /* XPLM_DEPRECATED */ }; typedef int XPLMTextureID; /* * XPLMSetGraphicsState - * - * XPLMSetGraphicsState changes OpenGL's graphics state in a number of ways: - * - * inEnableFog - enables or disables fog, equivalent to: glEnable(GL_FOG); - * - * inNumberTexUnits - enables or disables a number of multitexturing units. If - * the number is 0, 2d texturing is disabled entirely, as in - * glDisable(GL_TEXTURE_2D); Otherwise, 2d texturing is enabled, and a - * number of multitexturing units are enabled sequentially, starting with - * unit 0, e.g. glActiveTextureARB(GL_TEXTURE0_ARB); glEnable - * (GL_TEXTURE_2D); - * - * inEnableLighting - enables or disables OpenGL lighting, e.g. - * glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); - * - * inEnableAlphaTesting - enables or disables the alpha test per pixel, e.g. - * glEnable(GL_ALPHA_TEST); - * - * inEnableAlphaBlending - enables or disables alpha blending per pixel, e.g. - * glEnable(GL_BLEND); - * - * inEnableDepthTesting - enables per pixel depth testing, as in - * glEnable(GL_DEPTH_TEST); - * - * inEnableDepthWriting - enables writing back of depth information to the - * depth bufffer, as in glDepthMask(GL_TRUE); - * + * + * XPLMSetGraphicsState changes OpenGL's fixed function pipeline state. You + * are not responsible for restoring any state that is accessed via + * XPLMSetGraphicsState, but you are responsible for not accessing this state + * directly. + * + * - inEnableFog - enables or disables fog, equivalent to: glEnable(GL_FOG); + * - inNumberTexUnits - enables or disables a number of multitexturing units. + * If the number is 0, 2d texturing is disabled entirely, as in + * glDisable(GL_TEXTURE_2D); Otherwise, 2d texturing is enabled, and a + * number of multitexturing units are enabled sequentially, starting with + * unit 0, e.g. glActiveTextureARB(GL_TEXTURE0_ARB); glEnable + * (GL_TEXTURE_2D); + * - inEnableLighting - enables or disables OpenGL lighting, e.g. + * glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); + * - inEnableAlphaTesting - enables or disables the alpha test per pixel, e.g. + * glEnable(GL_ALPHA_TEST); + * - inEnableAlphaBlending - enables or disables alpha blending per pixel, + * e.g. glEnable(GL_BLEND); + * - inEnableDepthTesting - enables per pixel depth testing, as in + * glEnable(GL_DEPTH_TEST); + * - inEnableDepthWriting - enables writing back of depth information to the + * depth bufffer, as in glDepthMask(GL_TRUE); + * * The purpose of this function is to change OpenGL state while keeping * X-Plane aware of the state changes; this keeps X-Plane from getting * surprised by OGL state changes, and prevents X-Plane and plug-ins from * having to set all state before all draws; XPLMSetGraphicsState internally * skips calls to change state that is already properly enabled. - * - * X-Plane does not have a 'default' OGL state to plug-ins; plug-ins should - * totally set OGL state before drawing. Use XPLMSetGraphicsState instead of - * any of the above OpenGL calls. - * + * + * X-Plane does not have a 'default' OGL state for plug-ins with respect to + * the above state vector; plug-ins should totally set OGL state using this + * API before drawing. Use XPLMSetGraphicsState instead of any of the above + * OpenGL calls. + * * WARNING: Any routine that performs drawing (e.g. XPLMDrawString or widget * code) may change X-Plane's state. Always set state before drawing after * unknown code has executed. + * + * *Deprecation Warnings*: X-Plane's lighting and fog environemnt is + * significantly more complex than the fixed function pipeline can express; + * do not assume that lighting and fog state is a good approximation for 3-d + * drawing. Prefer to use XPLMInstancing to draw objects. All calls to + * XPLMSetGraphicsState should have no fog or lighting. * */ -XPLM_API void XPLMSetGraphicsState(int inEnableFog, - int inNumberTexUnits, - int inEnableLighting, - int inEnableAlphaTesting, - int inEnableAlphaBlending, - int inEnableDepthTesting, - int inEnableDepthWriting); +XPLM_API void XPLMSetGraphicsState( + int inEnableFog, + int inNumberTexUnits, + int inEnableLighting, + int inEnableAlphaTesting, + int inEnableAlphaBlending, + int inEnableDepthTesting, + int inEnableDepthWriting); /* * XPLMBindTexture2d - * - * XPLMBindTexture2d changes what texture is bound to the 2d texturing target. - * This routine caches the current 2d texture across all texturing units in - * the sim and plug-ins, preventing extraneous binding. For example, consider - * several plug-ins running in series; if they all use the 'general interface' - * bitmap to do UI, calling this function will skip the rebinding of the - * general interface texture on all but the first plug-in, which can provide - * better frame rate son some graphics cards. - * + * + * XPLMBindTexture2d changes what texture is bound to the 2d texturing + * target. This routine caches the current 2d texture across all texturing + * units in the sim and plug-ins, preventing extraneous binding. For + * example, consider several plug-ins running in series; if they all use the + * 'general interface' bitmap to do UI, calling this function will skip the + * rebinding of the general interface texture on all but the first plug-in, + * which can provide better frame rate son some graphics cards. + * * inTextureID is the ID of the texture object to bind; inTextureUnit is a - * zero-based texture unit (e.g. 0 for the first one), up to a maximum of 4 - * units. (This number may increase in future versions of x-plane.) - * - * Use this routine instead of glBindTexture(GL_TEXTURE_2D, ....); + * zero-based texture unit (e.g. 0 for the first one), up to a maximum of 4 + * units. (This number may increase in future versions of X-Plane.) + * + * Use this routine instead of glBindTexture(GL_TEXTURE_2D, ....); * */ -XPLM_API void XPLMBindTexture2d(int inTextureNum, int inTextureUnit); +XPLM_API void XPLMBindTexture2d( + int inTextureNum, + int inTextureUnit); /* * XPLMGenerateTextureNumbers - * - * This routine generates unused texture numbers that a plug-in can use to - * safely bind textures. Use this routine instead of glGenTextures; - * glGenTextures will allocate texture numbers in ranges that X-Plane reserves - * for its own use but does not always use; for example, it might provide an - * ID within the range of textures reserved for terrain...loading a new .env - * file as the plane flies might then cause X-Plane to use this texture ID. - * X-Plane will then overwrite the plug-ins texture. This routine returns - * texture IDs that are out of X-Plane's usage range. + * + * Use this routine instead of glGenTextures to generate new texture object + * IDs. This routine historically ensured that plugins don't use texure IDs + * that X-Plane is reserving for its own use. * */ -XPLM_API void XPLMGenerateTextureNumbers(int *outTextureIDs, int inCount); +XPLM_API void XPLMGenerateTextureNumbers( + int * outTextureIDs, + int inCount); +#if defined(XPLM_DEPRECATED) /* * XPLMGetTexture - * - * XPLMGetTexture returns the OpenGL texture enumeration of an X-Plane texture - * based on a generic identifying code. For example, you can get the texture - * for X-Plane's UI bitmaps. This allows you to build new gauges that take - * advantage of x-plane's textures, for smooth artwork integration and also - * saving texture memory. Note that the texture might not be loaded yet, - * depending on what the plane's panel contains. - * - * OPEN ISSUE: We really need a way to make sure X-Plane loads this texture if - * it isn't around, or at least a way to find out whether it is loaded or not. + * + * XPLMGetTexture returns the OpenGL texture ID of an X-Plane texture based on + * a generic identifying code. For example, you can get the texture for + * X-Plane's UI bitmaps. * */ -XPLM_API int XPLMGetTexture(XPLMTextureID inTexture); +XPLM_API int XPLMGetTexture( + XPLMTextureID inTexture); +#endif /* XPLM_DEPRECATED */ /* * XPLMWorldToLocal - * + * * This routine translates coordinates from latitude, longitude, and altitude * to local scene coordinates. Latitude and longitude are in decimal degrees, * and altitude is in meters MSL (mean sea level). The XYZ coordinates are in - * meters in the local OpenGL coordinate system. + * meters in the local OpenGL coordinate system. * */ -XPLM_API void XPLMWorldToLocal(double inLatitude, - double inLongitude, - double inAltitude, - double *outX, - double *outY, - double *outZ); +XPLM_API void XPLMWorldToLocal( + double inLatitude, + double inLongitude, + double inAltitude, + double * outX, + double * outY, + double * outZ); /* * XPLMLocalToWorld - * + * * This routine translates a local coordinate triplet back into latitude, * longitude, and altitude. Latitude and longitude are in decimal degrees, * and altitude is in meters MSL (mean sea level). The XYZ coordinates are in * meters in the local OpenGL coordinate system. - * + * * NOTE: world coordinates are less precise than local coordinates; you should - * try to avoid round tripping from local to world and back. + * try to avoid round tripping from local to world and back. * */ -XPLM_API void XPLMLocalToWorld(double inX, - double inY, - double inZ, - double *outLatitude, - double *outLongitude, - double *outAltitude); +XPLM_API void XPLMLocalToWorld( + double inX, + double inY, + double inZ, + double * outLatitude, + double * outLongitude, + double * outAltitude); /* * XPLMDrawTranslucentDarkBox - * + * * This routine draws a translucent dark box, partially obscuring parts of the * screen but making text easy to read. This is the same graphics primitive - * used by X-Plane to show text files and ATC info. + * used by X-Plane to show text files and ATC info. * */ -XPLM_API void XPLMDrawTranslucentDarkBox(int inLeft, - int inTop, - int inRight, - int inBottom); +XPLM_API void XPLMDrawTranslucentDarkBox( + int inLeft, + int inTop, + int inRight, + int inBottom); /*************************************************************************** * X-PLANE TEXT ***************************************************************************/ -/* - * - * - */ - /* * XPLMFontID - * + * * X-Plane features some fixed-character fonts. Each font may have its own * metrics. - * + * * WARNING: Some of these fonts are no longer supported or may have changed * geometries. For maximum copmatibility, see the comments below. - * + * * Note: X-Plane 7 supports proportional-spaced fonts. Since no measuring * routine is available yet, the SDK will normally draw using a fixed-width * font. You can use a dataref to enable proportional font drawing on XP7 if - * you want to. + * you want to. * */ enum { - /* Mono-spaced font for user interface. Available in all versions of the - SDK. */ - xplmFont_Basic = 0 + /* Mono-spaced font for user interface. Available in all versions of the SDK.*/ + xplmFont_Basic = 0, - /* Deprecated, do not use. */ - , - xplmFont_Menus = 1 +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_Menus = 1, - /* Deprecated, do not use. */ - , - xplmFont_Metal = 2 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_Metal = 2, - /* Deprecated, do not use. */ - , - xplmFont_Led = 3 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_Led = 3, - /* Deprecated, do not use. */ - , - xplmFont_LedWide = 4 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_LedWide = 4, - /* Deprecated, do not use. */ - , - xplmFont_PanelHUD = 5 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_PanelHUD = 5, - /* Deprecated, do not use. */ - , - xplmFont_PanelEFIS = 6 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_PanelEFIS = 6, - /* Deprecated, do not use. */ - , - xplmFont_PanelGPS = 7 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_PanelGPS = 7, - /* Deprecated, do not use. */ - , - xplmFont_RadiosGA = 8 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_RadiosGA = 8, - /* Deprecated, do not use. */ - , - xplmFont_RadiosBC = 9 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_RadiosBC = 9, - /* Deprecated, do not use. */ - , - xplmFont_RadiosHM = 10 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_RadiosHM = 10, - /* Deprecated, do not use. */ - , - xplmFont_RadiosGANarrow = 11 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_RadiosGANarrow = 11, - /* Deprecated, do not use. */ - , - xplmFont_RadiosBCNarrow = 12 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_RadiosBCNarrow = 12, - /* Deprecated, do not use. */ - , - xplmFont_RadiosHMNarrow = 13 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_RadiosHMNarrow = 13, - /* Deprecated, do not use. */ - , - xplmFont_Timer = 14 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_Timer = 14, - /* Deprecated, do not use. */ - , - xplmFont_FullRound = 15 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_FullRound = 15, - /* Deprecated, do not use. */ - , - xplmFont_SmallRound = 16 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_SmallRound = 16, - /* Deprecated, do not use. */ - , - xplmFont_Menus_Localized = 17 +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + /* Deprecated, do not use. */ + xplmFont_Menus_Localized = 17, +#endif /* XPLM_DEPRECATED */ #if defined(XPLM200) - /* Proportional UI font. */ - , - xplmFont_Proportional = 18 + /* Proportional UI font. */ + xplmFont_Proportional = 18, #endif /* XPLM200 */ @@ -341,69 +360,74 @@ typedef int XPLMFontID; /* * XPLMDrawString - * + * * This routine draws a NULL termianted string in a given font. Pass in the * lower left pixel that the character is to be drawn onto. Also pass the * character and font ID. This function returns the x offset plus the width of * all drawn characters. The color to draw in is specified as a pointer to an * array of three floating point colors, representing RGB intensities from 0.0 - * to 1.0. + * to 1.0. * */ -XPLM_API void XPLMDrawString(float *inColorRGB, - int inXOffset, - int inYOffset, - char *inChar, - int *inWordWrapWidth, /* Can be NULL */ - XPLMFontID inFontID); +XPLM_API void XPLMDrawString( + float * inColorRGB, + int inXOffset, + int inYOffset, + char * inChar, + int * inWordWrapWidth, /* Can be NULL */ + XPLMFontID inFontID); /* * XPLMDrawNumber - * + * * This routine draws a number similar to the digit editing fields in * PlaneMaker and data output display in X-Plane. Pass in a color, a * position, a floating point value, and formatting info. Specify how many - * integer and how many decimal digits to show and whether to show a sign, as + * integer and how many decimal digits to show and whether to show a sign, as * well as a character set. This routine returns the xOffset plus width of the - * string drawn. + * string drawn. * */ -XPLM_API void XPLMDrawNumber(float *inColorRGB, - int inXOffset, - int inYOffset, - double inValue, - int inDigits, - int inDecimals, - int inShowSign, - XPLMFontID inFontID); +XPLM_API void XPLMDrawNumber( + float * inColorRGB, + int inXOffset, + int inYOffset, + double inValue, + int inDigits, + int inDecimals, + int inShowSign, + XPLMFontID inFontID); /* * XPLMGetFontDimensions - * + * * This routine returns the width and height of a character in a given font. * It also tells you if the font only supports numeric digits. Pass NULL if * you don't need a given field. Note that for a proportional font the width - * will be an arbitrary, hopefully average width. + * will be an arbitrary, hopefully average width. * */ -XPLM_API void XPLMGetFontDimensions(XPLMFontID inFontID, - int *outCharWidth, /* Can be NULL */ - int *outCharHeight, /* Can be NULL */ - int *outDigitsOnly); /* Can be NULL */ +XPLM_API void XPLMGetFontDimensions( + XPLMFontID inFontID, + int * outCharWidth, /* Can be NULL */ + int * outCharHeight, /* Can be NULL */ + int * outDigitsOnly); /* Can be NULL */ #if defined(XPLM200) /* * XPLMMeasureString - * - * This routine returns the width in pixels of a string using a given font. + * + * This routine returns the width in pixels of a string using a given font. * The string is passed as a pointer plus length (and does not need to be null * terminated); this is used to allow for measuring substrings. The return * value is floating point; it is possible that future font drawing may allow - * for fractional pixels. + * for fractional pixels. * */ -XPLM_API float - XPLMMeasureString(XPLMFontID inFontID, const char *inChar, int inNumChars); +XPLM_API float XPLMMeasureString( + XPLMFontID inFontID, + const char * inChar, + int inNumChars); #endif /* XPLM200 */ #ifdef __cplusplus diff --git a/XPSDK/CHeaders/XPLM/XPLMInstance.h b/XPSDK/CHeaders/XPLM/XPLMInstance.h new file mode 100644 index 0000000..d2a8f2c --- /dev/null +++ b/XPSDK/CHeaders/XPLM/XPLMInstance.h @@ -0,0 +1,136 @@ +#ifndef _XPLMInstance_h_ +#define _XPLMInstance_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 + * + */ + +/*************************************************************************** + * XPLMInstance + ***************************************************************************/ +/* + * This API provides instanced drawing of X-Plane objects (.obj files). In + * contrast to old drawing APIs, which required you to draw your own objects + * per-frame, the instancing API allows you to simply register an OBJ for + * drawing, then move or manipulate it later (as needed). + * + * This provides one tremendous benefit: it keeps all dataref operations for + * your object in one place. Because datarefs are main thread only, allowing + * dataref access anywhere is a serious performance bottleneck for the + * simulator---the whole simulator has to pause and wait for each dataref + * access. This performance penalty will only grow worse as X-Plane moves + * toward an ever more heavily multithreaded engine. + * + * The instancing API allows X-Plane to isolate all dataref manipulations for + * all plugin object drawing to one place, potentially providing huge + * performance gains. + * + * Here's how it works: + * + * When an instance is created, it provides a list of all datarefs you want to + * manipulate in for the OBJ in the future. This list of datarefs replaces the + * ad-hoc collections of dataref objects previously used by art assets. Then, + * per-frame, you can manipulate the instance by passing in a "block" of + * packed floats representing the current values of the datarefs for your + * instance. (Note that the ordering of this set of packed floats must exactly + * match the ordering of the datarefs when you created your instance.) + * + */ + +#include "XPLMDefs.h" +#include "XPLMScenery.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * Instance Creation and Destruction + ***************************************************************************/ +/* + * Registers and unregisters instances. + * + */ + + +/* + * XPLMInstanceRef + * + * An opaque handle to an instance. + * + */ +typedef void * XPLMInstanceRef; + +/* + * XPLMCreateInstance + * + * XPLMCreateInstance creates a new instance, managed by your plug-in, and + * returns a handle to the instance. A few important requirements: + * + * * The object passed in must be fully loaded and returned from the XPLM + * before you can create your instance; you cannot pass a null obj ref, nor + * can you change the ref later. + * + * * If you use any custom datarefs in your object, they must be registered + * before the object is loaded. This is true even if their data will be + * provided via the instance dataref list. + * + * * The instance dataref array must be a valid ptr to an array of at least + * one item that is null terminated. That is, if you do not want any + * datarefs, you must passa ptr to an array with a null item. You cannot + * pass null for this. + * + */ +XPLM_API XPLMInstanceRef XPLMCreateInstance( + XPLMObjectRef obj, + const char ** datarefs); + +/* + * XPLMDestroyInstance + * + * XPLMDestroyInstance destroys and deallocates your instance; once called, + * you are still responsible for releasing the OBJ ref. + * + * Tip: you can release your OBJ ref after you call XPLMCreateInstance as long + * as you never use it again; the instance will maintain its own reference to + * the OBJ and the object OBJ be deallocated when the instance is destroyed. + * + */ +XPLM_API void XPLMDestroyInstance( + XPLMInstanceRef instance); + +/*************************************************************************** + * Instance Manipulation + ***************************************************************************/ + +/* + * XPLMInstanceSetPosition + * + * Updates both the position of the instance and all datarefs you registered + * for it. Call this from a flight loop callback or UI callback. + * + * __DO NOT__ call XPLMInstanceSetPosition from a drawing callback; the whole + * point of instancing is that you do not need any drawing callbacks. Setting + * instance data from a drawing callback may have undefined consequences, and + * the drawing callback hurts FPS unnecessarily. + * + * The memory pointed to by the data pointer must be large enough to hold one + * float for every data ref you have registered, and must contain valid + * floating point data. + * + * BUG: before X-Plane 11.50, if you have no dataref registered, you must + * still pass a valid pointer for data and not null. + * + */ +XPLM_API void XPLMInstanceSetPosition( + XPLMInstanceRef instance, + const XPLMDrawInfo_t * new_position, + const float * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/XPSDK/CHeaders/XPLM/XPLMMap.h b/XPSDK/CHeaders/XPLM/XPLMMap.h new file mode 100644 index 0000000..8297471 --- /dev/null +++ b/XPSDK/CHeaders/XPLM/XPLMMap.h @@ -0,0 +1,628 @@ +#ifndef _XPLMMap_h_ +#define _XPLMMap_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 + * + */ + +/*************************************************************************** + * XPLMMap + ***************************************************************************/ +/* + * This API allows you to create new layers within X-Plane maps. Your layers + * can draw arbitrary OpenGL, but they conveniently also have access to + * X-Plane's built-in icon and label drawing functions. + * + * As of X-Plane 11, map drawing happens in three stages: + * + * 1. backgrounds and "fill," + * 2. icons, and + * 3. labels. + * + * Thus, all background drawing gets layered beneath all icons, which likewise + * get layered beneath all labels. Within each stage, the map obeys a + * consistent layer ordering, such that "fill" layers (layers that cover a + * large amount of map area, like the terrain and clouds) appear beneath + * "markings" layers (like airport icons). This ensures that layers with fine + * details don't get obscured by layers with larger details. + * + * The XPLM map API reflects both aspects of this draw layering: you can + * register a layer as providing either markings or fill, and X-Plane will + * draw your fill layers beneath your markings layers (regardless of + * registration order). Likewise, you are guaranteed that your layer's icons + * (added from within an icon callback) will go above your layer's OpenGL + * drawing, and your labels will go above your icons. + * + * The XPLM guarantees that all plugin-created fill layers go on top of all + * native X-Plane fill layers, and all plugin-created markings layers go on + * top of all X-Plane markings layers (with the exception of the aircraft + * icons). It also guarantees that the draw order of your own plugin's layers + * will be consistent. But, for layers created by different plugins, the only + * guarantee is that we will draw all of one plugin's layers of each type + * (fill, then markings), then all of the others'; we don't guarantee which + * plugin's fill and markings layers go on top of the other's. + * + * As of X-Plane 11, maps use true cartographic projections for their drawing, + * and different maps may use different projections. For that reason, all + * drawing calls include an opaque handle for the projection you should use to + * do the drawing. Any time you would draw at a particular latitude/longitude, + * you'll need to ask the projection to translate that position into "map + * coordinates." (Note that the projection is guaranteed not to change between + * calls to your prepare-cache hook, so if you cache your map coordinates + * ahead of time, there's no need to re-project them when you actually draw.) + * + * In addition to mapping normal latitude/longitude locations into map + * coordinates, the projection APIs also let you know the current heading for + * north. (Since X-Plane 11 maps can rotate to match the heading of the user's + * aircraft, it's not safe to assume that north is at zero degrees rotation.) + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(XPLM300) +/*************************************************************************** + * DRAWING CALLBACKS + ***************************************************************************/ +/* + * When you create a new map layer (using XPLMCreateMapLayer), you can provide + * any or all of these callbacks. They allow you to insert your own OpenGL + * drawing, text labels, and icons into the X-Plane map at the appropriate + * places, allowing your layer to behave as similarly to X-Plane's built-in + * layers as possible. + * + */ + + +/* + * XPLMMapLayerID + * + * This is an opaque handle for a plugin-created map layer. Pass it to the map + * drawing APIs from an appropriate callback to draw in the layer you created. + * + */ +typedef void * XPLMMapLayerID; + +/* + * XPLMMapProjectionID + * + * This is an opaque handle for a map projection. Pass it to the projection + * APIs to translate between map coordinates and latitude/longitudes. + * + */ +typedef void * XPLMMapProjectionID; + +/* + * XPLMMapStyle + * + * Indicates the visual style being drawn by the map. In X-Plane, the user can + * choose between a number of map types, and different map types may have use + * a different visual representation for the same elements (for instance, the + * visual style of the terrain layer changes drastically between the VFR and + * IFR layers), or certain layers may be disabled entirely in some map types + * (e.g., localizers are only visible in the IFR low-enroute style). + * + */ +enum { + xplm_MapStyle_VFR_Sectional = 0, + + xplm_MapStyle_IFR_LowEnroute = 1, + + xplm_MapStyle_IFR_HighEnroute = 2, + + +}; +typedef int XPLMMapStyle; + +/* + * XPLMMapDrawingCallback_f + * + * This is the OpenGL map drawing callback for plugin-created map layers. You + * can perform arbitrary OpenGL drawing from this callback, with one + * exception: changes to the Z-buffer are not permitted, and will result in + * map drawing errors. + * + * All drawing done from within this callback appears beneath all built-in + * X-Plane icons and labels, but above the built-in "fill" layers (layers + * providing major details, like terrain and water). Note, however, that the + * relative ordering between the drawing callbacks of different plugins is not + * guaranteed. + * + */ +typedef void (* XPLMMapDrawingCallback_f)( + XPLMMapLayerID inLayer, + const float * inMapBoundsLeftTopRightBottom, + float zoomRatio, + float mapUnitsPerUserInterfaceUnit, + XPLMMapStyle mapStyle, + XPLMMapProjectionID projection, + void * inRefcon); + +/* + * XPLMMapIconDrawingCallback_f + * + * This is the icon drawing callback that enables plugin-created map layers to + * draw icons using X-Plane's built-in icon drawing functionality. You can + * request an arbitrary number of PNG icons to be drawn via + * XPLMDrawMapIconFromSheet() from within this callback, but you may not + * perform any OpenGL drawing here. + * + * Icons enqueued by this function will appear above all OpenGL drawing + * (performed by your optional XPLMMapDrawingCallback_f), and above all + * built-in X-Plane map icons of the same layer type ("fill" or "markings," as + * determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note, + * however, that the relative ordering between the drawing callbacks of + * different plugins is not guaranteed. + * + */ +typedef void (* XPLMMapIconDrawingCallback_f)( + XPLMMapLayerID inLayer, + const float * inMapBoundsLeftTopRightBottom, + float zoomRatio, + float mapUnitsPerUserInterfaceUnit, + XPLMMapStyle mapStyle, + XPLMMapProjectionID projection, + void * inRefcon); + +/* + * XPLMMapLabelDrawingCallback_f + * + * This is the label drawing callback that enables plugin-created map layers + * to draw text labels using X-Plane's built-in labeling functionality. You + * can request an arbitrary number of text labels to be drawn via + * XPLMDrawMapLabel() from within this callback, but you may not perform any + * OpenGL drawing here. + * + * Labels enqueued by this function will appear above all OpenGL drawing + * (performed by your optional XPLMMapDrawingCallback_f), and above all + * built-in map icons and labels of the same layer type ("fill" or "markings," + * as determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note, + * however, that the relative ordering between the drawing callbacks of + * different plugins is not guaranteed. + * + */ +typedef void (* XPLMMapLabelDrawingCallback_f)( + XPLMMapLayerID inLayer, + const float * inMapBoundsLeftTopRightBottom, + float zoomRatio, + float mapUnitsPerUserInterfaceUnit, + XPLMMapStyle mapStyle, + XPLMMapProjectionID projection, + void * inRefcon); + +#endif /* XPLM300 */ +#if defined(XPLM300) +/*************************************************************************** + * LAYER MANAGEMENT CALLBACKS + ***************************************************************************/ +/* + * These are various "bookkeeping" callbacks that your map layer can receive + * (if you provide the callback in your XPLMCreateMapLayer_t). They allow you + * to manage the lifecycle of your layer, as well as cache any + * computationally-intensive preparation you might need for drawing. + * + */ + + +/* + * XPLMMapPrepareCacheCallback_f + * + * A callback used to allow you to cache whatever information your layer needs + * to draw in the current map area. + * + * This is called each time the map's total bounds change. This is typically + * triggered by new DSFs being loaded, such that X-Plane discards old, + * now-distant DSFs and pulls in new ones. At that point, the available bounds + * of the map also change to match the new DSF area. + * + * By caching just the information you need to draw in this area, your future + * draw calls can be made faster, since you'll be able to simply "splat" your + * precomputed information each frame. + * + * We guarantee that the map projection will not change between successive + * prepare cache calls, nor will any draw call give you bounds outside these + * total map bounds. So, if you cache the projected map coordinates of all the + * items you might want to draw in the total map area, you can be guaranteed + * that no draw call will be asked to do any new work. + * + */ +typedef void (* XPLMMapPrepareCacheCallback_f)( + XPLMMapLayerID inLayer, + const float * inTotalMapBoundsLeftTopRightBottom, + XPLMMapProjectionID projection, + void * inRefcon); + +/* + * XPLMMapWillBeDeletedCallback_f + * + * Called just before your map layer gets deleted. Because SDK-created map + * layers have the same lifetime as the X-Plane map that contains them, if the + * map gets unloaded from memory, your layer will too. + * + */ +typedef void (* XPLMMapWillBeDeletedCallback_f)( + XPLMMapLayerID inLayer, + void * inRefcon); + +#endif /* XPLM300 */ +#if defined(XPLM300) +/*************************************************************************** + * MAP LAYER CREATION AND DESTRUCTION + ***************************************************************************/ +/* + * Enables the creation of new map layers. Layers are created for a particular + * instance of the X-Plane map. For instance, if you want your layer to appear + * in both the normal map interface and the Instructor Operator Station (IOS), + * you would need two separate calls to XPLMCreateMapLayer(), with two + * different values for your XPLMCreateMapLayer_t::layer_name. + * + * Your layer's lifetime will be determined by the lifetime of the map it is + * created in. If the map is destroyed (on the X-Plane side), your layer will + * be too, and you'll receive a callback to your + * XPLMMapWillBeDeletedCallback_f. + * + */ + + +/* + * XPLMMapLayerType + * + * Indicates the type of map layer you are creating. Fill layers will always + * be drawn beneath markings layers. + * + */ +enum { + /* A layer that draws "fill" graphics, like weather patterns, terrain, etc. * + * Fill layers frequently cover a large portion of the visible map area. */ + xplm_MapLayer_Fill = 0, + + /* A layer that provides markings for particular map features, like NAVAIDs, * + * airports, etc. Even dense markings layers cover a small portion of the * + * total map area. */ + xplm_MapLayer_Markings = 1, + + +}; +typedef int XPLMMapLayerType; + +/* Globally unique identifier for X-Plane's Map window, used as the * + * mapToCreateLayerIn parameter in XPLMCreateMapLayer_t */ +#define XPLM_MAP_USER_INTERFACE "XPLM_MAP_USER_INTERFACE" + +/* Globally unique identifier for X-Plane's Instructor Operator Station * + * window, used as the mapToCreateLayerIn parameter in XPLMCreateMapLayer_t */ +#define XPLM_MAP_IOS "XPLM_MAP_IOS" + +/* + * XPLMCreateMapLayer_t + * + * This structure defines all of the parameters used to create a map layer + * using XPLMCreateMapLayer. The structure will be expanded in future SDK APIs + * to include more features. Always set the structSize member to the size of + * your struct in bytes! + * + * Each layer must be associated with exactly one map instance in X-Plane. + * That map, and that map alone, will call your callbacks. Likewise, when that + * map is deleted, your layer will be as well. + * + */ +typedef struct { + /* Used to inform XPLMCreateMapLayer() of the SDK version you compiled * + * against; should always be set to sizeof(XPLMCreateMapLayer_t) */ + int structSize; + /* Globally unique string identifying the map you want this layer to appear * + * in. As of XPLM300, this is limited to one of XPLM_MAP_USER_INTERFACE or * + * XPLM_MAP_IOS */ + const char * mapToCreateLayerIn; + /* The type of layer you are creating, used to determine draw order (all * + * plugin-created markings layers are drawn above all plugin-created fill * + * layers) */ + XPLMMapLayerType layerType; + /* Optional callback to inform you this layer is being deleted (due to its * + * owning map being destroyed) */ + XPLMMapWillBeDeletedCallback_f willBeDeletedCallback; + /* Optional callback you want to use to prepare your draw cache when the map * + * bounds change (set to NULL if you don't want this callback) */ + XPLMMapPrepareCacheCallback_f prepCacheCallback; + /* Optional callback you want to use for arbitrary OpenGL drawing, which goes * + * beneath all icons in the map's layering system (set to NULL if you don't * + * want this callback) */ + XPLMMapDrawingCallback_f drawCallback; + /* Optional callback you want to use for drawing icons, which go above all * + * built-in X-Plane icons (except the aircraft) in the map's layering system * + * (set to NULL if you don't want this callback) */ + XPLMMapIconDrawingCallback_f iconCallback; + /* Optional callback you want to use for drawing map labels, which go above * + * all built-in X-Plane icons and labels (except those of aircraft) in the * + * map's layering system (set to NULL if you don't want this callback) */ + XPLMMapLabelDrawingCallback_f labelCallback; + /* True if you want a checkbox to be created in the map UI to toggle this * + * layer on and off; false if the layer should simply always be enabled */ + int showUiToggle; + /* Short label to use for this layer in the user interface */ + const char * layerName; + /* A reference to arbitrary data that will be passed to your callbacks */ + void * refcon; +} XPLMCreateMapLayer_t; + +/* + * XPLMCreateMapLayer + * + * This routine creates a new map layer. You pass in an XPLMCreateMapLayer_t + * structure with all of the fields set in. You must set the structSize of + * the structure to the size of the actual structure you used. + * + * Returns NULL if the layer creation failed. This happens most frequently + * because the map you specified in your + * XPLMCreateMapLayer_t::mapToCreateLayerIn field doesn't exist (that is, if + * XPLMMapExists() returns 0 for the specified map). You can use + * XPLMRegisterMapCreationHook() to get a notification each time a new map is + * opened in X-Plane, at which time you can create layers in it. + * + */ +XPLM_API XPLMMapLayerID XPLMCreateMapLayer( + XPLMCreateMapLayer_t * inParams); + +/* + * XPLMDestroyMapLayer + * + * Destroys a map layer you created (calling your + * XPLMMapWillBeDeletedCallback_f if applicable). Returns true if a deletion + * took place. + * + */ +XPLM_API int XPLMDestroyMapLayer( + XPLMMapLayerID inLayer); + +/* + * XPLMMapCreatedCallback_f + * + * A callback to notify your plugin that a new map has been created in + * X-Plane. This is the best time to add a custom map layer using + * XPLMCreateMapLayer(). + * + * No OpenGL drawing is permitted within this callback. + * + */ +typedef void (* XPLMMapCreatedCallback_f)( + const char * mapIdentifier, + void * refcon); + +/* + * XPLMRegisterMapCreationHook + * + * Registers your callback to receive a notification each time a new map is + * constructed in X-Plane. This callback is the best time to add your custom + * map layer using XPLMCreateMapLayer(). + * + * Note that you will not be notified about any maps that already exist---you + * can use XPLMMapExists() to check for maps that were created previously. + * + */ +XPLM_API void XPLMRegisterMapCreationHook( + XPLMMapCreatedCallback_f callback, + void * refcon); + +/* + * XPLMMapExists + * + * Returns 1 if the map with the specified identifier already exists in + * X-Plane. In that case, you can safely call XPLMCreateMapLayer() specifying + * that your layer should be added to that map. + * + */ +XPLM_API int XPLMMapExists( + const char * mapIdentifier); + +#endif /* XPLM300 */ +#if defined(XPLM300) +/*************************************************************************** + * MAP DRAWING + ***************************************************************************/ +/* + * These APIs are only valid from within a map drawing callback (one of + * XPLMIconDrawingCallback_t or XPLMMapLabelDrawingCallback_f). Your drawing + * callbacks are registered when you create a new map layer as part of your + * XPLMCreateMapLayer_t. The functions here hook into X-Plane's built-in map + * drawing functionality for icons and labels, so that you get a consistent + * style with the rest of the X-Plane map. + * + * Note that the X-Plane 11 map introduces a strict ordering: layers of type + * xplm_MapLayer_Fill get drawn beneath all xplm_MapLayer_Markings layers. + * Likewise, all OpenGL drawing (performed in your layer's + * XPLMMapDrawingCallback_f) will appear beneath any icons and labels you + * draw. + * + */ + + +/* + * XPLMMapOrientation + * + * Indicates whether a map element should be match its rotation to the map + * itself, or to the user interface. For instance, the map itself may be + * rotated such that "up" matches the user's aircraft, but you may want to + * draw a text label such that it is always rotated zero degrees relative to + * the user's perspective. In that case, you would have it draw with UI + * orientation. + * + */ +enum { + /* Orient such that a 0 degree rotation matches the map's north */ + xplm_MapOrientation_Map = 0, + + /* Orient such that a 0 degree rotation is "up" relative to the user interface*/ + xplm_MapOrientation_UI = 1, + + +}; +typedef int XPLMMapOrientation; + +/* + * XPLMDrawMapIconFromSheet + * + * Enables plugin-created map layers to draw PNG icons using X-Plane's + * built-in icon drawing functionality. Only valid from within an + * XPLMIconDrawingCallback_t (but you can request an arbitrary number of icons + * to be drawn from within your callback). + * + * X-Plane will automatically manage the memory for your texture so that it + * only has to be loaded from disk once as long as you continue drawing it + * per-frame. (When you stop drawing it, the memory may purged in a "garbage + * collection" pass, require a load from disk in the future.) + * + * Instead of having X-Plane draw a full PNG, this method allows you to use UV + * coordinates to request a portion of the image to be drawn. This allows you + * to use a single texture load (of an icon sheet, for example) to draw many + * icons. Doing so is much more efficient than drawing a dozen different small + * PNGs. + * + * The UV coordinates used here treat the texture you load as being comprised + * of a number of identically sized "cells." You specify the width and height + * in cells (ds and dt, respectively), as well as the coordinates within the + * cell grid for the sub-image you'd like to draw. + * + * Note that you can use different ds and dt values in subsequent calls with + * the same texture sheet. This enables you to use icons of different sizes in + * the same sheet if you arrange them properly in the PNG. + * + * This function is only valid from within an XPLMIconDrawingCallback_t (but + * you can request an arbitrary number of icons to be drawn from within your + * callback). + * + */ +XPLM_API void XPLMDrawMapIconFromSheet( + XPLMMapLayerID layer, + const char * inPngPath, + int s, + int t, + int ds, + int dt, + float mapX, + float mapY, + XPLMMapOrientation orientation, + float rotationDegrees, + float mapWidth); + +/* + * XPLMDrawMapLabel + * + * Enables plugin-created map layers to draw text labels using X-Plane's + * built-in labeling functionality. Only valid from within an + * XPLMMapLabelDrawingCallback_f (but you can request an arbitrary number of + * text labels to be drawn from within your callback). + * + */ +XPLM_API void XPLMDrawMapLabel( + XPLMMapLayerID layer, + const char * inText, + float mapX, + float mapY, + XPLMMapOrientation orientation, + float rotationDegrees); + +#endif /* XPLM300 */ +#if defined(XPLM300) +/*************************************************************************** + * MAP PROJECTIONS + ***************************************************************************/ +/* + * As of X-Plane 11, the map draws using true cartographic projections, and + * different maps may use different projections. Thus, to draw at a particular + * latitude and longitude, you must first transform your real-world + * coordinates into map coordinates. + * + * The map projection is also responsible for giving you the current scale of + * the map. That is, the projection can tell you how many map units correspond + * to 1 meter at a given point. + * + * Finally, the map projection can give you the current rotation of the map. + * Since X-Plane 11 maps can rotate to match the heading of the aircraft, the + * map's rotation can potentially change every frame. + * + */ + + +/* + * XPLMMapProject + * + * Projects a latitude/longitude into map coordinates. This is the inverse of + * XPLMMapUnproject(). + * + * Only valid from within a map layer callback (one of + * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, + * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.) + * + */ +XPLM_API void XPLMMapProject( + XPLMMapProjectionID projection, + double latitude, + double longitude, + float * outX, + float * outY); + +/* + * XPLMMapUnproject + * + * Transforms map coordinates back into a latitude and longitude. This is the + * inverse of XPLMMapProject(). + * + * Only valid from within a map layer callback (one of + * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, + * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.) + * + */ +XPLM_API void XPLMMapUnproject( + XPLMMapProjectionID projection, + float mapX, + float mapY, + double * outLatitude, + double * outLongitude); + +/* + * XPLMMapScaleMeter + * + * Returns the number of map units that correspond to a distance of one meter + * at a given set of map coordinates. + * + * Only valid from within a map layer callback (one of + * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, + * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.) + * + */ +XPLM_API float XPLMMapScaleMeter( + XPLMMapProjectionID projection, + float mapX, + float mapY); + +/* + * XPLMMapGetNorthHeading + * + * Returns the heading (in degrees clockwise) from the positive Y axis in the + * cartesian mapping coordinate system to true north at the point passed in. + * You can use it as a clockwise rotational offset to align icons and other + * 2-d drawing with true north on the map, compensating for rotations in the + * map due to projection. + * + * Only valid from within a map layer callback (one of + * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, + * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.) + * + */ +XPLM_API float XPLMMapGetNorthHeading( + XPLMMapProjectionID projection, + float mapX, + float mapY); + +#endif /* XPLM300 */ +#ifdef __cplusplus +} +#endif + +#endif diff --git a/XPSDK/CHeaders/XPLM/XPLMMenus.h b/XPSDK/CHeaders/XPLM/XPLMMenus.h index a94d7dd..f5802ab 100644 --- a/XPSDK/CHeaders/XPLM/XPLMMenus.h +++ b/XPSDK/CHeaders/XPLM/XPLMMenus.h @@ -2,27 +2,46 @@ #define _XPLMMenus_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPLMMenus + ***************************************************************************/ /* - * XPLMMenus - Theory of Operation - * - * Plug-ins can create menus in the menu bar of X-Plane. This is done by + * Plug-ins can create menus in the menu bar of X-Plane. This is done by * creating a menu and then creating items. Menus are referred to by an - * opaque ID. Items are referred to by index number. For each menu and item - * you specify a void *. Per menu you specify a handler function that is - * called with each void * when the menu item is picked. Menu item indices - * are zero based. + * opaque ID. Items are referred to by (zero-based) index number. + * + * Menus are "sandboxed" between plugins---no plugin can access the menus of + * any other plugin. Furthermore, all menu indices are relative to your + * plugin's menus only; if your plugin creates two sub-menus in the Plugins + * menu at different times, it doesn't matter how many other plugins also + * create sub-menus of Plugins in the intervening time: your sub-menus will be + * given menu indices 0 and 1. (The SDK does some work in the back-end to + * filter out menus that are irrelevant to your plugin in order to deliver + * this consistency for each plugin.) + * + * When you create a menu item, you specify how we should handle clicks on + * that menu item. You can either have the XPLM trigger a callback (the + * XPLMMenuHandler_f associated with the menu that contains the item), or you + * can simply have a command be triggered (with no associated call to your + * menu handler). The advantage of the latter method is that X-Plane will + * display any keyboard shortcuts associated with the command. (In contrast, + * there are no keyboard shortcuts associated with menu handler callbacks with + * specific parameters.) + * + * Menu text in X-Plane is UTF8; X-Plane's character set covers latin, greek + * and cyrillic characters, Katakana, as well as some Japanese symbols. Some + * APIs have a inDeprecatedAndIgnored parameter that used to select a + * character set; since X-Plane 9 all localization is done via UTF-8 only. * */ #include "XPLMDefs.h" +#include "XPLMUtilities.h" #ifdef __cplusplus extern "C" { @@ -31,31 +50,24 @@ extern "C" { /*************************************************************************** * XPLM MENUS ***************************************************************************/ -/* - * - * - */ - /* * XPLMMenuCheck - * - * These enumerations define the various 'check' states for an X-Plane menu. - * 'checking' in x-plane actually appears as a light which may or may not be - * lit. So there are three possible states. + * + * These enumerations define the various 'check' states for an X-Plane menu. + * 'checking' in X-Plane actually appears as a light which may or may not be + * lit. So there are three possible states. * */ enum { - /* there is no symbol to the left of the menu item. */ - xplm_Menu_NoCheck = 0 + /* there is no symbol to the left of the menu item. */ + xplm_Menu_NoCheck = 0, - /* the menu has a mark next to it that is unmarked (not lit). */ - , - xplm_Menu_Unchecked = 1 + /* the menu has a mark next to it that is unmarked (not lit). */ + xplm_Menu_Unchecked = 1, - /* the menu has a mark next to it that is checked (lit). */ - , - xplm_Menu_Checked = 2 + /* the menu has a mark next to it that is checked (lit). */ + xplm_Menu_Checked = 2, }; @@ -63,34 +75,55 @@ typedef int XPLMMenuCheck; /* * XPLMMenuID - * - * This is a unique ID for each menu you create. + * + * This is a unique ID for each menu you create. * */ -typedef void *XPLMMenuID; +typedef void * XPLMMenuID; /* * XPLMMenuHandler_f - * + * * A menu handler function takes two reference pointers, one for the menu * (specified when the menu was created) and one for the item (specified when - * the item was created). + * the item was created). * */ -typedef void (*XPLMMenuHandler_f)(void *inMenuRef, void *inItemRef); +typedef void (* XPLMMenuHandler_f)( + void * inMenuRef, + void * inItemRef); /* * XPLMFindPluginsMenu - * + * * This function returns the ID of the plug-ins menu, which is created for you - * at startup. + * at startup. * */ XPLM_API XPLMMenuID XPLMFindPluginsMenu(void); +#if defined(XPLM300) +/* + * XPLMFindAircraftMenu + * + * This function returns the ID of the menu for the currently-loaded aircraft, + * used for showing aircraft-specific commands. + * + * The aircraft menu is created by X-Plane at startup, but it remains hidden + * until it is populated via XPLMAppendMenuItem() or + * XPLMAppendMenuItemWithCommand(). + * + * Only plugins loaded with the user's current aircraft are allowed to access + * the aircraft menu. For all other plugins, this will return NULL, and any + * attempts to add menu items to it will fail. + * + */ +XPLM_API XPLMMenuID XPLMFindAircraftMenu(void); +#endif /* XPLM300 */ + /* * XPLMCreateMenu - * + * * This function creates a new menu and returns its ID. It returns NULL if * the menu cannot be created. Pass in a parent menu ID and an item index to * create a submenu, or NULL for the parent menu to put the menu in the menu @@ -98,109 +131,156 @@ XPLM_API XPLMMenuID XPLMFindPluginsMenu(void); * pass a handler function and a menu reference value. Pass NULL for the * handler if you do not need callbacks from the menu (for example, if it only * contains submenus). - * + * * Important: you must pass a valid, non-empty menu title even if the menu is - * a submenu where the title is not visible. + * a submenu where the title is not visible. * */ -XPLM_API XPLMMenuID XPLMCreateMenu(const char *inName, - XPLMMenuID inParentMenu, - int inParentItem, - XPLMMenuHandler_f inHandler, - void *inMenuRef); +XPLM_API XPLMMenuID XPLMCreateMenu( + const char * inName, + XPLMMenuID inParentMenu, + int inParentItem, + XPLMMenuHandler_f inHandler, + void * inMenuRef); /* * XPLMDestroyMenu - * + * * This function destroys a menu that you have created. Use this to remove a - * submenu if necessary. (Normally this function will not be necessary.) + * submenu if necessary. (Normally this function will not be necessary.) * */ -XPLM_API void XPLMDestroyMenu(XPLMMenuID inMenuID); +XPLM_API void XPLMDestroyMenu( + XPLMMenuID inMenuID); /* * XPLMClearAllMenuItems - * + * * This function removes all menu items from a menu, allowing you to rebuild * it. Use this function if you need to change the number of items on a menu. * */ -XPLM_API void XPLMClearAllMenuItems(XPLMMenuID inMenuID); +XPLM_API void XPLMClearAllMenuItems( + XPLMMenuID inMenuID); /* * XPLMAppendMenuItem - * + * * This routine appends a new menu item to the bottom of a menu and returns * its index. Pass in the menu to add the item to, the items name, and a void - * * ref for this item. If you pass in inForceEnglish, this menu item will be - * drawn using the english character set no matter what language x-plane is - * running in. Otherwise the menu item will be drawn localized. (An example - * of why you'd want to do this is for a proper name.) See XPLMUtilities for - * determining the current langauge. + * * ref for this item. + * + * Returns a negative index if the append failed (due to an invalid parent + * menu argument). + * + * Note that all menu indices returned are relative to your plugin's menus + * only; if your plugin creates two sub-menus in the Plugins menu at different + * times, it doesn't matter how many other plugins also create sub-menus of + * Plugins in the intervening time: your sub-menus will be given menu indices + * 0 and 1. (The SDK does some work in the back-end to filter out menus that + * are irrelevant to your plugin in order to deliver this consistency for each + * plugin.) * */ -XPLM_API int XPLMAppendMenuItem(XPLMMenuID inMenu, - const char *inItemName, - void *inItemRef, - int inForceEnglish); +XPLM_API int XPLMAppendMenuItem( + XPLMMenuID inMenu, + const char * inItemName, + void * inItemRef, + int inDeprecatedAndIgnored); + +#if defined(XPLM300) +/* + * XPLMAppendMenuItemWithCommand + * + * Like XPLMAppendMenuItem(), but instead of the new menu item triggering the + * XPLMMenuHandler_f of the containiner menu, it will simply execute the + * command you pass in. Using a command for your menu item allows the user to + * bind a keyboard shortcut to the command and see that shortcut represented + * in the menu. + * + * Returns a negative index if the append failed (due to an invalid parent + * menu argument). + * + * Like XPLMAppendMenuItem(), all menu indices are relative to your plugin's + * menus only. + * + */ +XPLM_API int XPLMAppendMenuItemWithCommand( + XPLMMenuID inMenu, + const char * inItemName, + XPLMCommandRef inCommandToExecute); +#endif /* XPLM300 */ /* * XPLMAppendMenuSeparator - * - * This routine adds a seperator to the end of a menu. + * + * This routine adds a separator to the end of a menu. + * + * Returns a negative index if the append failed (due to an invalid parent + * menu argument). * */ -XPLM_API void XPLMAppendMenuSeparator(XPLMMenuID inMenu); +XPLM_API void XPLMAppendMenuSeparator( + XPLMMenuID inMenu); /* * XPLMSetMenuItemName - * + * * This routine changes the name of an existing menu item. Pass in the menu - * ID and the index of the menu item. + * ID and the index of the menu item. * */ -XPLM_API void XPLMSetMenuItemName(XPLMMenuID inMenu, - int inIndex, - const char *inItemName, - int inForceEnglish); +XPLM_API void XPLMSetMenuItemName( + XPLMMenuID inMenu, + int inIndex, + const char * inItemName, + int inDeprecatedAndIgnored); /* * XPLMCheckMenuItem - * - * Set whether a menu item is checked. Pass in the menu ID and item index. + * + * Set whether a menu item is checked. Pass in the menu ID and item index. * */ -XPLM_API void - XPLMCheckMenuItem(XPLMMenuID inMenu, int index, XPLMMenuCheck inCheck); +XPLM_API void XPLMCheckMenuItem( + XPLMMenuID inMenu, + int index, + XPLMMenuCheck inCheck); /* * XPLMCheckMenuItemState - * + * * This routine returns whether a menu item is checked or not. A menu item's - * check mark may be on or off, or a menu may not have an icon at all. + * check mark may be on or off, or a menu may not have an icon at all. * */ -XPLM_API void XPLMCheckMenuItemState(XPLMMenuID inMenu, - int index, - XPLMMenuCheck *outCheck); +XPLM_API void XPLMCheckMenuItemState( + XPLMMenuID inMenu, + int index, + XPLMMenuCheck * outCheck); /* * XPLMEnableMenuItem - * - * Sets whether this menu item is enabled. Items start out enabled. + * + * Sets whether this menu item is enabled. Items start out enabled. * */ -XPLM_API void XPLMEnableMenuItem(XPLMMenuID inMenu, int index, int enabled); +XPLM_API void XPLMEnableMenuItem( + XPLMMenuID inMenu, + int index, + int enabled); #if defined(XPLM210) /* * XPLMRemoveMenuItem - * + * * Removes one item from a menu. Note that all menu items below are moved up - * one; your plugin must track the change in index numbers. + * one; your plugin must track the change in index numbers. * */ -XPLM_API void XPLMRemoveMenuItem(XPLMMenuID inMenu, int inIndex); +XPLM_API void XPLMRemoveMenuItem( + XPLMMenuID inMenu, + int inIndex); #endif /* XPLM210 */ #ifdef __cplusplus diff --git a/XPSDK/CHeaders/XPLM/XPLMNavigation.h b/XPSDK/CHeaders/XPLM/XPLMNavigation.h index 8bdbde2..716caf0 100644 --- a/XPSDK/CHeaders/XPLM/XPLMNavigation.h +++ b/XPSDK/CHeaders/XPLM/XPLMNavigation.h @@ -2,25 +2,23 @@ #define _XPLMNavigation_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPLMNavigation + ***************************************************************************/ /* - * XPLMNavigation - THEORY OF OPERATION - * * The XPLM Navigation APIs give you some access to the navigation databases * inside X-Plane. X-Plane stores all navigation information in RAM, so by * using these APIs you can gain access to most information without having to * go to disk or parse the files yourself. - * + * * You can also use this API to program the FMS. You must use the navigation * APIs to find the nav-aids you want to program into the FMS, since the FMS - * is powered internally by x-plane's navigation database. + * is powered internally by X-Plane's navigation database. * */ @@ -33,63 +31,46 @@ extern "C" { /*************************************************************************** * NAVIGATION DATABASE ACCESS ***************************************************************************/ -/* - * - * - */ - /* * XPLMNavType - * + * * These enumerations define the different types of navaids. They are each * defined with a separate bit so that they may be bit-wise added together to * form sets of nav-aid types. - * + * * NOTE: xplm_Nav_LatLon is a specific lat-lon coordinate entered into the * FMS. It will not exist in the database, and cannot be programmed into the * FMS. Querying the FMS for navaids will return it. Use - * XPLMSetFMSEntryLatLon to set a lat/lon waypoint. + * XPLMSetFMSEntryLatLon to set a lat/lon waypoint. * */ enum { - xplm_Nav_Unknown = 0 + xplm_Nav_Unknown = 0, - , - xplm_Nav_Airport = 1 + xplm_Nav_Airport = 1, - , - xplm_Nav_NDB = 2 + xplm_Nav_NDB = 2, - , - xplm_Nav_VOR = 4 + xplm_Nav_VOR = 4, - , - xplm_Nav_ILS = 8 + xplm_Nav_ILS = 8, - , - xplm_Nav_Localizer = 16 + xplm_Nav_Localizer = 16, - , - xplm_Nav_GlideSlope = 32 + xplm_Nav_GlideSlope = 32, - , - xplm_Nav_OuterMarker = 64 + xplm_Nav_OuterMarker = 64, - , - xplm_Nav_MiddleMarker = 128 + xplm_Nav_MiddleMarker = 128, - , - xplm_Nav_InnerMarker = 256 + xplm_Nav_InnerMarker = 256, - , - xplm_Nav_Fix = 512 + xplm_Nav_Fix = 512, - , - xplm_Nav_DME = 1024 + xplm_Nav_DME = 1024, - , - xplm_Nav_LatLon = 2048 + xplm_Nav_LatLon = 2048, }; @@ -97,140 +78,133 @@ typedef int XPLMNavType; /* * XPLMNavRef - * + * * XPLMNavRef is an iterator into the navigation database. The navigation * database is essentially an array, but it is not necessarily densely * populated. The only assumption you can safely make is that like-typed - * nav-aids are grouped together. - * + * nav-aids are grouped together. + * * Use XPLMNavRef to refer to a nav-aid. - * + * * XPLM_NAV_NOT_FOUND is returned by functions that return an XPLMNavRef when - * the iterator must be invalid. + * the iterator must be invalid. * */ typedef int XPLMNavRef; -#define XPLM_NAV_NOT_FOUND -1 +#define XPLM_NAV_NOT_FOUND -1 /* * XPLMGetFirstNavAid - * + * * This returns the very first navaid in the database. Use this to traverse * the entire database. Returns XPLM_NAV_NOT_FOUND if the nav database is - * empty. + * empty. * */ XPLM_API XPLMNavRef XPLMGetFirstNavAid(void); /* * XPLMGetNextNavAid - * - * Given a nav aid ref, this routine returns the next navaid. It returns - * XPLM_NAV_NOT_FOUND if the nav aid passed in was invalid or if the navaid - * passed in was the last one in the database. Use this routine to iterate - * across all like-typed navaids or the entire database. - * - * WARNING: due to a bug in the SDK, when fix loading is disabled in the - * rendering settings screen, calling this routine with the last airport - * returns a bogus nav aid. Using this nav aid can crash x-plane. + * + * Given a valid nav aid ref, this routine returns the next navaid. It + * returns XPLM_NAV_NOT_FOUND if the nav aid passed in was invalid or if the + * navaid passed in was the last one in the database. Use this routine to + * iterate across all like-typed navaids or the entire database. * */ -XPLM_API XPLMNavRef XPLMGetNextNavAid(XPLMNavRef inNavAidRef); +XPLM_API XPLMNavRef XPLMGetNextNavAid( + XPLMNavRef inNavAidRef); /* * XPLMFindFirstNavAidOfType - * + * * This routine returns the ref of the first navaid of the given type in the * database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the - * database. You must pass exactly one nav aid type to this routine. - * - * WARNING: due to a bug in the SDK, when fix loading is disabled in the - * rendering settings screen, calling this routine with fixes returns a bogus - * nav aid. Using this nav aid can crash x-plane. + * database. You must pass exactly one nav aid type to this routine. * */ -XPLM_API XPLMNavRef XPLMFindFirstNavAidOfType(XPLMNavType inType); +XPLM_API XPLMNavRef XPLMFindFirstNavAidOfType( + XPLMNavType inType); /* * XPLMFindLastNavAidOfType - * + * * This routine returns the ref of the last navaid of the given type in the * database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the - * database. You must pass exactly one nav aid type to this routine. - * - * WARNING: due to a bug in the SDK, when fix loading is disabled in the - * rendering settings screen, calling this routine with fixes returns a bogus - * nav aid. Using this nav aid can crash x-plane. + * database. You must pass exactly one nav aid type to this routine. * */ -XPLM_API XPLMNavRef XPLMFindLastNavAidOfType(XPLMNavType inType); +XPLM_API XPLMNavRef XPLMFindLastNavAidOfType( + XPLMNavType inType); /* * XPLMFindNavAid - * + * * This routine provides a number of searching capabilities for the nav * database. XPLMFindNavAid will search through every nav aid whose type is * within inType (multiple types may be added together) and return any - * nav-aids found based on the following rules: - * - * If inLat and inLon are not NULL, the navaid nearest to that lat/lon will be - * returned, otherwise the last navaid found will be returned. - * - * If inFrequency is not NULL, then any navaids considered must match this - * frequency. Note that this will screen out radio beacons that do not have - * frequency data published (like inner markers) but not fixes and airports. - * - * If inNameFragment is not NULL, only navaids that contain the fragment in - * their name will be returned. - * - * If inIDFragment is not NULL, only navaids that contain the fragment in - * their IDs will be returned. - * + * nav-aids found based on the following rules: + * + * * If inLat and inLon are not NULL, the navaid nearest to that lat/lon will + * be returned, otherwise the last navaid found will be returned. + * + * * If inFrequency is not NULL, then any navaids considered must match this + * frequency. Note that this will screen out radio beacons that do not have + * frequency data published (like inner markers) but not fixes and airports. + * + * * If inNameFragment is not NULL, only navaids that contain the fragment in + * their name will be returned. + * + * * If inIDFragment is not NULL, only navaids that contain the fragment in + * their IDs will be returned. + * * This routine provides a simple way to do a number of useful searches: - * - * Find the nearest navaid on this frequency. Find the nearest airport. Find - * the VOR whose ID is "KBOS". Find the nearest airport whose name contains - * "Chicago". + * * Find the nearest navaid on this frequency. + * * Find the nearest airport. + * * Find the VOR whose ID is "KBOS". + * * Find the nearest airport whose name contains "Chicago". * */ -XPLM_API XPLMNavRef XPLMFindNavAid(const char *inNameFragment, /* Can be NULL */ - const char *inIDFragment, /* Can be NULL */ - float *inLat, /* Can be NULL */ - float *inLon, /* Can be NULL */ - int *inFrequency, /* Can be NULL */ - XPLMNavType inType); +XPLM_API XPLMNavRef XPLMFindNavAid( + const char * inNameFragment, /* Can be NULL */ + const char * inIDFragment, /* Can be NULL */ + float * inLat, /* Can be NULL */ + float * inLon, /* Can be NULL */ + int * inFrequency, /* Can be NULL */ + XPLMNavType inType); /* * XPLMGetNavAidInfo - * + * * This routine returns information about a navaid. Any non-null field is * filled out with information if it is available. - * + * * Frequencies are in the nav.dat convention as described in the X-Plane nav * database FAQ: NDB frequencies are exact, all others are multiplied by 100. - * + * * The buffer for IDs should be at least 6 chars and the buffer for names * should be at least 41 chars, but since these values are likely to go up, I * recommend passing at least 32 chars for IDs and 256 chars for names when * possible. - * + * * The outReg parameter tells if the navaid is within the local "region" of * loaded DSFs. (This information may not be particularly useful to plugins.) * The parameter is a single byte value 1 for true or 0 for false, not a C - * string. + * string. * */ -XPLM_API void XPLMGetNavAidInfo(XPLMNavRef inRef, - XPLMNavType *outType, /* Can be NULL */ - float *outLatitude, /* Can be NULL */ - float *outLongitude, /* Can be NULL */ - float *outHeight, /* Can be NULL */ - int *outFrequency, /* Can be NULL */ - float *outHeading, /* Can be NULL */ - char *outID, /* Can be NULL */ - char *outName, /* Can be NULL */ - char *outReg); /* Can be NULL */ +XPLM_API void XPLMGetNavAidInfo( + XPLMNavRef inRef, + XPLMNavType * outType, /* Can be NULL */ + float * outLatitude, /* Can be NULL */ + float * outLongitude, /* Can be NULL */ + float * outHeight, /* Can be NULL */ + int * outFrequency, /* Can be NULL */ + float * outHeading, /* Can be NULL */ + char * outID, /* Can be NULL */ + char * outName, /* Can be NULL */ + char * outReg); /* Can be NULL */ /*************************************************************************** * FLIGHT MANAGEMENT COMPUTER @@ -239,129 +213,144 @@ XPLM_API void XPLMGetNavAidInfo(XPLMNavRef inRef, * Note: the FMS works based on an array of entries. Indices into the array * are zero-based. Each entry is a nav-aid plus an altitude. The FMS tracks * the currently displayed entry and the entry that it is flying to. - * + * * The FMS must be programmed with contiguous entries, so clearing an entry at * the end shortens the effective flight plan. There is a max of 100 - * waypoints in the flight plan. + * waypoints in the flight plan. * */ /* * XPLMCountFMSEntries - * - * This routine returns the number of entries in the FMS. + * + * This routine returns the number of entries in the FMS. * */ -XPLM_API int XPLMCountFMSEntries(void); +XPLM_API int XPLMCountFMSEntries(void); /* * XPLMGetDisplayedFMSEntry - * - * This routine returns the index of the entry the pilot is viewing. + * + * This routine returns the index of the entry the pilot is viewing. * */ -XPLM_API int XPLMGetDisplayedFMSEntry(void); +XPLM_API int XPLMGetDisplayedFMSEntry(void); /* * XPLMGetDestinationFMSEntry - * - * This routine returns the index of the entry the FMS is flying to. + * + * This routine returns the index of the entry the FMS is flying to. * */ -XPLM_API int XPLMGetDestinationFMSEntry(void); +XPLM_API int XPLMGetDestinationFMSEntry(void); /* * XPLMSetDisplayedFMSEntry - * + * * This routine changes which entry the FMS is showing to the index specified. - * * + * */ -XPLM_API void XPLMSetDisplayedFMSEntry(int inIndex); +XPLM_API void XPLMSetDisplayedFMSEntry( + int inIndex); /* * XPLMSetDestinationFMSEntry - * - * This routine changes which entry the FMS is flying the aircraft toward. + * + * This routine changes which entry the FMS is flying the aircraft toward. * */ -XPLM_API void XPLMSetDestinationFMSEntry(int inIndex); +XPLM_API void XPLMSetDestinationFMSEntry( + int inIndex); /* * XPLMGetFMSEntryInfo - * - * This routine returns information about a given FMS entry. A reference to a - * navaid can be returned allowing you to find additional information (such as - * a frequency, ILS heading, name, etc.). Some information is available - * immediately. For a lat/lon entry, the lat/lon is returned by this routine - * but the navaid cannot be looked up (and the reference will be - * XPLM_NAV_NOT_FOUND. FMS name entry buffers should be at least 256 chars in - * length. + * + * This routine returns information about a given FMS entry. If the entry is + * an airport or navaid, a reference to a nav entry can be returned allowing + * you to find additional information (such as a frequency, ILS heading, name, + * etc.). Note that this reference can be XPLM_NAV_NOT_FOUND until the + * information has been looked up asynchronously, so after flightplan changes, + * it might take up to a second for this field to become populated. The other + * information is available immediately. For a lat/lon entry, the lat/lon is + * returned by this routine but the navaid cannot be looked up (and the + * reference will be XPLM_NAV_NOT_FOUND). FMS name entry buffers should be at + * least 256 chars in length. + * + * WARNING: Due to a bug in X-Plane prior to 11.31, the navaid reference will + * not be set to XPLM_NAV_NOT_FOUND while no data is available, and instead + * just remain the value of the variable that you passed the pointer to. + * Therefore, always initialize the variable to XPLM_NAV_NOT_FOUND before + * passing the pointer to this function. * */ -XPLM_API void XPLMGetFMSEntryInfo(int inIndex, - XPLMNavType *outType, /* Can be NULL */ - char *outID, /* Can be NULL */ - XPLMNavRef *outRef, /* Can be NULL */ - int *outAltitude, /* Can be NULL */ - float *outLat, /* Can be NULL */ - float *outLon); /* Can be NULL */ +XPLM_API void XPLMGetFMSEntryInfo( + int inIndex, + XPLMNavType * outType, /* Can be NULL */ + char * outID, /* Can be NULL */ + XPLMNavRef * outRef, /* Can be NULL */ + int * outAltitude, /* Can be NULL */ + float * outLat, /* Can be NULL */ + float * outLon); /* Can be NULL */ /* * XPLMSetFMSEntryInfo - * + * * This routine changes an entry in the FMS to have the destination navaid * passed in and the altitude specified. Use this only for airports, fixes, * and radio-beacon navaids. Currently of radio beacons, the FMS can only * support VORs and NDBs. Use the routines below to clear or fly to a lat/lon. * */ -XPLM_API void - XPLMSetFMSEntryInfo(int inIndex, XPLMNavRef inRef, int inAltitude); +XPLM_API void XPLMSetFMSEntryInfo( + int inIndex, + XPLMNavRef inRef, + int inAltitude); /* * XPLMSetFMSEntryLatLon - * + * * This routine changes the entry in the FMS to a lat/lon entry with the given - * coordinates. + * coordinates. * */ -XPLM_API void XPLMSetFMSEntryLatLon(int inIndex, - float inLat, - float inLon, - int inAltitude); +XPLM_API void XPLMSetFMSEntryLatLon( + int inIndex, + float inLat, + float inLon, + int inAltitude); /* * XPLMClearFMSEntry - * + * * This routine clears the given entry, potentially shortening the flight - * plan. + * plan. * */ -XPLM_API void XPLMClearFMSEntry(int inIndex); +XPLM_API void XPLMClearFMSEntry( + int inIndex); /*************************************************************************** * GPS RECEIVER ***************************************************************************/ /* - * These APIs let you read data from the GPS unit. + * These APIs let you read data from the GPS unit. * */ - /* * XPLMGetGPSDestinationType - * + * * This routine returns the type of the currently selected GPS destination, - * one of fix, airport, VOR or NDB. + * one of fix, airport, VOR or NDB. * */ XPLM_API XPLMNavType XPLMGetGPSDestinationType(void); /* * XPLMGetGPSDestination - * - * This routine returns the current GPS destination. + * + * This routine returns the current GPS destination. * */ XPLM_API XPLMNavRef XPLMGetGPSDestination(void); diff --git a/XPSDK/CHeaders/XPLM/XPLMPlanes.h b/XPSDK/CHeaders/XPLM/XPLMPlanes.h index 4b4d3a5..486302d 100644 --- a/XPSDK/CHeaders/XPLM/XPLMPlanes.h +++ b/XPSDK/CHeaders/XPLM/XPLMPlanes.h @@ -2,17 +2,21 @@ #define _XPLMPlanes_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPLMPlanes + ***************************************************************************/ /* - * The XPLMPlanes APIs allow you to control the various aircraft in x-plane, + * The XPLMPlanes APIs allow you to control the various aircraft in X-Plane, * both the user's and the sim's. + * + * *Note*: unlike almost all other APIs in the SDK, aircraft paths are _full_ + * file system paths for historical reasons. You'll need to prefix all + * relative paths with the X-Plane path as accessed via XPLMGetSystemPath. * */ @@ -25,218 +29,256 @@ extern "C" { /*************************************************************************** * USER AIRCRAFT ACCESS ***************************************************************************/ -/* - * - * - */ - /* * XPLMSetUsersAircraft - * + * * This routine changes the user's aircraft. Note that this will reinitialize * the user to be on the nearest airport's first runway. Pass in a full path - * (hard drive and everything including the .acf extension) to the .acf file. + * (hard drive and everything including the .acf extension) to the .acf file. * */ -XPLM_API void XPLMSetUsersAircraft(const char *inAircraftPath); +XPLM_API void XPLMSetUsersAircraft( + const char * inAircraftPath); /* * XPLMPlaceUserAtAirport - * + * * This routine places the user at a given airport. Specify the airport by - * its ICAO code (e.g. 'KBOS'). + * its X-Plane airport ID (e.g. 'KBOS'). * */ -XPLM_API void XPLMPlaceUserAtAirport(const char *inAirportCode); +XPLM_API void XPLMPlaceUserAtAirport( + const char * inAirportCode); +#if defined(XPLM300) +/* + * XPLMPlaceUserAtLocation + * + * Places the user at a specific location after performing any necessary + * scenery loads. + * + * As with in-air starts initiated from the X-Plane user interface, the + * aircraft will always start with its engines running, regardless of the + * user's preferences (i.e., regardless of what the dataref + * `sim/operation/prefs/startup_running` says). + * + */ +XPLM_API void XPLMPlaceUserAtLocation( + double latitudeDegrees, + double longitudeDegrees, + float elevationMetersMSL, + float headingDegreesTrue, + float speedMetersPerSecond); +#endif /* XPLM300 */ /*************************************************************************** * GLOBAL AIRCRAFT ACCESS ***************************************************************************/ -/* - * - * - */ - -/* The user's aircraft is always index 0. */ -#define XPLM_USER_AIRCRAFT 0 +/* The user's aircraft is always index 0. */ +#define XPLM_USER_AIRCRAFT 0 +#if defined(XPLM_DEPRECATED) /* * XPLMPlaneDrawState_t - * + * * This structure contains additional plane parameter info to be passed to * draw plane. Make sure to fill in the size of the structure field with * sizeof(XPLMDrawPlaneState_t) so that the XPLM can tell how many fields you * knew about when compiling your plugin (since more fields may be added * later). - * + * * Most of these fields are ratios from 0 to 1 for control input. X-Plane * calculates what the actual controls look like based on the .acf file for * that airplane. Note for the yoke inputs, this is what the pilot of the * plane has commanded (post artificial stability system if there were one) - * and affects aelerons, rudder, etc. It is not necessarily related to the - * actual position of the plane! + * and affects aelerons, rudder, etc. It is not necessarily related to the + * actual position of the plane! * */ typedef struct { - /* The size of the draw state struct. */ - int structSize; - /* A ratio from [0..1] describing how far the landing gear is extended. */ - float gearPosition; - /* Ratio of flap deployment, 0 = up, 1 = full deploy. */ - float flapRatio; - /* Ratio of spoiler deployment, 0 = none, 1 = full deploy. */ - float spoilerRatio; - /* Ratio of speed brake deployment, 0 = none, 1 = full deploy. */ - float speedBrakeRatio; - /* Ratio of slat deployment, 0 = none, 1 = full deploy. */ - float slatRatio; - /* Wing sweep ratio, 0 = forward, 1 = swept. */ - float wingSweep; - /* Thrust power, 0 = none, 1 = full fwd, -1 = full reverse. */ - float thrust; - /* Total pitch input for this plane. */ - float yokePitch; - /* Total Heading input for this plane. */ - float yokeHeading; - /* Total Roll input for this plane. */ - float yokeRoll; + /* The size of the draw state struct. */ + int structSize; + /* A ratio from [0..1] describing how far the landing gear is extended. */ + float gearPosition; + /* Ratio of flap deployment, 0 = up, 1 = full deploy. */ + float flapRatio; + /* Ratio of spoiler deployment, 0 = none, 1 = full deploy. */ + float spoilerRatio; + /* Ratio of speed brake deployment, 0 = none, 1 = full deploy. */ + float speedBrakeRatio; + /* Ratio of slat deployment, 0 = none, 1 = full deploy. */ + float slatRatio; + /* Wing sweep ratio, 0 = forward, 1 = swept. */ + float wingSweep; + /* Thrust power, 0 = none, 1 = full fwd, -1 = full reverse. */ + float thrust; + /* Total pitch input for this plane. */ + float yokePitch; + /* Total Heading input for this plane. */ + float yokeHeading; + /* Total Roll input for this plane. */ + float yokeRoll; } XPLMPlaneDrawState_t; +#endif /* XPLM_DEPRECATED */ /* * XPLMCountAircraft - * + * * This function returns the number of aircraft X-Plane is capable of having, * as well as the number of aircraft that are currently active. These numbers * count the user's aircraft. It can also return the plugin that is currently * controlling aircraft. In X-Plane 7, this routine reflects the number of - * aircraft the user has enabled in the rendering options window. + * aircraft the user has enabled in the rendering options window. * */ -XPLM_API void XPLMCountAircraft(int *outTotalAircraft, - int *outActiveAircraft, - XPLMPluginID *outController); +XPLM_API void XPLMCountAircraft( + int * outTotalAircraft, + int * outActiveAircraft, + XPLMPluginID * outController); /* * XPLMGetNthAircraftModel - * + * * This function returns the aircraft model for the Nth aircraft. Indices are * zero based, with zero being the user's aircraft. The file name should be * at least 256 chars in length; the path should be at least 512 chars in - * length. + * length. * */ -XPLM_API void - XPLMGetNthAircraftModel(int inIndex, char *outFileName, char *outPath); +XPLM_API void XPLMGetNthAircraftModel( + int inIndex, + char * outFileName, + char * outPath); /*************************************************************************** * EXCLUSIVE AIRCRAFT ACCESS ***************************************************************************/ /* * The following routines require exclusive access to the airplane APIs. Only - * one plugin may have this access at a time. + * one plugin may have this access at a time. * */ /* * XPLMPlanesAvailable_f - * + * * Your airplanes available callback is called when another plugin gives up * access to the multiplayer planes. Use this to wait for access to - * multiplayer. + * multiplayer. * */ -typedef void (*XPLMPlanesAvailable_f)(void *inRefcon); +typedef void (* XPLMPlanesAvailable_f)( + void * inRefcon); /* * XPLMAcquirePlanes - * + * * XPLMAcquirePlanes grants your plugin exclusive access to the aircraft. It - * returns 1 if you gain access, 0 if you do not. inAircraft - pass in an - * array of pointers to strings specifying the planes you want loaded. For - * any plane index you do not want loaded, pass a 0-length string. Other - * strings should be full paths with the .acf extension. NULL terminates this - * array, or pass NULL if there are no planes you want loaded. If you pass in - * a callback and do not receive access to the planes your callback will be - * called when the airplanes are available. If you do receive airplane access, - * your callback will not be called. + * returns 1 if you gain access, 0 if you do not. + * + * inAircraft - pass in an array of pointers to strings specifying the planes + * you want loaded. For any plane index you do not want loaded, pass a + * 0-length string. Other strings should be full paths with the .acf + * extension. NULL terminates this array, or pass NULL if there are no planes + * you want loaded. + * + * If you pass in a callback and do not receive access to the planes your + * callback will be called when the airplanes are available. If you do receive + * airplane access, your callback will not be called. * */ -XPLM_API int XPLMAcquirePlanes(char **inAircraft, /* Can be NULL */ - XPLMPlanesAvailable_f inCallback, - void *inRefcon); +XPLM_API int XPLMAcquirePlanes( + char ** inAircraft, /* Can be NULL */ + XPLMPlanesAvailable_f inCallback, + void * inRefcon); /* * XPLMReleasePlanes - * + * * Call this function to release access to the planes. Note that if you are - * disabled, access to planes is released for you and you must reacquire it. + * disabled, access to planes is released for you and you must reacquire it. * */ -XPLM_API void XPLMReleasePlanes(void); +XPLM_API void XPLMReleasePlanes(void); /* * XPLMSetActiveAircraftCount - * + * * This routine sets the number of active planes. If you pass in a number * higher than the total number of planes availables, only the total number of - * planes available is actually used. + * planes available is actually used. * */ -XPLM_API void XPLMSetActiveAircraftCount(int inCount); +XPLM_API void XPLMSetActiveAircraftCount( + int inCount); /* * XPLMSetAircraftModel - * - * This routine loads an aircraft model. It may only be called if you have - * exclusive access to the airplane APIs. Pass in the path of the model with - * the .acf extension. The index is zero based, but you may not pass in 0 - * (use XPLMSetUsersAircraft to load the user's aircracft). + * + * This routine loads an aircraft model. It may only be called if you have + * exclusive access to the airplane APIs. Pass in the path of the model with + * the .acf extension. The index is zero based, but you may not pass in 0 + * (use XPLMSetUsersAircraft to load the user's aircracft). * */ -XPLM_API void XPLMSetAircraftModel(int inIndex, const char *inAircraftPath); +XPLM_API void XPLMSetAircraftModel( + int inIndex, + const char * inAircraftPath); /* * XPLMDisableAIForPlane - * + * * This routine turns off X-Plane's AI for a given plane. The plane will - * continue to draw and be a real plane in X-Plane, but will not move itself. + * continue to draw and be a real plane in X-Plane, but will not move itself. * */ -XPLM_API void XPLMDisableAIForPlane(int inPlaneIndex); +XPLM_API void XPLMDisableAIForPlane( + int inPlaneIndex); +#if defined(XPLM_DEPRECATED) /* * XPLMDrawAircraft - * + * + * WARNING: Aircraft drawing via this API is deprecated and will not work in + * future versions of X-Plane. Use XPLMInstance for 3-d drawing of custom + * aircraft models. + * * This routine draws an aircraft. It can only be called from a 3-d drawing * callback. Pass in the position of the plane in OpenGL local coordinates * and the orientation of the plane. A 1 for full drawing indicates that the * whole plane must be drawn; a 0 indicates you only need the nav lights - * drawn. (This saves rendering time when planes are far away.) + * drawn. (This saves rendering time when planes are far away.) * */ -XPLM_API void XPLMDrawAircraft(int inPlaneIndex, - float inX, - float inY, - float inZ, - float inPitch, - float inRoll, - float inYaw, - int inFullDraw, - XPLMPlaneDrawState_t *inDrawStateInfo); +XPLM_API void XPLMDrawAircraft( + int inPlaneIndex, + float inX, + float inY, + float inZ, + float inPitch, + float inRoll, + float inYaw, + int inFullDraw, + XPLMPlaneDrawState_t * inDrawStateInfo); +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) /* * XPLMReinitUsersPlane - * + * + * WARNING: DO NOT USE. Use XPLMPlaceUserAtAirport or + * XPLMPlaceUserAtLocation. + * * This function recomputes the derived flight model data from the aircraft * structure in memory. If you have used the data access layer to modify the - * aircraft structure, use this routine to resynchronize x-plane; since - * X-plane works at least partly from derived values, the sim will not behave + * aircraft structure, use this routine to resynchronize X-Plane; since + * X-Plane works at least partly from derived values, the sim will not behave * properly until this is called. - * + * * WARNING: this routine does not necessarily place the airplane at the * airport; use XPLMSetUsersAircraft to be compatible. This routine is * provided to do special experimentation with flight models without resetting - * flight. + * flight. * */ -XPLM_API void XPLMReinitUsersPlane(void); +XPLM_API void XPLMReinitUsersPlane(void); +#endif /* XPLM_DEPRECATED */ #ifdef __cplusplus } diff --git a/XPSDK/CHeaders/XPLM/XPLMPlugin.h b/XPSDK/CHeaders/XPLM/XPLMPlugin.h index 8080a94..be5d06c 100644 --- a/XPSDK/CHeaders/XPLM/XPLMPlugin.h +++ b/XPSDK/CHeaders/XPLM/XPLMPlugin.h @@ -2,17 +2,17 @@ #define _XPLMPlugin_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPLMPlugin + ***************************************************************************/ /* * These APIs provide facilities to find and work with other plugins and - * manage other plugins. + * manage other plugins. * */ @@ -29,129 +29,136 @@ extern "C" { * These APIs allow you to find another plugin or yourself, or iterate across * all plugins. For example, if you wrote an FMS plugin that needed to talk * to an autopilot plugin, you could use these APIs to locate the autopilot - * plugin. + * plugin. * */ /* * XPLMGetMyID - * + * * This routine returns the plugin ID of the calling plug-in. Call this to - * get your own ID. + * get your own ID. * */ XPLM_API XPLMPluginID XPLMGetMyID(void); /* * XPLMCountPlugins - * + * * This routine returns the total number of plug-ins that are loaded, both - * disabled and enabled. + * disabled and enabled. * */ -XPLM_API int XPLMCountPlugins(void); +XPLM_API int XPLMCountPlugins(void); /* * XPLMGetNthPlugin - * + * * This routine returns the ID of a plug-in by index. Index is 0 based from 0 * to XPLMCountPlugins-1, inclusive. Plugins may be returned in any arbitrary - * order. + * order. * */ -XPLM_API XPLMPluginID XPLMGetNthPlugin(int inIndex); +XPLM_API XPLMPluginID XPLMGetNthPlugin( + int inIndex); /* * XPLMFindPluginByPath - * + * * This routine returns the plug-in ID of the plug-in whose file exists at the * passed in absolute file system path. XPLM_NO_PLUGIN_ID is returned if the - * path does not point to a currently loaded plug-in. + * path does not point to a currently loaded plug-in. * */ -XPLM_API XPLMPluginID XPLMFindPluginByPath(const char *inPath); +XPLM_API XPLMPluginID XPLMFindPluginByPath( + const char * inPath); /* * XPLMFindPluginBySignature - * + * * This routine returns the plug-in ID of the plug-in whose signature matches * what is passed in or XPLM_NO_PLUGIN_ID if no running plug-in has this * signature. Signatures are the best way to identify another plug-in as they * are independent of the file system path of a plug-in or the human-readable * plug-in name, and should be unique for all plug-ins. Use this routine to - * locate another plugin that your plugin interoperates with + * locate another plugin that your plugin interoperates with * */ -XPLM_API XPLMPluginID XPLMFindPluginBySignature(const char *inSignature); +XPLM_API XPLMPluginID XPLMFindPluginBySignature( + const char * inSignature); /* * XPLMGetPluginInfo - * + * * This routine returns information about a plug-in. Each parameter should be - * a pointer to a buffer of at least 256 characters, or NULL to not receive - * the information. - * - * outName - the human-readable name of the plug-in. outFilePath - the + * a pointer to a buffer of at least + * 256 characters, or NULL to not receive the information. + * + * outName - the human-readable name of the plug-in. outFilePath - the * absolute file path to the file that contains this plug-in. outSignature - a * unique string that identifies this plug-in. outDescription - a - * human-readable description of this plug-in. + * human-readable description of this plug-in. * */ -XPLM_API void XPLMGetPluginInfo(XPLMPluginID inPlugin, - char *outName, /* Can be NULL */ - char *outFilePath, /* Can be NULL */ - char *outSignature, /* Can be NULL */ - char *outDescription); /* Can be NULL */ +XPLM_API void XPLMGetPluginInfo( + XPLMPluginID inPlugin, + char * outName, /* Can be NULL */ + char * outFilePath, /* Can be NULL */ + char * outSignature, /* Can be NULL */ + char * outDescription); /* Can be NULL */ /*************************************************************************** * ENABLING/DISABLING PLUG-INS ***************************************************************************/ /* * These routines are used to work with plug-ins and manage them. Most - * plugins will not need to use these APIs. + * plugins will not need to use these APIs. * */ /* * XPLMIsPluginEnabled - * - * Returns whether the specified plug-in is enabled for running. + * + * Returns whether the specified plug-in is enabled for running. * */ -XPLM_API int XPLMIsPluginEnabled(XPLMPluginID inPluginID); +XPLM_API int XPLMIsPluginEnabled( + XPLMPluginID inPluginID); /* * XPLMEnablePlugin - * - * This routine enables a plug-in if it is not already enabled. It returns 1 + * + * This routine enables a plug-in if it is not already enabled. It returns 1 * if the plugin was enabled or successfully enables itself, 0 if it does not. * Plugins may fail to enable (for example, if resources cannot be acquired) - * by returning 0 from their XPluginEnable callback. + * by returning 0 from their XPluginEnable callback. * */ -XPLM_API int XPLMEnablePlugin(XPLMPluginID inPluginID); +XPLM_API int XPLMEnablePlugin( + XPLMPluginID inPluginID); /* * XPLMDisablePlugin - * - * This routine disableds an enabled plug-in. + * + * This routine disableds an enabled plug-in. * */ -XPLM_API void XPLMDisablePlugin(XPLMPluginID inPluginID); +XPLM_API void XPLMDisablePlugin( + XPLMPluginID inPluginID); /* * XPLMReloadPlugins - * + * * This routine reloads all plug-ins. Once this routine is called and you * return from the callback you were within (e.g. a menu select callback) you - * will receive your XPluginDisable and XPluginStop callbacks and your DLL + * will receive your XPluginDisable and XPluginStop callbacks and your DLL * will be unloaded, then the start process happens as if the sim was starting - * up. + * up. * */ -XPLM_API void XPLMReloadPlugins(void); +XPLM_API void XPLMReloadPlugins(void); /*************************************************************************** * INTERPLUGIN MESSAGING @@ -159,82 +166,130 @@ XPLM_API void XPLMReloadPlugins(void); /* * Plugin messages are defined as 32-bit integers. Messages below 0x00FFFFFF * are reserved for X-Plane and the plugin SDK. - * + * + * Messages come with a pointer parameter; the meaning of this pointer depends + * on the message itself. In some messages, the pointer parameter contains an + * actual typed pointer to data that can be inspected in the plugin; in these + * cases the documentation will state that the parameter "points to" + * information. + * + * in other cases, the value of the pointer is actually an integral number + * stuffed into the pointer's storage. In these second cases, the pointer + * parameter needs to be cast, not dereferenced. In these caess, the + * documentation will state that the parameter "contains" a value, which will + * always be an integral type. + * + * Some messages don't use the pointer parameter - in this case your plugin + * should ignore it. + * * Messages have two conceptual uses: notifications and commands. Commands - * are sent from one plugin to another to induce behavior; notifications are - * sent from one plugin to all others for informational purposes. It is + * are sent from one plugin to another to induce behavior; notifications are + * sent from one plugin to all others for informational purposes. It is * important that commands and notifications not have the same values because * this could cause a notification sent by one plugin to accidentally induce a * command in another. - * + * * By convention, plugin-defined notifications should have the high bit set * (e.g. be greater or equal to unsigned 0x8000000) while commands should have * this bit be cleared. - * - * The following messages are sent to your plugin by x-plane. + * + * The following messages are sent to your plugin by X-Plane. * */ -/* This message is sent to your plugin whenever the user's plane crashes. */ +/* This message is sent to your plugin whenever the user's plane crashes. The * + * parameter is ignored. */ #define XPLM_MSG_PLANE_CRASHED 101 -/* This message is sent to your plugin whenever a new plane is loaded. The * - * parameter is the number of the plane being loaded; 0 indicates the user's * - * plane. */ +/* This message is sent to your plugin whenever a new plane is loaded. The * + * parameter contains the index number of the plane being loaded; 0 indicates * + * the user's plane. */ #define XPLM_MSG_PLANE_LOADED 102 -/* This messages is called whenever the user's plane is positioned at a new * - * airport. */ +/* This messages is sent whenever the user's plane is positioned at a new * + * airport. The parameter is ignored. */ #define XPLM_MSG_AIRPORT_LOADED 103 -/* This message is sent whenever new scenery is loaded. Use datarefs to * - * determine the new scenery files that were loaded. */ +/* This message is sent whenever new scenery is loaded. Use datarefs to * + * determine the new scenery files that were loaded. The parameter is ignored.*/ #define XPLM_MSG_SCENERY_LOADED 104 -/* This message is sent whenever the user adjusts the number of X-Plane * - * aircraft models. You must use XPLMCountPlanes to find out how many planes * - * are now available. This message will only be sent in XP7 and higher * - * because in XP6 the number of aircraft is not user-adjustable. */ +/* This message is sent whenever the user adjusts the number of X-Plane * + * aircraft models. You must use XPLMCountPlanes to find out how many planes * + * are now available. This message will only be sent in XP7 and higher * + * because in XP6 the number of aircraft is not user-adjustable. The parameter* + * is ignored. */ #define XPLM_MSG_AIRPLANE_COUNT_CHANGED 105 #if defined(XPLM200) -/* This message is sent to your plugin whenever a plane is unloaded. The * - * parameter is the number of the plane being unloaded; 0 indicates the user's * - * plane. The parameter is of type int, passed as the value of the pointer. * - * (That is: the parameter is an int, not a pointer to an int.) */ +/* This message is sent to your plugin whenever a plane is unloaded. The * + * parameter contains the index number of the plane being unloaded; 0 * + * indicates the user's plane. The parameter is of type int, passed as the * + * value of the pointer. (That is: the parameter is an int, not a pointer to * + * an int.) */ #define XPLM_MSG_PLANE_UNLOADED 106 #endif /* XPLM200 */ #if defined(XPLM210) -/* This message is sent to your plugin right before X-Plane writes its * - * preferences file. You can use this for two purposes: to write your own * - * preferences, and to modify any datarefs to influence preferences output. * - * For example, if your plugin temporarily modifies saved preferences, you can * - * put them back to their default values here to avoid having the tweaks be * - * persisted if your plugin is not loaded on the next invocation of X-Plane. */ +/* This message is sent to your plugin right before X-Plane writes its * + * preferences file. You can use this for two purposes: to write your own * + * preferences, and to modify any datarefs to influence preferences output. * + * For example, if your plugin temporarily modifies saved preferences, you can* + * put them back to their default values here to avoid having the tweaks be * + * persisted if your plugin is not loaded on the next invocation of X-Plane. * + * The parameter is ignored. */ #define XPLM_MSG_WILL_WRITE_PREFS 107 #endif /* XPLM210 */ #if defined(XPLM210) -/* This message is sent to your plugin right after a livery is loaded for an * - * airplane. You can use this to check the new livery (via datarefs) and * - * react accordingly. The parameter is of type int, passed as the value of a * - * pointer and represents the aicraft plane number - 0 is the user's plane. */ +/* This message is sent to your plugin right after a livery is loaded for an * + * airplane. You can use this to check the new livery (via datarefs) and * + * react accordingly. The parameter contains the index number of the aircraft* + * whose livery is changing. */ #define XPLM_MSG_LIVERY_LOADED 108 #endif /* XPLM210 */ +#if defined(XPLM301) +/* Sent to your plugin right before X-Plane enters virtual reality mode (at * + * which time any windows that are not positioned in VR mode will no longer be* + * visible to the user). The parameter is unused and should be ignored. */ +#define XPLM_MSG_ENTERED_VR 109 +#endif /* XPLM301 */ + +#if defined(XPLM301) +/* Sent to your plugin right before X-Plane leaves virtual reality mode (at * + * which time you may want to clean up windows that are positioned in VR * + * mode). The parameter is unused and should be ignored. */ +#define XPLM_MSG_EXITING_VR 110 +#endif /* XPLM301 */ + +#if defined(XPLM303) +/* Sent to your plugin if another plugin wants to take over AI planes. If you * + * are a synthetic traffic provider, that probably means a plugin for an * + * online network has connected and wants to supply aircraft flown by real * + * humans and you should cease to provide synthetic traffic. If however you * + * are providing online traffic from real humans, you probably don't want to * + * disconnect, in which case you just ignore this message. The sender is the * + * plugin ID of the plugin asking for control of the planes now. You can use * + * it to find out who is requesting and whether you should yield to them. * + * Synthetic traffic providers should always yield to online networks. The * + * parameter is unused and should be ignored. */ +#define XPLM_MSG_RELEASE_PLANES 111 +#endif /* XPLM303 */ + /* * XPLMSendMessageToPlugin - * + * * This function sends a message to another plug-in or X-Plane. Pass * XPLM_NO_PLUGIN_ID to broadcast to all plug-ins. Only enabled plug-ins with - * a message receive function receive the message. + * a message receive function receive the message. * */ -XPLM_API void XPLMSendMessageToPlugin(XPLMPluginID inPlugin, - int inMessage, - void *inParam); +XPLM_API void XPLMSendMessageToPlugin( + XPLMPluginID inPlugin, + int inMessage, + void * inParam); #if defined(XPLM200) /*************************************************************************** @@ -245,63 +300,119 @@ XPLM_API void XPLMSendMessageToPlugin(XPLMPluginID inPlugin, * capabilities and plugin system features that are normally disabled for * backward compatibility. This allows advanced plugins to "opt-in" to new * behavior. - * + * * Each feature is defined by a permanent string name. The feature string - * names will vary with the particular installation of X-Plane, so plugins + * names will vary with the particular installation of X-Plane, so plugins * should not expect a feature to be guaranteed present. + * + * XPLM_WANTS_REFLECTIONS + * ---------------------- + * + * Available in the SDK 2.0 and later for X-Plane 9, enabling this capability + * causes your plugin to receive drawing hook callbacks when X-Plane builds + * its off-screen reflection and shadow rendering passes. Plugins should + * enable this and examine the dataref sim/graphics/view/plane_render_type to + * determine whether the drawing callback is for a reflection, shadow + * calculation, or the main screen. Rendering can be simlified or omitted for + * reflections, and non-solid drawing should be skipped for shadow + * calculations. + * + * **Note**: direct drawing via draw callbacks is not recommended; use the + * XPLMInstance API to create object models instead. + * + * XPLM_USE_NATIVE_PATHS + * --------------------- + * + * available in the SDK 2.1 and later for X-Plane 10, this modifies the plugin + * system to use Unix-style paths on all operating systems. With this enabled: + * + * * OS X paths will match the native OS X Unix. + * * Windows will use forward slashes but preserve C:\ or another drive letter + * when using complete file paths. + * * Linux uses its native file system path scheme. + * + * Without this enabled: + * + * * OS X will use CFM file paths separated by a colon. + * * Windows will use back-slashes and conventional DOS paths. + * * Linux uses its native file system path scheme. + * + * All plugins should enable this feature on OS X to access the native file + * system. + * + * XPLM_USE_NATIVE_WIDGET_WINDOWS + * ------------------------------ + * + * Available in the SDK 3.0.2 SDK, this capability tells the widgets library + * to use new, modern X-Plane backed XPLMDisplay windows to anchor all widget + * trees. Without it, widgets will always use legacy windows. + * + * Plugins should enable this to allow their widget hierarchies to respond to + * the user's UI size settings and to map widget-based windwos to a VR HMD. + * + * Before enabling this, make sure any custom widget code in your plugin is + * prepared to cope with the UI coordinate system not being th same as the + * OpenGL window coordinate system. * */ /* * XPLMFeatureEnumerator_f - * + * * You pass an XPLMFeatureEnumerator_f to get a list of all features supported * by a given version running version of X-Plane. This routine is called once - * for each feature. + * for each feature. * */ -typedef void (*XPLMFeatureEnumerator_f)(const char *inFeature, void *inRef); +typedef void (* XPLMFeatureEnumerator_f)( + const char * inFeature, + void * inRef); /* * XPLMHasFeature - * + * * This returns 1 if the given installation of X-Plane supports a feature, or - * 0 if it does not. + * 0 if it does not. * */ -XPLM_API int XPLMHasFeature(const char *inFeature); +XPLM_API int XPLMHasFeature( + const char * inFeature); /* * XPLMIsFeatureEnabled - * + * * This returns 1 if a feature is currently enabled for your plugin, or 0 if * it is not enabled. It is an error to call this routine with an unsupported - * feature. + * feature. * */ -XPLM_API int XPLMIsFeatureEnabled(const char *inFeature); +XPLM_API int XPLMIsFeatureEnabled( + const char * inFeature); /* * XPLMEnableFeature - * + * * This routine enables or disables a feature for your plugin. This will * change the running behavior of X-Plane and your plugin in some way, - * depending on the feature. + * depending on the feature. * */ -XPLM_API void XPLMEnableFeature(const char *inFeature, int inEnable); +XPLM_API void XPLMEnableFeature( + const char * inFeature, + int inEnable); /* * XPLMEnumerateFeatures - * + * * This routine calls your enumerator callback once for each feature that this * running version of X-Plane supports. Use this routine to determine all of - * the features that X-Plane can support. + * the features that X-Plane can support. * */ -XPLM_API void XPLMEnumerateFeatures(XPLMFeatureEnumerator_f inEnumerator, - void *inRef); +XPLM_API void XPLMEnumerateFeatures( + XPLMFeatureEnumerator_f inEnumerator, + void * inRef); #endif /* XPLM200 */ #ifdef __cplusplus diff --git a/XPSDK/CHeaders/XPLM/XPLMProcessing.h b/XPSDK/CHeaders/XPLM/XPLMProcessing.h index 5119449..94ef0c4 100644 --- a/XPSDK/CHeaders/XPLM/XPLMProcessing.h +++ b/XPSDK/CHeaders/XPLM/XPLMProcessing.h @@ -2,23 +2,38 @@ #define _XPLMProcessing_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPLMProcessing + ***************************************************************************/ /* * This API allows you to get regular callbacks during the flight loop, the * part of X-Plane where the plane's position calculates the physics of - * flight, etc. Use these APIs to accomplish periodic tasks like logging data + * flight, etc. Use these APIs to accomplish periodic tasks like logging data * and performing I/O. - * - * WARNING: Do NOT use these callbacks to draw! You cannot draw during flight - * loop callbacks. Use the drawing callbacks (see XPLMDisplay for more info) - * for graphics. + * + * You can receive a callback either just before or just after the per-frame + * physics calculations happen - you can use post-FM callbacks to "patch" the + * flight model after it has run. + * + * If the user has set the number of flight model iterations per frame greater + * than one your plugin will _not_ see this; these integrations run on the + * sub-section of the flight model where iterations improve responsiveness + * (e.g. physical integration, not simple systems tracking) and are thus + * opaque to plugins. + * + * Flight loop scheduling, when scheduled by time, is scheduled by a "first + * callback after the deadline" schedule, e.g. your callbacks will always be + * slightly late to ensure that we don't run faster than your deadline. + * + * WARNING: Do NOT use these callbacks to draw! You cannot draw during flight + * loop callbacks. Use the drawing callbacks (see XPLMDisplay for more info) + * for graphics. (One exception: you can use a post-flight loop callback to + * update your own off-screen FBOs.) * */ @@ -31,27 +46,21 @@ extern "C" { /*************************************************************************** * FLIGHT LOOP CALLBACKS ***************************************************************************/ -/* - * - * - */ - #if defined(XPLM210) /* * XPLMFlightLoopPhaseType - * + * * You can register a flight loop callback to run either before or after the - * flight model is integrated by X-Plane. + * flight model is integrated by X-Plane. * */ enum { - /* Your callback runs before X-Plane integrates the flight model. */ - xplm_FlightLoop_Phase_BeforeFlightModel = 0 + /* Your callback runs before X-Plane integrates the flight model. */ + xplm_FlightLoop_Phase_BeforeFlightModel = 0, - /* Your callback runs after X-Plane integrates the flight model. */ - , - xplm_FlightLoop_Phase_AfterFlightModel = 1 + /* Your callback runs after X-Plane integrates the flight model. */ + xplm_FlightLoop_Phase_AfterFlightModel = 1, }; @@ -61,184 +70,191 @@ typedef int XPLMFlightLoopPhaseType; #if defined(XPLM210) /* * XPLMFlightLoopID - * - * This is an opaque identifier for a flight loop callback. You can use this + * + * This is an opaque identifier for a flight loop callback. You can use this * identifier to easily track and remove your callbacks, or to use the new - * flight loop APIs. + * flight loop APIs. * */ -typedef void *XPLMFlightLoopID; +typedef void * XPLMFlightLoopID; #endif /* XPLM210 */ /* * XPLMFlightLoop_f - * - * This is your flight loop callback. Each time the flight loop is iterated - * through, you receive this call at the end. You receive a time since you - * were last called and a time since the last loop, as well as a loop counter. - * The 'phase' parameter is deprecated and should be ignored. - * - * Your return value controls when you will next be called. Return 0 to stop - * receiving callbacks. Pass a positive number to specify how many seconds - * until the next callback. (You will be called at or after this time, not - * before.) Pass a negative number to specify how many loops must go by until - * you are called. For example, -1.0 means call me the very next loop. Try - * to run your flight loop as infrequently as is practical, and suspend it + * + * This is your flight loop callback. Each time the flight loop is iterated + * through, you receive this call at the end. + * + * Flight loop callbacks receive a number of input timing parameters. These + * input timing parameters are not particularly useful; you may need to track + * your own timing data (e.g. by reading datarefs). The input parameters are: + * + * - inElapsedSinceLastCall: the wall time since your last callback. + * - inElapsedTimeSinceLastFlightLoop: the wall time since any flight loop was + * dispatched. + * - inCounter: a monotonically increasing counter, bumped once per flight + * loop dispatch from the sim. + * - inRefcon: your own ptr constant from when you regitered yor callback. + * + * Your return value controls when you will next be called. + * + * - Return 0 to stop receiving callbacks. + * - Pass a positive number to specify how many seconds until the next + * callback. (You will be called at or after this time, not before.) + * - Pass a negative number to specify how many loops must go by until you + * are called. For example, -1.0 means call me the very next loop. + * + * Try to run your flight loop as infrequently as is practical, and suspend it * (using return value 0) when you do not need it; lots of flight loop - * callbacks that do nothing lowers x-plane's frame rate. - * + * callbacks that do nothing lowers X-Plane's frame rate. + * * Your callback will NOT be unregistered if you return 0; it will merely be - * inactive. - * - * The reference constant you passed to your loop is passed back to you. + * inactive. * */ -typedef float (*XPLMFlightLoop_f)(float inElapsedSinceLastCall, - float inElapsedTimeSinceLastFlightLoop, - int inCounter, - void *inRefcon); +typedef float (* XPLMFlightLoop_f)( + float inElapsedSinceLastCall, + float inElapsedTimeSinceLastFlightLoop, + int inCounter, + void * inRefcon); #if defined(XPLM210) /* * XPLMCreateFlightLoop_t - * + * * XPLMCreateFlightLoop_t contains the parameters to create a new flight loop - * callback. The strsucture can be expanded in future SDKs - always set - * structSize to the size of your structure in bytes. + * callback. The strsucture can be expanded in future SDKs - always set + * structSize to the size of your structure in bytes. * */ typedef struct { - int structSize; - XPLMFlightLoopPhaseType phase; - XPLMFlightLoop_f callbackFunc; - void *refcon; + int structSize; + XPLMFlightLoopPhaseType phase; + XPLMFlightLoop_f callbackFunc; + void * refcon; } XPLMCreateFlightLoop_t; #endif /* XPLM210 */ /* * XPLMGetElapsedTime - * + * * This routine returns the elapsed time since the sim started up in decimal - * seconds. + * seconds. This is a wall timer; it keeps counting upward even if the sim is + * pasued. + * + * __WARNING__: XPLMGetElapsedTime is not a very good timer! It lacks + * precision in both its data type and its source. Do not attempt to use it + * for timing critical applications like network multiplayer. * */ -XPLM_API float XPLMGetElapsedTime(void); +XPLM_API float XPLMGetElapsedTime(void); /* * XPLMGetCycleNumber - * + * * This routine returns a counter starting at zero for each sim cycle - * computed/video frame rendered. + * computed/video frame rendered. * */ -XPLM_API int XPLMGetCycleNumber(void); +XPLM_API int XPLMGetCycleNumber(void); /* * XPLMRegisterFlightLoopCallback - * - * This routine registers your flight loop callback. Pass in a pointer to a - * flight loop function and a refcon. inInterval defines when you will be - * called. Pass in a positive number to specify seconds from registration - * time to the next callback. Pass in a negative number to indicate when you - * will be called (e.g. pass -1 to be called at the next cylcle). Pass 0 to - * not be called; your callback will be inactive. + * + * This routine registers your flight loop callback. Pass in a pointer to a + * flight loop function and a refcon. inInterval defines when you will be + * called. Pass in a positive number to specify seconds from registration time + * to the next callback. Pass in a negative number to indicate when you will + * be called (e.g. pass -1 to be called at the next cylcle). Pass 0 to not be + * called; your callback will be inactive. + * + * (This legacy function only installs pre-flight-loop callbacks; use + * XPLMCreateFlightLoop for more control.) * */ -XPLM_API void XPLMRegisterFlightLoopCallback(XPLMFlightLoop_f inFlightLoop, - float inInterval, - void *inRefcon); +XPLM_API void XPLMRegisterFlightLoopCallback( + XPLMFlightLoop_f inFlightLoop, + float inInterval, + void * inRefcon); /* * XPLMUnregisterFlightLoopCallback - * - * This routine unregisters your flight loop callback. Do NOT call it from - * your flight loop callback. Once your flight loop callback is - * unregistered, it will not be called again. + * + * This routine unregisters your flight loop callback. Do NOT call it from + * your flight loop callback. Once your flight loop callback is unregistered, + * it will not be called again. + * + * Only use this on flight loops registered via + * XPLMRegisterFlightLoopCallback. * */ -XPLM_API void XPLMUnregisterFlightLoopCallback(XPLMFlightLoop_f inFlightLoop, - void *inRefcon); +XPLM_API void XPLMUnregisterFlightLoopCallback( + XPLMFlightLoop_f inFlightLoop, + void * inRefcon); /* * XPLMSetFlightLoopCallbackInterval - * - * This routine sets when a callback will be called. Do NOT call it from your + * + * This routine sets when a callback will be called. Do NOT call it from your * callback; use the return value of the callback to change your callback * interval from inside your callback. - * + * * inInterval is formatted the same way as in XPLMRegisterFlightLoopCallback; * positive for seconds, negative for cycles, and 0 for deactivating the - * callback. If inRelativeToNow is 1, times are from the time of this call; + * callback. If inRelativeToNow is 1, times are from the time of this call; * otherwise they are from the time the callback was last called (or the time - * it was registered if it has never been called. + * it was registered if it has never been called. * */ -XPLM_API void XPLMSetFlightLoopCallbackInterval(XPLMFlightLoop_f inFlightLoop, - float inInterval, - int inRelativeToNow, - void *inRefcon); +XPLM_API void XPLMSetFlightLoopCallbackInterval( + XPLMFlightLoop_f inFlightLoop, + float inInterval, + int inRelativeToNow, + void * inRefcon); #if defined(XPLM210) /* * XPLMCreateFlightLoop - * - * This routine creates a flight loop callback and returns its ID. The flight + * + * This routine creates a flight loop callback and returns its ID. The flight * loop callback is created using the input param struct, and is inited to be - * unscheduled. + * unscheduled. * */ -XPLM_API XPLMFlightLoopID - XPLMCreateFlightLoop(XPLMCreateFlightLoop_t *inParams); +XPLM_API XPLMFlightLoopID XPLMCreateFlightLoop( + XPLMCreateFlightLoop_t * inParams); #endif /* XPLM210 */ #if defined(XPLM210) /* * XPLMDestroyFlightLoop - * - * This routine destroys a flight loop callback by ID. + * + * This routine destroys a flight loop callback by ID. Only call it on flight + * loops created with the newer XPLMCreateFlightLoop API. * */ -XPLM_API void XPLMDestroyFlightLoop(XPLMFlightLoopID inFlightLoopID); +XPLM_API void XPLMDestroyFlightLoop( + XPLMFlightLoopID inFlightLoopID); #endif /* XPLM210 */ #if defined(XPLM210) /* * XPLMScheduleFlightLoop - * - * This routine schedules a flight loop callback for future execution. If - * inInterval is negative, it is run in a certain number of frames based on - * the absolute value of the input. If the interval is positive, it is a + * + * This routine schedules a flight loop callback for future execution. If + * inInterval is negative, it is run in a certain number of frames based on + * the absolute value of the input. If the interval is positive, it is a * duration in seconds. - * + * * If inRelativeToNow is true, ties are interpretted relative to the time this * routine is called; otherwise they are relative to the last call time or the - * time the flight loop was registered (if never called). - * - * THREAD SAFETY: it is legal to call this routine from any thread under the - * following conditions: - * - * 1. The call must be between the beginning of an XPLMEnable and the end of - * an XPLMDisable sequence. (That is, you must not call this routine from - * thread activity when your plugin was supposed to be disabled. Since - * plugins are only enabled while loaded, this also implies you cannot run - * this routine outside an XPLMStart/XPLMStop sequence.) - * - * 2. You may not call this routine re-entrantly for a single flight loop ID. - * (That is, you can't enable from multiple threads at the same time.) - * - * 3. You must call this routine between the time after XPLMCreateFlightLoop - * returns a value and the time you call XPLMDestroyFlightLoop. (That is, you - * must ensure that your threaded activity is within the life of the object. - * The SDK does not check this for you, nor does it synchronize destruction of - * the object.) - * - * 4. The object must be unscheduled if this routine is to be called from a - * thread other than the main thread. + * time the flight loop was registered (if never called). * */ -XPLM_API void XPLMScheduleFlightLoop(XPLMFlightLoopID inFlightLoopID, - float inInterval, - int inRelativeToNow); +XPLM_API void XPLMScheduleFlightLoop( + XPLMFlightLoopID inFlightLoopID, + float inInterval, + int inRelativeToNow); #endif /* XPLM210 */ #ifdef __cplusplus diff --git a/XPSDK/CHeaders/XPLM/XPLMScenery.h b/XPSDK/CHeaders/XPLM/XPLMScenery.h index 0233cbb..452bac9 100644 --- a/XPSDK/CHeaders/XPLM/XPLMScenery.h +++ b/XPSDK/CHeaders/XPLM/XPLMScenery.h @@ -2,16 +2,16 @@ #define _XPLMScenery_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ +/*************************************************************************** + * XPLMScenery + ***************************************************************************/ /* - * This package contains APIs to interact with X-Plane's scenery system. + * This package contains APIs to interact with X-Plane's scenery system. * */ @@ -26,46 +26,49 @@ extern "C" { * Terrain Y-Testing ***************************************************************************/ /* - * The Y-testing API allows you to locate the physical scenery mesh. This - * would be used to place dynamic graphics on top of the ground in a - * plausible way or do physics interactions. - * + * The Y-testing API allows you to locate the physical scenery mesh. This + * would be used to place dynamic graphics on top of the ground in a plausible + * way or do physics interactions. + * * The Y-test API works via probe objects, which are allocated by your plugin * and used to query terrain. Probe objects exist both to capture which * algorithm you have requested (see probe types) and also to cache query * information. - * - * Performance guidelines: It is generally faster to use the same probe for - * nearby points and different probes for different points. Try not to - * allocate more than "hundreds" of probes at most. Share probes if you need - * more. Generally, probing operations are expensive, and should be avoided - * via caching when possible. - * + * + * Performance Guidelines + * ---------------------- + * + * It is generally faster to use the same probe for nearby points and + * different probes for different points. Try not to allocate more than + * "hundreds" of probes at most. Share probes if you need more. Generally, + * probing operations are expensive, and should be avoided via caching when + * possible. + * * Y testing returns a location on the terrain, a normal vectory, and a - * velocity vector. The normal vector tells you the slope of the terrain at - * that point. The velocity vector tells you if that terrain is moving (and - * is in meters/second). For example, if your Y test hits the aircraft carrier + * velocity vector. The normal vector tells you the slope of the terrain at + * that point. The velocity vector tells you if that terrain is moving (and is + * in meters/second). For example, if your Y test hits the aircraft carrier * deck, this tells you the velocity of that point on the deck. - * + * * Note: the Y-testing API is limited to probing the loaded scenery area, - * which is approximately 300x300 km in X-Plane 9. Probes outside this area - * will return the height of a 0 MSL sphere. + * which is approximately 300x300 km in X-Plane 9. Probes outside this area + * will return the height of a 0 MSL sphere. * */ /* * XPLMProbeType - * + * * XPLMProbeType defines the type of terrain probe - each probe has a - * different algorithm. (Only one type of probe is provided right now, but - * future APIs will expose more flexible or poewrful or useful probes. + * different algorithm. (Only one type of probe is provided right now, but + * future APIs will expose more flexible or poewrful or useful probes. * */ enum { - /* The Y probe gives you the location of the tallest physical scenery along - * * the Y axis going through the queried point. */ - xplm_ProbeY = 0 + /* The Y probe gives you the location of the tallest physical scenery along * + * the Y axis going through the queried point. */ + xplm_ProbeY = 0, }; @@ -73,24 +76,21 @@ typedef int XPLMProbeType; /* * XPLMProbeResult - * - * Probe results - possible results from a probe query. + * + * Probe results - possible results from a probe query. * */ enum { - /* The probe hit terrain and returned valid values. */ - xplm_ProbeHitTerrain = 0 + /* The probe hit terrain and returned valid values. */ + xplm_ProbeHitTerrain = 0, - /* An error in the API call. Either the probe struct size is bad, or the * - * probe is invalid or the type is mismatched for the specific query call. - */ - , - xplm_ProbeError = 1 + /* An error in the API call. Either the probe struct size is bad, or the * + * probe is invalid or the type is mismatched for the specific query call. */ + xplm_ProbeError = 1, - /* The probe call succeeded but there is no terrain under this point - * (perhaps * it is off the side of the planet?) */ - , - xplm_ProbeMissed = 2 + /* The probe call succeeded but there is no terrain under this point (perhaps * + * it is off the side of the planet?) */ + xplm_ProbeMissed = 2, }; @@ -98,88 +98,142 @@ typedef int XPLMProbeResult; /* * XPLMProbeRef - * + * * An XPLMProbeRef is an opaque handle to a probe, used for querying the - * terrain. + * terrain. * */ -typedef void *XPLMProbeRef; +typedef void * XPLMProbeRef; /* * XPLMProbeInfo_t - * - * XPLMProbeInfo_t contains the results of a probe call. Make sure to set - * structSize to the size of the struct before using it. + * + * XPLMProbeInfo_t contains the results of a probe call. Make sure to set + * structSize to the size of the struct before using it. * */ typedef struct { - /* Size of structure in bytes - always set this before calling the XPLM. */ - int structSize; - /* Resulting X location of the terrain point we hit, in local OpenGL * - * coordinates. */ - float locationX; - /* Resulting Y location of the terrain point we hit, in local OpenGL * - * coordinates. */ - float locationY; - /* Resulting Z location of the terrain point we hit, in local OpenGL * - * coordinates. */ - float locationZ; - /* X component of the normal vector to the terrain we found. */ - float normalX; - /* Y component of the normal vector to the terrain we found. */ - float normalY; - /* Z component of the normal vector to the terrain we found. */ - float normalZ; - /* X component of the velocity vector of the terrain we found. */ - float velocityX; - /* Y component of the velocity vector of the terrain we found. */ - float velocityY; - /* Z component of the velocity vector of the terrain we found. */ - float velocityZ; - /* Tells if the surface we hit is water (otherwise it is land). */ - int is_wet; + /* Size of structure in bytes - always set this before calling the XPLM. */ + int structSize; + /* Resulting X location of the terrain point we hit, in local OpenGL * + * coordinates. */ + float locationX; + /* Resulting Y location of the terrain point we hit, in local OpenGL * + * coordinates. */ + float locationY; + /* Resulting Z location of the terrain point we hit, in local OpenGL * + * coordinates. */ + float locationZ; + /* X component of the normal vector to the terrain we found. */ + float normalX; + /* Y component of the normal vector to the terrain we found. */ + float normalY; + /* Z component of the normal vector to the terrain we found. */ + float normalZ; + /* X component of the velocity vector of the terrain we found. */ + float velocityX; + /* Y component of the velocity vector of the terrain we found. */ + float velocityY; + /* Z component of the velocity vector of the terrain we found. */ + float velocityZ; + /* Tells if the surface we hit is water (otherwise it is land). */ + int is_wet; } XPLMProbeInfo_t; /* * XPLMCreateProbe - * - * Creates a new probe object of a given type and returns. + * + * Creates a new probe object of a given type and returns. * */ -XPLM_API XPLMProbeRef XPLMCreateProbe(XPLMProbeType inProbeType); +XPLM_API XPLMProbeRef XPLMCreateProbe( + XPLMProbeType inProbeType); /* * XPLMDestroyProbe - * - * Deallocates an existing probe object. + * + * Deallocates an existing probe object. * */ -XPLM_API void XPLMDestroyProbe(XPLMProbeRef inProbe); +XPLM_API void XPLMDestroyProbe( + XPLMProbeRef inProbe); /* * XPLMProbeTerrainXYZ - * - * Probes the terrain. Pass in the XYZ coordinate of the probe point, a probe - * object, and an XPLMProbeInfo_t struct that has its structSize member set - * properly. Other fields are filled in if we hit terrain, and a probe result - * is returned. + * + * Probes the terrain. Pass in the XYZ coordinate of the probe point, a probe + * object, and an XPLMProbeInfo_t struct that has its structSize member set + * properly. Other fields are filled in if we hit terrain, and a probe result + * is returned. * */ -XPLM_API XPLMProbeResult XPLMProbeTerrainXYZ(XPLMProbeRef inProbe, - float inX, - float inY, - float inZ, - XPLMProbeInfo_t *outInfo); +XPLM_API XPLMProbeResult XPLMProbeTerrainXYZ( + XPLMProbeRef inProbe, + float inX, + float inY, + float inZ, + XPLMProbeInfo_t * outInfo); #endif /* XPLM200 */ +#if defined(XPLM300) +/*************************************************************************** + * Magnetic Variation + ***************************************************************************/ +/* + * Use the magnetic variation (more properly, the "magnetic declination") API + * to find the offset of magnetic north from true north at a given latitude + * and longitude within the simulator. + * + * In the real world, the Earth's magnetic field is irregular, such that true + * north (the direction along a meridian toward the north pole) does not + * necessarily match what a magnetic compass shows as north. + * + * Using this API ensures that you present the same offsets to users as + * X-Plane's built-in instruments. + * + */ + + +/* + * XPLMGetMagneticVariation + * + * Returns X-Plane's simulated magnetic variation (declination) at the + * indication latitude and longitude. + * + */ +XPLM_API float XPLMGetMagneticVariation( + double latitude, + double longitude); + +/* + * XPLMDegTrueToDegMagnetic + * + * Converts a heading in degrees relative to true north into a value relative + * to magnetic north at the user's current location. + * + */ +XPLM_API float XPLMDegTrueToDegMagnetic( + float headingDegreesTrue); + +/* + * XPLMDegMagneticToDegTrue + * + * Converts a heading in degrees relative to magnetic north at the user's + * current location into a value relative to true north. + * + */ +XPLM_API float XPLMDegMagneticToDegTrue( + float headingDegreesMagnetic); + +#endif /* XPLM300 */ /*************************************************************************** * Object Drawing ***************************************************************************/ /* * The object drawing routines let you load and draw X-Plane OBJ files. - * Objects are loaded by file path and managed via an opaque handle. X-Plane + * Objects are loaded by file path and managed via an opaque handle. X-Plane * naturally reference counts objects, so it is important that you balance - * every successful call to XPLMLoadObject with a call to XPLMUnloadObject! + * every successful call to XPLMLoadObject with a call to XPLMUnloadObject! * */ @@ -187,152 +241,159 @@ XPLM_API XPLMProbeResult XPLMProbeTerrainXYZ(XPLMProbeRef inProbe, #if defined(XPLM200) /* * XPLMObjectRef - * + * * An XPLMObjectRef is a opaque handle to an .obj file that has been loaded - * into memory. + * into memory. * */ -typedef void *XPLMObjectRef; +typedef void * XPLMObjectRef; #endif /* XPLM200 */ #if defined(XPLM200) /* * XPLMDrawInfo_t - * + * * The XPLMDrawInfo_t structure contains positioning info for one object that * is to be drawn. Be sure to set structSize to the size of the structure for - * future expansion. + * future expansion. * */ typedef struct { - /* Set this to the size of this structure! */ - int structSize; - /* X location of the object in local coordinates. */ - float x; - /* Y location of the object in local coordinates. */ - float y; - /* Z location of the object in local coordinates. */ - float z; - /* Pitch in degres to rotate the object, positive is up. */ - float pitch; - /* Heading in local coordinates to rotate the object, clockwise. */ - float heading; - /* Roll to rotate the object. */ - float roll; + /* Set this to the size of this structure! */ + int structSize; + /* X location of the object in local coordinates. */ + float x; + /* Y location of the object in local coordinates. */ + float y; + /* Z location of the object in local coordinates. */ + float z; + /* Pitch in degres to rotate the object, positive is up. */ + float pitch; + /* Heading in local coordinates to rotate the object, clockwise. */ + float heading; + /* Roll to rotate the object. */ + float roll; } XPLMDrawInfo_t; #endif /* XPLM200 */ #if defined(XPLM210) /* * XPLMObjectLoaded_f - * + * * You provide this callback when loading an object asynchronously; it will be - * called once the object is loaded. Your refcon is passed back. The object + * called once the object is loaded. Your refcon is passed back. The object * ref passed in is the newly loaded object (ready for use) or NULL if an * error occured. - * + * * If your plugin is disabled, this callback will be delivered as soon as the - * plugin is re-enabled. If your plugin is unloaded before this callback is - * ever called, the SDK will release the object handle for you. + * plugin is re-enabled. If your plugin is unloaded before this callback is + * ever called, the SDK will release the object handle for you. * */ -typedef void (*XPLMObjectLoaded_f)(XPLMObjectRef inObject, void *inRefcon); +typedef void (* XPLMObjectLoaded_f)( + XPLMObjectRef inObject, + void * inRefcon); #endif /* XPLM210 */ #if defined(XPLM200) /* * XPLMLoadObject - * - * This routine loads an OBJ file and returns a handle to it. If X-plane has + * + * This routine loads an OBJ file and returns a handle to it. If X-Plane has * already loaded the object, the handle to the existing object is returned. * Do not assume you will get the same handle back twice, but do make sure to - * call unload once for every load to avoid "leaking" objects. The object - * will be purged from memory when no plugins and no scenery are using it. - * - * The path for the object must be relative to the X-System base folder. If + * call unload once for every load to avoid "leaking" objects. The object will + * be purged from memory when no plugins and no scenery are using it. + * + * The path for the object must be relative to the X-System base folder. If * the path is in the root of the X-System folder you may need to prepend ./ * to it; loading objects in the root of the X-System folder is STRONGLY * discouraged - your plugin should not dump art resources in the root folder! - * - * + * * XPLMLoadObject will return NULL if the object cannot be loaded (either * because it is not found or the file is misformatted). This routine will * load any object that can be used in the X-Plane scenery system. - * + * * It is important that the datarefs an object uses for animation already be - * loaded before you load the object. For this reason it may be necessary to - * defer object loading until the sim has fully started. + * loaded before you load the object. For this reason it may be necessary to + * defer object loading until the sim has fully started. * */ -XPLM_API XPLMObjectRef XPLMLoadObject(const char *inPath); +XPLM_API XPLMObjectRef XPLMLoadObject( + const char * inPath); #endif /* XPLM200 */ #if defined(XPLM210) /* * XPLMLoadObjectAsync - * + * * This routine loads an object asynchronously; control is returned to you - * immediately while X-Plane loads the object. The sim will not stop flying - * while the object loads. For large objects, it may be several seconds - * before the load finishes. - * + * immediately while X-Plane loads the object. The sim will not stop flying + * while the object loads. For large objects, it may be several seconds before + * the load finishes. + * * You provide a callback function that is called once the load has completed. * Note that if the object cannot be loaded, you will not find out until the * callback function is called with a NULL object handle. - * + * * There is no way to cancel an asynchronous object load; you must wait for * the load to complete and then release the object if it is no longer - * desired. + * desired. * */ -XPLM_API void XPLMLoadObjectAsync(const char *inPath, - XPLMObjectLoaded_f inCallback, - void *inRefcon); +XPLM_API void XPLMLoadObjectAsync( + const char * inPath, + XPLMObjectLoaded_f inCallback, + void * inRefcon); #endif /* XPLM210 */ -#if defined(XPLM200) +#if defined(XPLM_DEPRECATED) /* * XPLMDrawObjects - * - * XPLMDrawObjects draws an object from an OBJ file one or more times. You - * pass in the object and an array of XPLMDrawInfo_t structs, one for each + * + * __Deprecation Warning__: use XPLMInstancing to draw 3-d objects by creating + * instances, rather than these APIs from draw callbacks. + * + * XPLMDrawObjects draws an object from an OBJ file one or more times. You + * pass in the object and an array of XPLMDrawInfo_t structs, one for each * place you would like the object to be drawn. - * + * * X-Plane will attempt to cull the objects based on LOD and visibility, and * will pick the appropriate LOD. - * + * * Lighting is a boolean; pass 1 to show the night version of object with - * night-only lights lit up. Pass 0 to show the daytime version of the - * object. - * - * earth_relative controls the coordinate system. If this is 1, the rotations + * night-only lights lit up. Pass 0 to show the daytime version of the object. + * + * earth_relative controls the coordinate system. If this is 1, the rotations * you specify are applied to the object after its coordinate system is * transformed from local to earth-relative coordinates -- that is, an object * with no rotations will point toward true north and the Y axis will be up - * against gravity. If this is 0, the object is drawn with your rotations - * from local coordanates -- that is, an object with no rotations is drawn - * pointing down the -Z axis and the Y axis of the object matches the local - * coordinate Y axis. + * against gravity. If this is 0, the object is drawn with your rotations from + * local coordanates -- that is, an object with no rotations is drawn pointing + * down the -Z axis and the Y axis of the object matches the local coordinate + * Y axis. * */ -XPLM_API void XPLMDrawObjects(XPLMObjectRef inObject, - int inCount, - XPLMDrawInfo_t *inLocations, - int lighting, - int earth_relative); -#endif /* XPLM200 */ +XPLM_API void XPLMDrawObjects( + XPLMObjectRef inObject, + int inCount, + XPLMDrawInfo_t * inLocations, + int lighting, + int earth_relative); +#endif /* XPLM_DEPRECATED */ #if defined(XPLM200) /* * XPLMUnloadObject - * + * * This routine marks an object as no longer being used by your plugin. * Objects are reference counted: once no plugins are using an object, it is - * purged from memory. Make sure to call XPLMUnloadObject once for each - * successful call to XPLMLoadObject. + * purged from memory. Make sure to call XPLMUnloadObject once for each + * successful call to XPLMLoadObject. * */ -XPLM_API void XPLMUnloadObject(XPLMObjectRef inObject); +XPLM_API void XPLMUnloadObject( + XPLMObjectRef inObject); #endif /* XPLM200 */ #if defined(XPLM200) @@ -341,42 +402,45 @@ XPLM_API void XPLMUnloadObject(XPLMObjectRef inObject); ***************************************************************************/ /* * The library access routines allow you to locate scenery objects via the - * X-Plane library system. Right now library access is only provided for + * X-Plane library system. Right now library access is only provided for * objects, allowing plugin-drawn objects to be extended using the library - * system. + * system. * */ /* * XPLMLibraryEnumerator_f - * + * * An XPLMLibraryEnumerator_f is a callback you provide that is called once * for each library element that is located. The returned paths will be - * relative to the X-System folder. + * relative to the X-System folder. * */ -typedef void (*XPLMLibraryEnumerator_f)(const char *inFilePath, void *inRef); +typedef void (* XPLMLibraryEnumerator_f)( + const char * inFilePath, + void * inRef); /* * XPLMLookupObjects - * + * * This routine looks up a virtual path in the library system and returns all - * matching elements. You provide a callback - one virtual path may match - * many objects in the library. XPLMLookupObjects returns the number of - * objects found. - * + * matching elements. You provide a callback - one virtual path may match many + * objects in the library. XPLMLookupObjects returns the number of objects + * found. + * * The latitude and longitude parameters specify the location the object will - * be used. The library system allows for scenery packages to only provide - * objects to certain local locations. Only objects that are allowed at the - * latitude/longitude you provide will be returned. + * be used. The library system allows for scenery packages to only provide + * objects to certain local locations. Only objects that are allowed at the + * latitude/longitude you provide will be returned. * */ -XPLM_API int XPLMLookupObjects(const char *inPath, - float inLatitude, - float inLongitude, - XPLMLibraryEnumerator_f enumerator, - void *ref); +XPLM_API int XPLMLookupObjects( + const char * inPath, + float inLatitude, + float inLongitude, + XPLMLibraryEnumerator_f enumerator, + void * ref); #endif /* XPLM200 */ #ifdef __cplusplus diff --git a/XPSDK/CHeaders/XPLM/XPLMUtilities.h b/XPSDK/CHeaders/XPLM/XPLMUtilities.h index ab57f10..bec319e 100644 --- a/XPSDK/CHeaders/XPLM/XPLMUtilities.h +++ b/XPSDK/CHeaders/XPLM/XPLMUtilities.h @@ -2,18 +2,14 @@ #define _XPLMUtilities_h_ /* - * Copyright 2005-2012 Sandy Barbour and Ben Supnik - * - * All rights reserved. See license.txt for usage. - * - * X-Plane SDK Version: 2.1.1 + * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + * license.txt for usage. X-Plane SDK Version: 2.1.1 * */ -/* - * - * - */ +/*************************************************************************** + * XPLMUtilities + ***************************************************************************/ #include "XPLMDefs.h" @@ -22,689 +18,531 @@ extern "C" { #endif /*************************************************************************** - * X-PLANE USER INTERACTION + * FILE UTILITIES ***************************************************************************/ /* - * The user interaction APIs let you simulate commands the user can do with a - * joystick, keyboard etc. Note that it is generally safer for future - * compatibility to use one of these commands than to manipulate the - * underlying sim data. + * The XPLMUtilities file APIs provide some basic file and path functions for + * use with X-Plane. + * + * Directory Separators + * -------------------- + * + * The XPLM has two modes it can work in: + * + * * X-Plane native paths: all paths are UTF8 strings, using the unix forward + * slash (/) as the directory separating character. In native path mode, + * you use the same path format for all three operating systems. + * + * * Legacy OS paths: the directroy separator is \ for Windows, : for OS X, + * and / for Linux; OS paths are encoded in MacRoman for OS X using legacy + * HFS conventions, use the application code page for multi-byte encoding + * on Unix using DOS path conventions, and use UTF-8 for Linux. + * + * While legacy OS paths are the default, we strongly encourage you to opt in + * to native paths using the XPLMEnableFeature API. + * + * * All OS X plugins should enable native paths all of the time; if you do + * not do this, you will have to convert all paths back from HFS to Unix + * (and deal with MacRoman) - code written using native paths and the C + * file APIs "just works" on OS X. + * + * * For Linux plugins, there is no difference between the two encodings. + * + * * Windows plugins will need to convert the UTF8 file paths to UTF16 for + * use with the "wide" APIs. While it might seem tempting to stick with + * legacy OS paths (and just use the "ANSI" Windows APIs), X-Plane is fully + * unicode-capable, and will often be installed in paths where the user's + * directories have no ACP encoding. + * + * Full and Relative Paths + * ----------------------- + * + * Some of these APIs use full paths, but others use paths relative to the + * user's X-Plane installation. This is documented on a per-API basis. * */ -/* - * XPLMCommandKeyID - * - * These enums represent all the keystrokes available within x-plane. They - * can be sent to x-plane directly. For example, you can reverse thrust using - * these enumerations. - * - */ -enum { - xplm_key_pause = 0, - xplm_key_revthrust, - xplm_key_jettison, - xplm_key_brakesreg, - xplm_key_brakesmax, - xplm_key_gear, - xplm_key_timedn, - xplm_key_timeup, - xplm_key_fadec, - xplm_key_otto_dis, - xplm_key_otto_atr, - xplm_key_otto_asi, - xplm_key_otto_hdg, - xplm_key_otto_gps, - xplm_key_otto_lev, - xplm_key_otto_hnav, - xplm_key_otto_alt, - xplm_key_otto_vvi, - xplm_key_otto_vnav, - xplm_key_otto_nav1, - xplm_key_otto_nav2, - xplm_key_targ_dn, - xplm_key_targ_up, - xplm_key_hdgdn, - xplm_key_hdgup, - xplm_key_barodn, - xplm_key_baroup, - xplm_key_obs1dn, - xplm_key_obs1up, - xplm_key_obs2dn, - xplm_key_obs2up, - xplm_key_com1_1, - xplm_key_com1_2, - xplm_key_com1_3, - xplm_key_com1_4, - xplm_key_nav1_1, - xplm_key_nav1_2, - xplm_key_nav1_3, - xplm_key_nav1_4, - xplm_key_com2_1, - xplm_key_com2_2, - xplm_key_com2_3, - xplm_key_com2_4, - xplm_key_nav2_1, - xplm_key_nav2_2, - xplm_key_nav2_3, - xplm_key_nav2_4, - xplm_key_adf_1, - xplm_key_adf_2, - xplm_key_adf_3, - xplm_key_adf_4, - xplm_key_adf_5, - xplm_key_adf_6, - xplm_key_transpon_1, - xplm_key_transpon_2, - xplm_key_transpon_3, - xplm_key_transpon_4, - xplm_key_transpon_5, - xplm_key_transpon_6, - xplm_key_transpon_7, - xplm_key_transpon_8, - xplm_key_flapsup, - xplm_key_flapsdn, - xplm_key_cheatoff, - xplm_key_cheaton, - xplm_key_sbrkoff, - xplm_key_sbrkon, - xplm_key_ailtrimL, - xplm_key_ailtrimR, - xplm_key_rudtrimL, - xplm_key_rudtrimR, - xplm_key_elvtrimD, - xplm_key_elvtrimU, - xplm_key_forward, - xplm_key_down, - xplm_key_left, - xplm_key_right, - xplm_key_back, - xplm_key_tower, - xplm_key_runway, - xplm_key_chase, - xplm_key_free1, - xplm_key_free2, - xplm_key_spot, - xplm_key_fullscrn1, - xplm_key_fullscrn2, - xplm_key_tanspan, - xplm_key_smoke, - xplm_key_map, - xplm_key_zoomin, - xplm_key_zoomout, - xplm_key_cycledump, - xplm_key_replay, - xplm_key_tranID, - xplm_key_max -}; -typedef int XPLMCommandKeyID; - -/* - * XPLMCommandButtonID - * - * These are enumerations for all of the things you can do with a joystick - * button in X-Plane. They currently match the buttons menu in the equipment - * setup dialog, but these enums will be stable even if they change in - * X-Plane. - * - */ -enum { - xplm_joy_nothing = 0, - xplm_joy_start_all, - xplm_joy_start_0, - xplm_joy_start_1, - xplm_joy_start_2, - xplm_joy_start_3, - xplm_joy_start_4, - xplm_joy_start_5, - xplm_joy_start_6, - xplm_joy_start_7, - xplm_joy_throt_up, - xplm_joy_throt_dn, - xplm_joy_prop_up, - xplm_joy_prop_dn, - xplm_joy_mixt_up, - xplm_joy_mixt_dn, - xplm_joy_carb_tog, - xplm_joy_carb_on, - xplm_joy_carb_off, - xplm_joy_trev, - xplm_joy_trm_up, - xplm_joy_trm_dn, - xplm_joy_rot_trm_up, - xplm_joy_rot_trm_dn, - xplm_joy_rud_lft, - xplm_joy_rud_cntr, - xplm_joy_rud_rgt, - xplm_joy_ail_lft, - xplm_joy_ail_cntr, - xplm_joy_ail_rgt, - xplm_joy_B_rud_lft, - xplm_joy_B_rud_rgt, - xplm_joy_look_up, - xplm_joy_look_dn, - xplm_joy_look_lft, - xplm_joy_look_rgt, - xplm_joy_glance_l, - xplm_joy_glance_r, - xplm_joy_v_fnh, - xplm_joy_v_fwh, - xplm_joy_v_tra, - xplm_joy_v_twr, - xplm_joy_v_run, - xplm_joy_v_cha, - xplm_joy_v_fr1, - xplm_joy_v_fr2, - xplm_joy_v_spo, - xplm_joy_flapsup, - xplm_joy_flapsdn, - xplm_joy_vctswpfwd, - xplm_joy_vctswpaft, - xplm_joy_gear_tog, - xplm_joy_gear_up, - xplm_joy_gear_down, - xplm_joy_lft_brake, - xplm_joy_rgt_brake, - xplm_joy_brakesREG, - xplm_joy_brakesMAX, - xplm_joy_speedbrake, - xplm_joy_ott_dis, - xplm_joy_ott_atr, - xplm_joy_ott_asi, - xplm_joy_ott_hdg, - xplm_joy_ott_alt, - xplm_joy_ott_vvi, - xplm_joy_tim_start, - xplm_joy_tim_reset, - xplm_joy_ecam_up, - xplm_joy_ecam_dn, - xplm_joy_fadec, - xplm_joy_yaw_damp, - xplm_joy_art_stab, - xplm_joy_chute, - xplm_joy_JATO, - xplm_joy_arrest, - xplm_joy_jettison, - xplm_joy_fuel_dump, - xplm_joy_puffsmoke, - xplm_joy_prerotate, - xplm_joy_UL_prerot, - xplm_joy_UL_collec, - xplm_joy_TOGA, - xplm_joy_shutdown, - xplm_joy_con_atc, - xplm_joy_fail_now, - xplm_joy_pause, - xplm_joy_rock_up, - xplm_joy_rock_dn, - xplm_joy_rock_lft, - xplm_joy_rock_rgt, - xplm_joy_rock_for, - xplm_joy_rock_aft, - xplm_joy_idle_hilo, - xplm_joy_lanlights, - xplm_joy_max -}; -typedef int XPLMCommandButtonID; - -/* - * XPLMHostApplicationID - * - * The plug-in system is based on Austin's cross-platform OpenGL framework and - * could theoretically be adapted to run in other apps like WorldMaker. The - * plug-in system also runs against a test harness for internal development - * and could be adapted to another flight sim (in theory at least). So an ID - * is providing allowing plug-ins to indentify what app they are running - * under. - * - */ -enum { - xplm_Host_Unknown = 0 - - , - xplm_Host_XPlane = 1 - - , - xplm_Host_PlaneMaker = 2 - - , - xplm_Host_WorldMaker = 3 - - , - xplm_Host_Briefer = 4 - - , - xplm_Host_PartMaker = 5 - - , - xplm_Host_YoungsMod = 6 - - , - xplm_Host_XAuto = 7 - - -}; -typedef int XPLMHostApplicationID; - -/* - * XPLMLanguageCode - * - * These enums define what language the sim is running in. These enumerations - * do not imply that the sim can or does run in all of these languages; they - * simply provide a known encoding in the event that a given sim version is - * localized to a certain language. - * - */ -enum { - xplm_Language_Unknown = 0 - - , - xplm_Language_English = 1 - - , - xplm_Language_French = 2 - - , - xplm_Language_German = 3 - - , - xplm_Language_Italian = 4 - - , - xplm_Language_Spanish = 5 - - , - xplm_Language_Korean = 6 - -#if defined(XPLM200) - , - xplm_Language_Russian = 7 - -#endif /* XPLM200 */ -#if defined(XPLM200) - , - xplm_Language_Greek = 8 - -#endif /* XPLM200 */ -#if defined(XPLM200) - , - xplm_Language_Japanese = 9 - -#endif /* XPLM200 */ -#if defined(XPLM200) - , - xplm_Language_Chinese = 10 - -#endif /* XPLM200 */ - -}; -typedef int XPLMLanguageCode; - #if defined(XPLM200) /* * XPLMDataFileType - * + * * These enums define types of data files you can load or unload using the - * SDK. + * SDK. * */ enum { - /* A situation (.sit) file, which starts off a flight in a given * - * configuration. */ - xplm_DataFile_Situation = 1 + /* A situation (.sit) file, which starts off a flight in a given * + * configuration. */ + xplm_DataFile_Situation = 1, - /* A situation movie (.smo) file, which replays a past flight. */ - , - xplm_DataFile_ReplayMovie = 2 + /* A situation movie (.smo) file, which replays a past flight. */ + xplm_DataFile_ReplayMovie = 2, }; typedef int XPLMDataFileType; #endif /* XPLM200 */ -#if defined(XPLM200) -/* - * XPLMError_f - * - * An XPLM error callback is a function that you provide to receive debugging - * information from the plugin SDK. See XPLMSetErrorCallback for more - * information. NOTE: for the sake of debugging, your error callback will be - * called even if your plugin is not enabled, allowing you to receive debug - * info in your XPluginStart and XPluginStop callbacks. To avoid causing - * logic errors in the management code, do not call any other plugin routines - * from your error callback - it is only meant for logging! - * - */ -typedef void (*XPLMError_f)(const char *inMessage); -#endif /* XPLM200 */ - -/* - * XPLMSimulateKeyPress - * - * This function simulates a key being pressed for x-plane. The keystroke - * goes directly to x-plane; it is never sent to any plug-ins. However, since - * this is a raw key stroke it may be mapped by the keys file or enter text - * into a field. - * - * WARNING: This function will be deprecated; do not use it. Instead use - * XPLMCommandKeyStroke. - * - */ -XPLM_API void XPLMSimulateKeyPress(int inKeyType, int inKey); - -/* - * XPLMSpeakString - * - * This function displays the string in a translucent overlay over the current - * display and also speaks the string if text-to-speech is enabled. The - * string is spoken asynchronously, this function returns immediately. - * - */ -XPLM_API void XPLMSpeakString(const char *inString); - -/* - * XPLMCommandKeyStroke - * - * This routine simulates a command-key stroke. However, the keys are done by - * function, not by actual letter, so this function works even if the user has - * remapped their keyboard. Examples of things you might do with this include - * pausing the simulator. - * - */ -XPLM_API void XPLMCommandKeyStroke(XPLMCommandKeyID inKey); - -/* - * XPLMCommandButtonPress - * - * This function simulates any of the actions that might be taken by pressing - * a joystick button. However, this lets you call the command directly rather - * than have to know which button is mapped where. Important: you must - * release each button you press. The APIs are separate so that you can 'hold - * down' a button for a fixed amount of time. - * - */ -XPLM_API void XPLMCommandButtonPress(XPLMCommandButtonID inButton); - -/* - * XPLMCommandButtonRelease - * - * This function simulates any of the actions that might be taken by pressing - * a joystick button. See XPLMCommandButtonPress - * - */ -XPLM_API void XPLMCommandButtonRelease(XPLMCommandButtonID inButton); - -/* - * XPLMGetVirtualKeyDescription - * - * Given a virtual key code (as defined in XPLMDefs.h) this routine returns a - * human-readable string describing the character. This routine is provided - * for showing users what keyboard mappings they have set up. The string may - * read 'unknown' or be a blank or NULL string if the virtual key is unknown. - * - */ -XPLM_API const char *XPLMGetVirtualKeyDescription(char inVirtualKey); - -/*************************************************************************** - * X-PLANE MISC - ***************************************************************************/ -/* - * - * - */ - - -/* - * XPLMReloadScenery - * - * XPLMReloadScenery reloads the current set of scenery. You can use this - * function in two typical ways: simply call it to reload the scenery, picking - * up any new installed scenery, .env files, etc. from disk. Or, change the - * lat/ref and lon/ref data refs and then call this function to shift the - * scenery environment. - * - */ -XPLM_API void XPLMReloadScenery(void); - /* * XPLMGetSystemPath - * - * This function returns the full path to the X-System folder. Note that this - * is a directory path, so it ends in a trailing : or /. The buffer you pass - * should be at least 512 characters long. + * + * This function returns the full path to the X-System folder. Note that this + * is a directory path, so it ends in a trailing : or /. + * + * The buffer you pass should be at least 512 characters long. The path is + * returned using the current native or OS path conventions. * */ -XPLM_API void XPLMGetSystemPath(char *outSystemPath); +XPLM_API void XPLMGetSystemPath( + char * outSystemPath); /* * XPLMGetPrefsPath - * - * This routine returns a full path to the proper directory to store - * preferences in. It ends in a : or /. The buffer you pass should be at - * least 512 characters long. + * + * This routine returns a full path to a file that is within X-Plane's + * preferences directory. (You should remove the file name back to the last + * directory separator to get the preferences directory using + * XPLMExtractFileAndPath.) + * + * The buffer you pass should be at least 512 characters long. The path is + * returned using the current native or OS path conventions. * */ -XPLM_API void XPLMGetPrefsPath(char *outPrefsPath); +XPLM_API void XPLMGetPrefsPath( + char * outPrefsPath); /* * XPLMGetDirectorySeparator - * + * * This routine returns a string with one char and a null terminator that is - * the directory separator for the current platform. This allows you to write + * the directory separator for the current platform. This allows you to write * code that concatinates directory paths without having to #ifdef for - * platform. + * platform. The character returned will reflect the current file path mode. * */ -XPLM_API const char *XPLMGetDirectorySeparator(void); +XPLM_API const char * XPLMGetDirectorySeparator(void); /* * XPLMExtractFileAndPath - * + * * Given a full path to a file, this routine separates the path from the file. * If the path is a partial directory (e.g. ends in : or \) the trailing - * directory separator is removed. This routine works in-place; a pointer to + * directory separator is removed. This routine works in-place; a pointer to * the file part of the buffer is returned; the original buffer still starts - * with the path. + * with the path and is null terminated with no trailing separator. * */ -XPLM_API char *XPLMExtractFileAndPath(char *inFullPath); +XPLM_API char * XPLMExtractFileAndPath( + char * inFullPath); /* * XPLMGetDirectoryContents - * + * * This routine returns a list of files in a directory (specified by a full - * path, no trailing : or \). The output is returned as a list of NULL + * path, no trailing : or \). The output is returned as a list of NULL * terminated strings. An index array (if specified) is filled with pointers - * into the strings. This routine The last file is indicated by a zero-length - * string (and NULL in the indices). This routine will return 1 if you had - * capacity for all files or 0 if you did not. You can also skip a given - * number of files. - * - * inDirectoryPath - a null terminated C string containing the full path to - * the directory with no trailing directory char. - * - * inFirstReturn - the zero-based index of the first file in the directory to - * return. (Usually zero to fetch all in one pass.) - * - * outFileNames - a buffer to receive a series of sequential null terminated - * C-string file names. A zero-length C string will be appended to the very - * end. - * - * inFileNameBufSize - the size of the file name buffer in bytes. - * - * outIndices - a pointer to an array of character pointers that will become - * an index into the directory. The last file will be followed by a NULL - * value. Pass NULL if you do not want indexing information. - * - * inIndexCount - the max size of the index in entries. - * - * outTotalFiles - if not NULL, this is filled in with the number of files in - * the directory. - * - * outReturnedFiles - if not NULL, the number of files returned by this - * iteration. - * - * Return value - 1 if all info could be returned, 0 if there was a buffer + * into the strings. The last file is indicated by a zero-length string (and + * NULL in the indices). This routine will return 1 if you had capacity for + * all files or 0 if you did not. You can also skip a given number of files. + * + * * inDirectoryPath - a null terminated C string containing the full path to + * the directory with no trailing directory char. + * + * * inFirstReturn - the zero-based index of the first file in the directory + * to return. (Usually zero to fetch all in one pass.) + * + * * outFileNames - a buffer to receive a series of sequential null + * terminated C-string file names. A zero-length C string will be appended + * to the very end. + * + * * inFileNameBufSize - the size of the file name buffer in bytes. + * + * * outIndices - a pointer to an array of character pointers that will + * become an index into the directory. The last file will be followed by a + * NULL value. Pass NULL if you do not want indexing information. + * + * * inIndexCount - the max size of the index in entries. + * + * * outTotalFiles - if not NULL, this is filled in with the number of files + * in the directory. + * + * * outReturnedFiles - if not NULL, the number of files returned by this + * iteration. + * + * Return value: 1 if all info could be returned, 0 if there was a buffer * overrun. - * + * * WARNING: Before X-Plane 7 this routine did not properly iterate through - * directories. If X-Plane 6 compatibility is needed, use your own code to - * iterate directories. + * directories. If X-Plane + * 6 compatibility is needed, use your own code to iterate directories. * */ -XPLM_API int XPLMGetDirectoryContents(const char *inDirectoryPath, - int inFirstReturn, - char *outFileNames, - int inFileNameBufSize, - char **outIndices, /* Can be NULL */ - int inIndexCount, - int *outTotalFiles, /* Can be NULL */ - int *outReturnedFiles); /* Can be NULL */ - -/* - * XPLMInitialized - * - * This function returns 1 if X-Plane has properly initialized the plug-in - * system. If this routine returns 0, many XPLM functions will not work. - * - * NOTE: Under normal circumstances a plug-in should never be running while - * the plug-in manager is not initialized. - * - * WARNING: This function is generally not needed and may be deprecated in the - * future. - * - */ -XPLM_API int XPLMInitialized(void); - -/* - * XPLMGetVersions - * - * This routine returns the revision of both X-Plane and the XPLM DLL. All - * versions are three-digit decimal numbers (e.g. 606 for version 6.06 of - * X-Plane); the current revision of the XPLM is 200 (2.00). This routine - * also returns the host ID of the app running us. - * - * The most common use of this routine is to special-case around x-plane - * version-specific behavior. - * - */ -XPLM_API void XPLMGetVersions(int *outXPlaneVersion, - int *outXPLMVersion, - XPLMHostApplicationID *outHostID); - -/* - * XPLMGetLanguage - * - * This routine returns the langauge the sim is running in. - * - */ -XPLM_API XPLMLanguageCode XPLMGetLanguage(void); - -/* - * XPLMDebugString - * - * This routine outputs a C-style string to the Log.txt file. The file is - * immediately flushed so you will not lose data. (This does cause a - * performance penalty.) - * - */ -XPLM_API void XPLMDebugString(const char *inString); - -#if defined(XPLM200) -/* - * XPLMSetErrorCallback - * - * XPLMSetErrorCallback installs an error-reporting callback for your plugin. - * Normally the plugin system performs minimum diagnostics to maximize - * performance. When you install an error callback, you will receive calls - * due to certain plugin errors, such as passing bad parameters or incorrect - * data. - * - * The intention is for you to install the error callback during debug - * sections and put a break-point inside your callback. This will cause you - * to break into the debugger from within the SDK at the point in your plugin - * where you made an illegal call. - * - * Installing an error callback may activate error checking code that would - * not normally run, and this may adversely affect performance, so do not - * leave error callbacks installed in shipping plugins. - * - */ -XPLM_API void XPLMSetErrorCallback(XPLMError_f inCallback); -#endif /* XPLM200 */ - -#if defined(XPLM200) -/* - * XPLMFindSymbol - * - * This routine will attempt to find the symbol passed in the inString - * parameter. If the symbol is found a pointer the function is returned, - * othewise the function will return NULL. - * - */ -XPLM_API void *XPLMFindSymbol(const char *inString); -#endif /* XPLM200 */ +XPLM_API int XPLMGetDirectoryContents( + const char * inDirectoryPath, + int inFirstReturn, + char * outFileNames, + int inFileNameBufSize, + char ** outIndices, /* Can be NULL */ + int inIndexCount, + int * outTotalFiles, /* Can be NULL */ + int * outReturnedFiles); /* Can be NULL */ #if defined(XPLM200) /* * XPLMLoadDataFile - * - * Loads a data file of a given type. Paths must be relative to the X-System + * + * Loads a data file of a given type. Paths must be relative to the X-System * folder. To clear the replay, pass a NULL file name (this is only valid with - * replay movies, not sit files). + * replay movies, not sit files). * */ -XPLM_API int XPLMLoadDataFile(XPLMDataFileType inFileType, - const char *inFilePath); /* Can be NULL */ -#endif /* XPLM200 */ +XPLM_API int XPLMLoadDataFile( + XPLMDataFileType inFileType, + const char * inFilePath); /* Can be NULL */ +#endif /* XPLM200 */ #if defined(XPLM200) /* * XPLMSaveDataFile - * + * * Saves the current situation or replay; paths are relative to the X-System - * folder. + * folder. * */ -XPLM_API int XPLMSaveDataFile(XPLMDataFileType inFileType, - const char *inFilePath); +XPLM_API int XPLMSaveDataFile( + XPLMDataFileType inFileType, + const char * inFilePath); #endif /* XPLM200 */ +/*************************************************************************** + * X-PLANE MISC + ***************************************************************************/ + +/* + * XPLMHostApplicationID + * + * While the plug-in SDK is only accessible to plugins running inside X-Plane, + * the original authors considered extending the API to other applications + * that shared basic infrastructure with X-Plane. These enumerations are + * hold-overs from that original roadmap; all values other than X-Plane are + * deprecated. Your plugin should never need this enumeration. + * + */ +enum { + xplm_Host_Unknown = 0, + + xplm_Host_XPlane = 1, + +#if defined(XPLM_DEPRECATED) + xplm_Host_PlaneMaker = 2, + +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + xplm_Host_WorldMaker = 3, + +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + xplm_Host_Briefer = 4, + +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + xplm_Host_PartMaker = 5, + +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + xplm_Host_YoungsMod = 6, + +#endif /* XPLM_DEPRECATED */ +#if defined(XPLM_DEPRECATED) + xplm_Host_XAuto = 7, + +#endif /* XPLM_DEPRECATED */ + +}; +typedef int XPLMHostApplicationID; + +/* + * XPLMLanguageCode + * + * These enums define what language the sim is running in. These enumerations + * do not imply that the sim can or does run in all of these languages; they + * simply provide a known encoding in the event that a given sim version is + * localized to a certain language. + * + */ +enum { + xplm_Language_Unknown = 0, + + xplm_Language_English = 1, + + xplm_Language_French = 2, + + xplm_Language_German = 3, + + xplm_Language_Italian = 4, + + xplm_Language_Spanish = 5, + + xplm_Language_Korean = 6, + +#if defined(XPLM200) + xplm_Language_Russian = 7, + +#endif /* XPLM200 */ +#if defined(XPLM200) + xplm_Language_Greek = 8, + +#endif /* XPLM200 */ +#if defined(XPLM200) + xplm_Language_Japanese = 9, + +#endif /* XPLM200 */ +#if defined(XPLM300) + xplm_Language_Chinese = 10, + +#endif /* XPLM300 */ + +}; +typedef int XPLMLanguageCode; + +#if defined(XPLM200) +/* + * XPLMError_f + * + * An XPLM error callback is a function that you provide to receive debugging + * information from the plugin SDK. See XPLMSetErrorCallback for more + * information. NOTE: for the sake of debugging, your error callback will be + * called even if your plugin is not enabled, allowing you to receive debug + * info in your XPluginStart and XPluginStop callbacks. To avoid causing logic + * errors in the management code, do not call any other plugin routines from + * your error callback - it is only meant for catching errors in the + * debugging. + * + */ +typedef void (* XPLMError_f)( + const char * inMessage); +#endif /* XPLM200 */ + +#if defined(XPLM_DEPRECATED) +/* + * XPLMInitialized + * + * Deprecated: This function returns 1 if X-Plane has properly initialized the + * plug-in system. If this routine returns 0, many XPLM functions will not + * work. + * + * NOTE: because plugins are always called from within the XPLM, there is no + * need to check for initialization; it will always return 1. This routine is + * deprecated - you do not need to check it before continuing within your + * plugin. + * + */ +XPLM_API int XPLMInitialized(void); +#endif /* XPLM_DEPRECATED */ + +/* + * XPLMGetVersions + * + * This routine returns the revision of both X-Plane and the XPLM DLL. All + * versions are three-digit decimal numbers (e.g. 606 for version 6.06 of + * X-Plane); the current revision of the XPLM is 200 (2.00). This routine also + * returns the host ID of the app running us. + * + * The most common use of this routine is to special-case around X-Plane + * version-specific behavior. + * + */ +XPLM_API void XPLMGetVersions( + int * outXPlaneVersion, + int * outXPLMVersion, + XPLMHostApplicationID * outHostID); + +/* + * XPLMGetLanguage + * + * This routine returns the langauge the sim is running in. + * + */ +XPLM_API XPLMLanguageCode XPLMGetLanguage(void); + +#if defined(XPLM200) +/* + * XPLMFindSymbol + * + * This routine will attempt to find the symbol passed in the inString + * parameter. If the symbol is found a pointer the function is returned, + * othewise the function will return NULL. + * + * You can use XPLMFindSymbol to utilize newer SDK API features without + * requiring newer versions of the SDK (and X-Plane) as your minimum X-Plane + * version as follows: + * + * * Define the XPLMnnn macro to the minimum required XPLM version you will + * ship with (e.g. XPLM210 for X-Plane 10 compatibility). + * + * * Use XPLMGetVersions and XPLMFindSymbol to detect that the host sim is + * new enough to use new functions and resolve function pointers. + * + * * Conditionally use the new functions if and only if XPLMFindSymbol only + * returns a non- NULL pointer. + * + * Warning: you should always check the XPLM API version as well as the + * results of XPLMFindSymbol to determine if funtionality is safe to use. + * + * To use functionality via XPLMFindSymbol you will need to copy your own + * definitions of the X-Plane API prototypes and cast the returned pointer to + * the correct type. + * + */ +XPLM_API void * XPLMFindSymbol( + const char * inString); +#endif /* XPLM200 */ + +#if defined(XPLM200) +/* + * XPLMSetErrorCallback + * + * XPLMSetErrorCallback installs an error-reporting callback for your plugin. + * Normally the plugin system performs minimum diagnostics to maximize + * performance. When you install an error callback, you will receive calls due + * to certain plugin errors, such as passing bad parameters or incorrect data. + * + * Important: the error callback determines *programming* errors, e.g. bad API + * parameters. Every error that is returned by the error callback represents a + * mistake in your plugin that you should fix. Error callbacks are not used to + * report expected run-time problems (e.g. disk I/O errors). + * + * The intention is for you to install the error callback during debug + * sections and put a break-point inside your callback. This will cause you to + * break into the debugger from within the SDK at the point in your plugin + * where you made an illegal call. + * + * Installing an error callback may activate error checking code that would + * not normally run, and this may adversely affect performance, so do not + * leave error callbacks installed in shipping plugins. Since the only useful + * response to an error is to change code, error callbacks are not useful "in + * the field". + * + */ +XPLM_API void XPLMSetErrorCallback( + XPLMError_f inCallback); +#endif /* XPLM200 */ + +/* + * XPLMDebugString + * + * This routine outputs a C-style string to the Log.txt file. The file is + * immediately flushed so you will not lose data. (This does cause a + * performance penalty.) + * + * Please do *not* leave routine diagnostic logging enabled in your shipping + * plugin. The X-Plane Log file is shared by X-Plane and every plugin in the + * system, and plugins that (when functioning normally) print verbose log + * output make it difficult for developers to find error conditions from other + * parts of the system. + * + */ +XPLM_API void XPLMDebugString( + const char * inString); + +/* + * XPLMSpeakString + * + * This function displays the string in a translucent overlay over the current + * display and also speaks the string if text-to-speech is enabled. The string + * is spoken asynchronously, this function returns immediately. This function + * may not speak or print depending on user preferences. + * + */ +XPLM_API void XPLMSpeakString( + const char * inString); + +/* + * XPLMGetVirtualKeyDescription + * + * Given a virtual key code (as defined in XPLMDefs.h) this routine returns a + * human-readable string describing the character. This routine is provided + * for showing users what keyboard mappings they have set up. The string may + * read 'unknown' or be a blank or NULL string if the virtual key is unknown. + * + */ +XPLM_API const char * XPLMGetVirtualKeyDescription( + char inVirtualKey); + +/* + * XPLMReloadScenery + * + * XPLMReloadScenery reloads the current set of scenery. You can use this + * function in two typical ways: simply call it to reload the scenery, picking + * up any new installed scenery, .env files, etc. from disk. Or, change the + * lat/ref and lon/ref data refs and then call this function to shift the + * scenery environment. This routine is equivalent to picking "reload + * scenery" from the developer menu. + * + */ +XPLM_API void XPLMReloadScenery(void); + #if defined(XPLM200) /*************************************************************************** * X-PLANE COMMAND MANAGEMENT ***************************************************************************/ /* * The command management APIs let plugins interact with the command-system in - * X-Plane, the abstraction behind keyboard presses and joystick buttons. - * This API lets you create new commands and modify the behavior (or get + * X-Plane, the abstraction behind keyboard presses and joystick buttons. This + * API lets you create new commands and modify the behavior (or get * notification) of existing ones. - * + * + * X-Plane Command Phases + * ---------------------- + * + * X-Plane commands are not instantaneous; they operate over a duration. + * (Think of a joystick button press - you can press, hold down, and then + * release the joystick button; X-Plane commands model this entire process.) + * * An X-Plane command consists of three phases: a beginning, continuous - * repetition, and an ending. The command may be repeated zero times in the - * event that the user presses a button only momentarily. + * repetition, and an ending. The command may be repeated zero times in its + * duration, followed by one command ending. Command begin and end messges are + * balanced, but a command may be bound to more than one event source (e.g. a + * keyboard key and a joystick button), in which case you may receive a second + * begin during before any end). + * + * When you issue commands in the plugin system, you *must* balance every call + * to XPLMCommandBegin with a call to XPLMCommandEnd with the same command + * reference. + * + * Command Behavior Modification + * ----------------------------- + * + * You can register a callback to handle a command either before or after + * X-Plane does; if you receive the command before X-Plane you have the option + * to either let X-Plane handle the command or hide the command from X-Plane. + * This lets plugins both augment commands and replace them. + * + * If you register for an existing command, be sure that you are *consistent* + * in letting X-Plane handle or not handle the command; you are responsible + * for passing a *balanced* number of begin and end messages to X-Plane. (E.g. + * it is not legal to pass all the begin messages to X-Plane but hide all the + * end messages). * */ /* * XPLMCommandPhase - * - * The phases of a command. + * + * The phases of a command. * */ enum { - /* The command is being started. */ - xplm_CommandBegin = 0 + /* The command is being started. */ + xplm_CommandBegin = 0, - /* The command is continuing to execute. */ - , - xplm_CommandContinue = 1 + /* The command is continuing to execute. */ + xplm_CommandContinue = 1, - /* The command has ended. */ - , - xplm_CommandEnd = 2 + /* The command has ended. */ + xplm_CommandEnd = 2, }; @@ -712,116 +550,419 @@ typedef int XPLMCommandPhase; /* * XPLMCommandRef - * - * A command ref is an opaque identifier for an X-Plane command. Command + * + * A command ref is an opaque identifier for an X-Plane command. Command * references stay the same for the life of your plugin but not between - * executions of X-Plane. Command refs are used to execute commands, create + * executions of X-Plane. Command refs are used to execute commands, create * commands, and create callbacks for particular commands. - * - * Note that a command is not "owned" by a particular plugin. Since many + * + * Note that a command is not "owned" by a particular plugin. Since many * plugins may participate in a command's execution, the command does not go - * away if the plugin that created it is unloaded. + * away if the plugin that created it is unloaded. * */ -typedef void *XPLMCommandRef; +typedef void * XPLMCommandRef; /* * XPLMCommandCallback_f - * + * * A command callback is a function in your plugin that is called when a - * command is pressed. Your callback receives the commadn reference for the + * command is pressed. Your callback receives the command reference for the * particular command, the phase of the command that is executing, and a * reference pointer that you specify when registering the callback. - * + * * Your command handler should return 1 to let processing of the command - * continue to other plugins and X-Plane, or 0 to halt processing, - * potentially bypassing X-Plane code. + * continue to other plugins and X-Plane, or 0 to halt processing, potentially + * bypassing X-Plane code. * */ -typedef int (*XPLMCommandCallback_f)(XPLMCommandRef inCommand, - XPLMCommandPhase inPhase, - void *inRefcon); +typedef int (* XPLMCommandCallback_f)( + XPLMCommandRef inCommand, + XPLMCommandPhase inPhase, + void * inRefcon); /* * XPLMFindCommand - * + * * XPLMFindCommand looks up a command by name, and returns its command - * reference or NULL if the command does not exist. + * reference or NULL if the command does not exist. * */ -XPLM_API XPLMCommandRef XPLMFindCommand(const char *inName); +XPLM_API XPLMCommandRef XPLMFindCommand( + const char * inName); /* * XPLMCommandBegin - * + * * XPLMCommandBegin starts the execution of a command, specified by its - * command reference. The command is "held down" until XPLMCommandEnd is - * called. + * command reference. The command is "held down" until XPLMCommandEnd is + * called. You must balance each XPLMCommandBegin call with an XPLMCommandEnd + * call. * */ -XPLM_API void XPLMCommandBegin(XPLMCommandRef inCommand); +XPLM_API void XPLMCommandBegin( + XPLMCommandRef inCommand); /* * XPLMCommandEnd - * + * * XPLMCommandEnd ends the execution of a given command that was started with - * XPLMCommandBegin. + * XPLMCommandBegin. You must not issue XPLMCommandEnd for a command you did + * not begin. * */ -XPLM_API void XPLMCommandEnd(XPLMCommandRef inCommand); +XPLM_API void XPLMCommandEnd( + XPLMCommandRef inCommand); /* * XPLMCommandOnce - * + * * This executes a given command momentarily, that is, the command begins and - * ends immediately. + * ends immediately. This is the equivalent of calling XPLMCommandBegin() and + * XPLMCommandEnd() back ot back. * */ -XPLM_API void XPLMCommandOnce(XPLMCommandRef inCommand); +XPLM_API void XPLMCommandOnce( + XPLMCommandRef inCommand); /* * XPLMCreateCommand - * - * XPLMCreateCommand creates a new command for a given string. If the command - * already exists, the existing command reference is returned. The - * description may appear in user interface contexts, such as the joystick - * configuration screen. + * + * XPLMCreateCommand creates a new command for a given string. If the command + * already exists, the existing command reference is returned. The description + * may appear in user interface contexts, such as the joystick configuration + * screen. * */ -XPLM_API XPLMCommandRef XPLMCreateCommand(const char *inName, - const char *inDescription); +XPLM_API XPLMCommandRef XPLMCreateCommand( + const char * inName, + const char * inDescription); /* * XPLMRegisterCommandHandler - * + * * XPLMRegisterCommandHandler registers a callback to be called when a command - * is executed. You provide a callback with a reference pointer. - * + * is executed. You provide a callback with a reference pointer. + * * If inBefore is true, your command handler callback will be executed before * X-Plane executes the command, and returning 0 from your callback will - * disable X-Plane's processing of the command. If inBefore is false, your - * callback will run after X-Plane. (You can register a single callback both - * before and after a command.) + * disable X-Plane's processing of the command. If inBefore is false, your + * callback will run after X-Plane. (You can register a single callback both + * before and after a command.) * */ -XPLM_API void XPLMRegisterCommandHandler(XPLMCommandRef inComand, - XPLMCommandCallback_f inHandler, - int inBefore, - void *inRefcon); +XPLM_API void XPLMRegisterCommandHandler( + XPLMCommandRef inComand, + XPLMCommandCallback_f inHandler, + int inBefore, + void * inRefcon); /* * XPLMUnregisterCommandHandler - * + * * XPLMUnregisterCommandHandler removes a command callback registered with - * XPLMRegisterCommandHandler. + * XPLMRegisterCommandHandler. * */ -XPLM_API void XPLMUnregisterCommandHandler(XPLMCommandRef inComand, - XPLMCommandCallback_f inHandler, - int inBefore, - void *inRefcon); +XPLM_API void XPLMUnregisterCommandHandler( + XPLMCommandRef inComand, + XPLMCommandCallback_f inHandler, + int inBefore, + void * inRefcon); #endif /* XPLM200 */ +#if defined(XPLM_DEPRECATED) +/*************************************************************************** + * X-PLANE USER INTERACTION + ***************************************************************************/ +/* + * WARNING: The legacy user interaction API is deprecated; while it was the + * only way to run commands in X-Plane 6,7 and 8, it is obsolete, and was + * replaced by the command system API in X-Plane 9. You should not use this + * API; replace any of the calls below with XPLMCommand invocations based on + * persistent command strings. The documentation that follows is for historic + * reference only. + * + * The legacy user interaction APIs let you simulate commands the user can do + * with a joystick, keyboard etc. Note that it is generally safer for future + * compatibility to use one of these commands than to manipulate the + * underlying sim data. + * + */ + + +/* + * XPLMCommandKeyID + * + * These enums represent all the keystrokes available within X-Plane. They can + * be sent to X-Plane directly. For example, you can reverse thrust using + * these enumerations. + * + */ +enum { + xplm_key_pause=0, + xplm_key_revthrust, + xplm_key_jettison, + xplm_key_brakesreg, + xplm_key_brakesmax, + xplm_key_gear, + xplm_key_timedn, + xplm_key_timeup, + xplm_key_fadec, + xplm_key_otto_dis, + xplm_key_otto_atr, + xplm_key_otto_asi, + xplm_key_otto_hdg, + xplm_key_otto_gps, + xplm_key_otto_lev, + xplm_key_otto_hnav, + xplm_key_otto_alt, + xplm_key_otto_vvi, + xplm_key_otto_vnav, + xplm_key_otto_nav1, + xplm_key_otto_nav2, + xplm_key_targ_dn, + xplm_key_targ_up, + xplm_key_hdgdn, + xplm_key_hdgup, + xplm_key_barodn, + xplm_key_baroup, + xplm_key_obs1dn, + xplm_key_obs1up, + xplm_key_obs2dn, + xplm_key_obs2up, + xplm_key_com1_1, + xplm_key_com1_2, + xplm_key_com1_3, + xplm_key_com1_4, + xplm_key_nav1_1, + xplm_key_nav1_2, + xplm_key_nav1_3, + xplm_key_nav1_4, + xplm_key_com2_1, + xplm_key_com2_2, + xplm_key_com2_3, + xplm_key_com2_4, + xplm_key_nav2_1, + xplm_key_nav2_2, + xplm_key_nav2_3, + xplm_key_nav2_4, + xplm_key_adf_1, + xplm_key_adf_2, + xplm_key_adf_3, + xplm_key_adf_4, + xplm_key_adf_5, + xplm_key_adf_6, + xplm_key_transpon_1, + xplm_key_transpon_2, + xplm_key_transpon_3, + xplm_key_transpon_4, + xplm_key_transpon_5, + xplm_key_transpon_6, + xplm_key_transpon_7, + xplm_key_transpon_8, + xplm_key_flapsup, + xplm_key_flapsdn, + xplm_key_cheatoff, + xplm_key_cheaton, + xplm_key_sbrkoff, + xplm_key_sbrkon, + xplm_key_ailtrimL, + xplm_key_ailtrimR, + xplm_key_rudtrimL, + xplm_key_rudtrimR, + xplm_key_elvtrimD, + xplm_key_elvtrimU, + xplm_key_forward, + xplm_key_down, + xplm_key_left, + xplm_key_right, + xplm_key_back, + xplm_key_tower, + xplm_key_runway, + xplm_key_chase, + xplm_key_free1, + xplm_key_free2, + xplm_key_spot, + xplm_key_fullscrn1, + xplm_key_fullscrn2, + xplm_key_tanspan, + xplm_key_smoke, + xplm_key_map, + xplm_key_zoomin, + xplm_key_zoomout, + xplm_key_cycledump, + xplm_key_replay, + xplm_key_tranID, + xplm_key_max +}; +typedef int XPLMCommandKeyID; + +/* + * XPLMCommandButtonID + * + * These are enumerations for all of the things you can do with a joystick + * button in X-Plane. They currently match the buttons menu in the equipment + * setup dialog, but these enums will be stable even if they change in + * X-Plane. + * + */ +enum { + xplm_joy_nothing=0, + xplm_joy_start_all, + xplm_joy_start_0, + xplm_joy_start_1, + xplm_joy_start_2, + xplm_joy_start_3, + xplm_joy_start_4, + xplm_joy_start_5, + xplm_joy_start_6, + xplm_joy_start_7, + xplm_joy_throt_up, + xplm_joy_throt_dn, + xplm_joy_prop_up, + xplm_joy_prop_dn, + xplm_joy_mixt_up, + xplm_joy_mixt_dn, + xplm_joy_carb_tog, + xplm_joy_carb_on, + xplm_joy_carb_off, + xplm_joy_trev, + xplm_joy_trm_up, + xplm_joy_trm_dn, + xplm_joy_rot_trm_up, + xplm_joy_rot_trm_dn, + xplm_joy_rud_lft, + xplm_joy_rud_cntr, + xplm_joy_rud_rgt, + xplm_joy_ail_lft, + xplm_joy_ail_cntr, + xplm_joy_ail_rgt, + xplm_joy_B_rud_lft, + xplm_joy_B_rud_rgt, + xplm_joy_look_up, + xplm_joy_look_dn, + xplm_joy_look_lft, + xplm_joy_look_rgt, + xplm_joy_glance_l, + xplm_joy_glance_r, + xplm_joy_v_fnh, + xplm_joy_v_fwh, + xplm_joy_v_tra, + xplm_joy_v_twr, + xplm_joy_v_run, + xplm_joy_v_cha, + xplm_joy_v_fr1, + xplm_joy_v_fr2, + xplm_joy_v_spo, + xplm_joy_flapsup, + xplm_joy_flapsdn, + xplm_joy_vctswpfwd, + xplm_joy_vctswpaft, + xplm_joy_gear_tog, + xplm_joy_gear_up, + xplm_joy_gear_down, + xplm_joy_lft_brake, + xplm_joy_rgt_brake, + xplm_joy_brakesREG, + xplm_joy_brakesMAX, + xplm_joy_speedbrake, + xplm_joy_ott_dis, + xplm_joy_ott_atr, + xplm_joy_ott_asi, + xplm_joy_ott_hdg, + xplm_joy_ott_alt, + xplm_joy_ott_vvi, + xplm_joy_tim_start, + xplm_joy_tim_reset, + xplm_joy_ecam_up, + xplm_joy_ecam_dn, + xplm_joy_fadec, + xplm_joy_yaw_damp, + xplm_joy_art_stab, + xplm_joy_chute, + xplm_joy_JATO, + xplm_joy_arrest, + xplm_joy_jettison, + xplm_joy_fuel_dump, + xplm_joy_puffsmoke, + xplm_joy_prerotate, + xplm_joy_UL_prerot, + xplm_joy_UL_collec, + xplm_joy_TOGA, + xplm_joy_shutdown, + xplm_joy_con_atc, + xplm_joy_fail_now, + xplm_joy_pause, + xplm_joy_rock_up, + xplm_joy_rock_dn, + xplm_joy_rock_lft, + xplm_joy_rock_rgt, + xplm_joy_rock_for, + xplm_joy_rock_aft, + xplm_joy_idle_hilo, + xplm_joy_lanlights, + xplm_joy_max +}; +typedef int XPLMCommandButtonID; + +/* + * XPLMSimulateKeyPress + * + * This function simulates a key being pressed for X-Plane. The keystroke goes + * directly to X-Plane; it is never sent to any plug-ins. However, since this + * is a raw key stroke it may be mapped by the keys file or enter text into a + * field. + * + * Deprecated: use XPLMCommandOnce + * + */ +XPLM_API void XPLMSimulateKeyPress( + int inKeyType, + int inKey); + +/* + * XPLMCommandKeyStroke + * + * This routine simulates a command-key stroke. However, the keys are done by + * function, not by actual letter, so this function works even if the user has + * remapped their keyboard. Examples of things you might do with this include + * pausing the simulator. + * + * Deprecated: use XPLMCommandOnce + * + */ +XPLM_API void XPLMCommandKeyStroke( + XPLMCommandKeyID inKey); + +/* + * XPLMCommandButtonPress + * + * This function simulates any of the actions that might be taken by pressing + * a joystick button. However, this lets you call the command directly rather + * than have to know which button is mapped where. Important: you must release + * each button you press. The APIs are separate so that you can 'hold down' a + * button for a fixed amount of time. + * + * Deprecated: use XPLMCommandBegin. + * + */ +XPLM_API void XPLMCommandButtonPress( + XPLMCommandButtonID inButton); + +/* + * XPLMCommandButtonRelease + * + * This function simulates any of the actions that might be taken by pressing + * a joystick button. See XPLMCommandButtonPress. + * + * Deprecated: use XPLMCommandEnd. + * + */ +XPLM_API void XPLMCommandButtonRelease( + XPLMCommandButtonID inButton); + +#endif /* XPLM_DEPRECATED */ #ifdef __cplusplus } #endif diff --git a/XPSDK/Delphi/Widgets/XPStandardWidgets.pas b/XPSDK/Delphi/Widgets/XPStandardWidgets.pas index bde7c77..d77f383 100644 --- a/XPSDK/Delphi/Widgets/XPStandardWidgets.pas +++ b/XPSDK/Delphi/Widgets/XPStandardWidgets.pas @@ -1,79 +1,71 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPStandardWidgets; INTERFACE { - XPStandardWidgets - THEORY OF OPERATION + ## THEORY OF OPERATION - The standard widgets are widgets built into the widgets library. While you - can gain access to the widget function that drives them, you generally use - them by calling XPCreateWidget and then listening for special messages, - etc. + The standard widgets are widgets built into the widgets library. While you + can gain access to the widget function that drives them, you generally use + them by calling XPCreateWidget and then listening for special messages, + etc. - The standard widgets often send mesages to themselves when the user - performs an event; these messages are sent up the widget hierarchy until - they are handled. So you can add a widget proc directly to a push button - (for example) to intercept the message when it is clicked, or you can put - one widget proc on a window for all of the push buttons in the window. - Most of these messages contain the original widget ID as a parameter so you - can know which widget is messaging no matter who it is sent to. + The standard widgets often send mesages to themselves when the user + performs an event; these messages are sent up the widget hierarchy until + they are handled. So you can add a widget proc directly to a push button + (for example) to intercept the message when it is clicked, or you can put + one widget proc on a window for all of the push buttons in the window. Most + of these messages contain the original widget ID as a parameter so you can + know which widget is messaging no matter who it is sent to. } -USES XPWidgetDefs; +USES + XPWidgetDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * MAIN WINDOW ___________________________________________________________________________} { - The main window widget class provides a "window" as the user knows it. - These windows are dragable and can be selected. Use them to create - floating windows and non-modal dialogs. + The main window widget class provides a "window" as the user knows it. + These windows are dragable and can be selected. Use them to create floating + windows and non-modal dialogs. } - CONST xpWidgetClass_MainWindow = 1; { Main Window Type Values - These type values are used to control the appearance of a main window. + These type values are used to control the appearance of a main window. } - { The standard main window; pin stripes on XP7, metal frame on XP 6. } + { The standard main window; pin stripes on XP7, metal frame on XP 6. } xpMainWindowStyle_MainWindow = 0 ; - { A translucent dark gray window, like the one ATC messages appear in. } + { A translucent dark gray window, like the one ATC messages appear in. } xpMainWindowStyle_Translucent = 1 ; { - Main Window Properties - + Main Window Properties } - { This property specifies the type of window. Set to one of the main window } - { types above. } + { This property specifies the type of window. Set to one of the main window } + { types above. } xpProperty_MainWindowType = 1100 ; - { This property specifies whether the main window has close boxes in its } - { corners. } + { This property specifies whether the main window has close boxes in its } + { corners. } xpProperty_MainWindowHasCloseBoxes = 1200 ; { - MainWindow Messages - + MainWindow Messages } - { This message is sent when the close buttons are pressed for your window. } + { This message is sent when the close buttons are pressed for your window. } xpMessage_CloseButtonPushed = 1200 ; @@ -81,37 +73,35 @@ CONST * SUB WINDOW ___________________________________________________________________________} { - X-plane dialogs are divided into separate areas; the sub window widgets - allow you to make these areas. Create one main window and place several - subwindows inside it. Then place your controls inside the subwindows. + X-Plane dialogs are divided into separate areas; the sub window widgets + allow you to make these areas. Create one main window and place several + subwindows inside it. Then place your controls inside the subwindows. } - CONST xpWidgetClass_SubWindow = 2; { SubWindow Type Values - These values control the appearance of the subwindow. + These values control the appearance of the subwindow. } - { A panel that sits inside a main window. } + { A panel that sits inside a main window. } xpSubWindowStyle_SubWindow = 0 ; - { A screen that sits inside a panel for showing text information. } + { A screen that sits inside a panel for showing text information. } xpSubWindowStyle_Screen = 2 ; - { A list view for scrolling lists. } + { A list view for scrolling lists. } xpSubWindowStyle_ListView = 3 ; { - SubWindow Properties - + SubWindow Properties } - { This property specifies the type of window. Set to one of the subwindow } - { types above. } + { This property specifies the type of window. Set to one of the subwindow } + { types above. } xpProperty_SubWindowType = 1200 ; @@ -119,110 +109,108 @@ CONST * BUTTON ___________________________________________________________________________} { - The button class provides a number of different button styles and - behaviors, including push buttons, radio buttons, check boxes, etc. The - button label appears on or next to the button depending on the button's - appearance, or type. + The button class provides a number of different button styles and + behaviors, including push buttons, radio buttons, check boxes, etc. The + button label appears on or next to the button depending on the button's + appearance, or type. - The button's behavior is a separate property that dictates who it hilights - and what kinds of messages it sends. Since behavior and type are - different, you can do strange things like make check boxes that act as push - buttons or push buttons with radio button behavior. + The button's behavior is a separate property that dictates who it hilights + and what kinds of messages it sends. Since behavior and type are different, + you can do strange things like make check boxes that act as push buttons or + push buttons with radio button behavior. - In X-Plane 6 there were no check box graphics. The result is the following - behavior: in x-plane 6 all check box and radio buttons are round - (radio-button style) buttons; in X-Plane 7 they are all square (check-box - style) buttons. In a future version of x-plane, the xpButtonBehavior enums - will provide the correct graphic (check box or radio button) giving the - expected result. + In X-Plane 6 there were no check box graphics. The result is the following + behavior: in X-Plane + 6 all check box and radio buttons are round (radio-button style) buttons; + in X-Plane 7 they are all square (check-box style) buttons. In a future + version of X-Plane, the xpButtonBehavior enums will provide the correct + graphic (check box or radio button) giving the expected result. } - CONST xpWidgetClass_Button = 3; { Button Types - These define the visual appearance of buttons but not how they respond to - the mouse. + These define the visual appearance of buttons but not how they respond to + the mouse. } - { This is a standard push button, like an "OK" or "Cancel" button in a dialog } - { box. } + { This is a standard push button, like an 'OK' or 'Cancel' button in a dialog} + { box. } xpPushButton = 0 ; - { A check box or radio button. Use this and the button behaviors below to } - { get the desired behavior. } + { A check box or radio button. Use this and the button behaviors below to } + { get the desired behavior. } xpRadioButton = 1 ; - { A window close box. } + { A window close box. } xpWindowCloseBox = 3 ; - { A small down arrow. } + { A small down arrow. } xpLittleDownArrow = 5 ; - { A small up arrow. } + { A small up arrow. } xpLittleUpArrow = 6 ; { Button Behavior Values - These define how the button responds to mouse clicks. + These define how the button responds to mouse clicks. } - { Standard push button behavior. The button hilites while the mouse is } - { clicked over it and unhilites when the mouse is moved outside of it or } - { released. If the mouse is released over the button, the } - { xpMsg_PushButtonPressed message is sent. } + { Standard push button behavior. The button hilites while the mouse is } + { clicked over it and unhilites when the mouse is moved outside of it or } + { released. If the mouse is released over the button, the } + { xpMsg_PushButtonPressed message is sent. } xpButtonBehaviorPushButton = 0 ; - { Check box behavior. The button immediately toggles its value when the } - { mouse is clicked and sends out a xpMsg_ButtonStateChanged message. } + { Check box behavior. The button immediately toggles its value when the mouse} + { is clicked and sends out a xpMsg_ButtonStateChanged message. } xpButtonBehaviorCheckBox = 1 ; - { Radio button behavior. The button immediately sets its state to one and } - { sends out a xpMsg_ButtonStateChanged message if it was not already set to } - { one. You must turn off other radio buttons in a group in your code. } + { Radio button behavior. The button immediately sets its state to one and } + { sends out a xpMsg_ButtonStateChanged message if it was not already set to } + { one. You must turn off other radio buttons in a group in your code. } xpButtonBehaviorRadioButton = 2 ; { - Button Properties - + Button Properties } - { This property sets the visual type of button. Use one of the button types } - { above. } + { This property sets the visual type of button. Use one of the button types } + { above. } xpProperty_ButtonType = 1300 ; - { This property sets the button's behavior. Use one of the button behaviors } - { above. } + { This property sets the button's behavior. Use one of the button behaviors } + { above. } xpProperty_ButtonBehavior = 1301 ; - { This property tells whether a check box or radio button is "checked" or } - { not. Not used for push buttons. } + { This property tells whether a check box or radio button is "checked" or } + { not. Not used for push buttons. } xpProperty_ButtonState = 1302 ; { Button Messages - These messages are sent by the button to itself and then up the widget - chain when the button is clicked. (You may intercept them by providing a - widget handler for the button itself or by providing a handler in a parent - widget.) + These messages are sent by the button to itself and then up the widget + chain when the button is clicked. (You may intercept them by providing a + widget handler for the button itself or by providing a handler in a parent + widget.) } - { This message is sent when the user completes a click and release in a } - { button with push button behavior. Parameter one of the message is the } - { widget ID of the button. This message is dispatched up the widget } - { hierarchy. } + { This message is sent when the user completes a click and release in a } + { button with push button behavior. Parameter one of the message is the } + { widget ID of the button. This message is dispatched up the widget } + { hierarchy. } xpMsg_PushButtonPressed = 1300 ; - { This message is sent when a button is clicked that has radio button or } - { check box behavior and its value changes. (Note that if the value changes } - { by setting a property you do not receive this message!) Parameter one is } - { the widget ID of the button, parameter 2 is the new state value, either } - { zero or one. This message is dispatched up the widget hierarchy. } + { This message is sent when a button is clicked that has radio button or } + { check box behavior and its value changes. (Note that if the value changes } + { by setting a property you do not receive this message!) Parameter one is } + { the widget ID of the button, parameter 2 is the new state value, either } + { zero or one. This message is dispatched up the widget hierarchy. } xpMsg_ButtonStateChanged = 1301 ; @@ -230,91 +218,86 @@ CONST * TEXT FIELD ___________________________________________________________________________} { - The text field widget provides an editable text field including mouse - selection and keyboard navigation. The contents of the text field are its - descriptor. (The descriptor changes as the user types.) + The text field widget provides an editable text field including mouse + selection and keyboard navigation. The contents of the text field are its + descriptor. (The descriptor changes as the user types.) - The text field can have a number of types, that effect the visual layout of - the text field. The text field sends messages to itself so you may control - its behavior. + The text field can have a number of types, that effect the visual layout of + the text field. The text field sends messages to itself so you may control + its behavior. - If you need to filter keystrokes, add a new handler and intercept the key - press message. Since key presses are passed by pointer, you can modify the - keystroke and pass it through to the text field widget. + If you need to filter keystrokes, add a new handler and intercept the key + press message. Since key presses are passed by pointer, you can modify the + keystroke and pass it through to the text field widget. - WARNING: in x-plane before 7.10 (including 6.70) null characters could - crash x-plane. To prevent this, wrap this object with a filter function - (more instructions can be found on the SDK website). + WARNING: in X-Plane before 7.10 (including 6.70) null characters could + crash X-Plane. To prevent this, wrap this object with a filter function + (more instructions can be found on the SDK website). } - CONST xpWidgetClass_TextField = 4; { Text Field Type Values - These control the look of the text field. + These control the look of the text field. } - { A field for text entry. } + { A field for text entry. } xpTextEntryField = 0 ; - { A transparent text field. The user can type and the text is drawn, but no } - { background is drawn. You can draw your own background by adding a widget } - { handler and prehandling the draw message. } + { A transparent text field. The user can type and the text is drawn, but no } + { background is drawn. You can draw your own background by adding a widget } + { handler and prehandling the draw message. } xpTextTransparent = 3 ; - { A translucent edit field, dark gray. } + { A translucent edit field, dark gray. } xpTextTranslucent = 4 ; { - Text Field Properties - + Text Field Properties } - { This is the character position the selection starts at, zero based. If it } - { is the same as the end insertion point, the insertion point is not a } - { selection. } + { This is the character position the selection starts at, zero based. If it } + { is the same as the end insertion point, the insertion point is not a } + { selection. } xpProperty_EditFieldSelStart = 1400 ; - { This is the character position of the end of the selection. } + { This is the character position of the end of the selection. } xpProperty_EditFieldSelEnd = 1401 ; - { This is the character position a drag was started at if the user is } - { dragging to select text, or -1 if a drag is not in progress. } + { This is the character position a drag was started at if the user is } + { dragging to select text, or -1 if a drag is not in progress. } xpProperty_EditFieldSelDragStart = 1402 ; - { This is the type of text field to display, from the above list. } + { This is the type of text field to display, from the above list. } xpProperty_TextFieldType = 1403 ; - { Set this property to 1 to password protect the field. Characters will be } - { drawn as *s even though the descriptor will contain plain-text. } + { Set this property to 1 to password protect the field. Characters will be } + { drawn as *s even though the descriptor will contain plain-text. } xpProperty_PasswordMode = 1404 ; - { The max number of characters you can enter, if limited. Zero means } - { unlimited. } + { The max number of characters you can enter, if limited. Zero means } + { unlimited. } xpProperty_MaxCharacters = 1405 ; - { The first visible character on the left. This effectively scrolls the text } - { field. } + { The first visible character on the left. This effectively scrolls the text} + { field. } xpProperty_ScrollPosition = 1406 ; - { The font to draw the field's text with. (An XPLMFontID.) } + { The font to draw the field's text with. (An XPLMFontID.) } xpProperty_Font = 1407 ; - { This is the active side of the insert selection. (Internal) } + { This is the active side of the insert selection. (Internal) } xpProperty_ActiveEditSide = 1408 ; { - Text Field Messages - + Text Field Messages } - { Text Field Messages } - { } - { The text field sends this message to itself when its text changes. It } - { sends the message up the call chain; param1 is the text field's widget ID. } + { The text field sends this message to itself when its text changes. It sends} + { the message up the call chain; param1 is the text field's widget ID. } xpMsg_TextFieldChanged = 1400 ; @@ -322,60 +305,55 @@ CONST * SCROLL BAR ___________________________________________________________________________} { - A standard scroll bar or slider control. The scroll bar has a minimum, - maximum and current value that is updated when the user drags it. The - scroll bar sends continuous messages as it is dragged. + A standard scroll bar or slider control. The scroll bar has a minimum, + maximum and current value that is updated when the user drags it. The + scroll bar sends continuous messages as it is dragged. } - CONST xpWidgetClass_ScrollBar = 5; { Scroll Bar Type Values - This defines how the scroll bar looks. + This defines how the scroll bar looks. } - { Scroll bar types. } - { } - { A standard x-plane scroll bar (with arrows on the ends). } + { A standard X-Plane scroll bar (with arrows on the ends). } xpScrollBarTypeScrollBar = 0 ; - { A slider, no arrows. } + { A slider, no arrows. } xpScrollBarTypeSlider = 1 ; { - Scroll Bar Properties - + Scroll Bar Properties } - { The current position of the thumb (in between the min and max, inclusive) } + { The current position of the thumb (in between the min and max, inclusive) } xpProperty_ScrollBarSliderPosition = 1500 ; - { The value the scroll bar has when the thumb is in the lowest position. } + { The value the scroll bar has when the thumb is in the lowest position. } xpProperty_ScrollBarMin = 1501 ; - { The value the scroll bar has when the thumb is in the highest position. } + { The value the scroll bar has when the thumb is in the highest position. } xpProperty_ScrollBarMax = 1502 ; - { How many units to moev the scroll bar when clicking next to the thumb. The } - { scroll bar always moves one unit when the arrows are clicked. } + { How many units to move the scroll bar when clicking next to the thumb. The } + { scroll bar always moves one unit when the arrows are clicked. } xpProperty_ScrollBarPageAmount = 1503 ; - { The type of scrollbar from the enums above. } + { The type of scrollbar from the enums above. } xpProperty_ScrollBarType = 1504 ; - { Used internally. } + { Used internally. } xpProperty_ScrollBarSlop = 1505 ; { - Scroll Bar Messages - + Scroll Bar Messages } - { The Scroll Bar sends this message when the slider position changes. It } - { sends the message up the call chain; param1 is the Scroll Bar widget ID. } + { The scroll bar sends this message when the slider position changes. It } + { sends the message up the call chain; param1 is the Scroll Bar widget ID. } xpMsg_ScrollBarSliderPositionChanged = 1500 ; @@ -383,22 +361,20 @@ CONST * CAPTION ___________________________________________________________________________} { - A caption is a simple widget that shows its descriptor as a string, useful - for labeling parts of a window. It always shows its descriptor as its - string and is otherwise transparent. + A caption is a simple widget that shows its descriptor as a string, useful + for labeling parts of a window. It always shows its descriptor as its + string and is otherwise transparent. } - CONST xpWidgetClass_Caption = 6; { - Caption Properties - + Caption Properties } - { This property specifies whether the caption is lit; use lit captions } - { against screens. } + { This property specifies whether the caption is lit; use lit captions } + { against screens. } xpProperty_CaptionLit = 1600 ; @@ -406,19 +382,18 @@ CONST * GENERAL GRAPHICS ___________________________________________________________________________} { - The general graphics widget can show one of many icons available from - x-plane. + The general graphics widget can show one of many icons available from + X-Plane. } - CONST xpWidgetClass_GeneralGraphics = 7; { General Graphics Types Values - These define the icon for the general graphics. + These define the icon for the general graphics. } xpShip = 4 ; @@ -460,10 +435,9 @@ CONST ; { - General Graphics Properties - + General Graphics Properties } - { This property controls the type of icon that is drawn. } + { This property controls the type of icon that is drawn. } xpProperty_GeneralGraphicsType = 1700 ; @@ -471,27 +445,26 @@ CONST * PROGRESS INDICATOR ___________________________________________________________________________} { - This widget implements a progress indicator as seen when x-plane starts up. + This widget implements a progress indicator as seen when X-Plane starts up. } - - CONST xpWidgetClass_Progress = 8; { - Progress Indicator Properties - + Progress Indicator Properties } - { This is the current value of the progress indicator. } + { This is the current value of the progress indicator. } xpProperty_ProgressPosition = 1800 ; - { This is the minimum value, equivalent to 0% filled. } + { This is the minimum value, equivalent to 0% filled. } xpProperty_ProgressMin = 1801 ; - { This is the maximum value, equivalent to 100% filled. } + { This is the maximum value, equivalent to 100% filled. } xpProperty_ProgressMax = 1802 ; + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/Widgets/XPUIGraphics.pas b/XPSDK/Delphi/Widgets/XPUIGraphics.pas index f06806a..65e0636 100644 --- a/XPSDK/Delphi/Widgets/XPUIGraphics.pas +++ b/XPSDK/Delphi/Widgets/XPUIGraphics.pas @@ -1,66 +1,53 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPUIGraphics; INTERFACE -{ - -} -USES XPWidgetDefs; +USES + XPWidgetDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * UI GRAPHICS ___________________________________________________________________________} -{ - -} - { XPWindowStyle - There are a few built-in window styles in X-Plane that you can use. + There are a few built-in window styles in X-Plane that you can use. - Note that X-Plane 6 does not offer real shadow-compositing; you must make - sure to put a window on top of another window of the right style to the - shadows work, etc. This applies to elements with insets and shadows. The - rules are: + Note that X-Plane 6 does not offer real shadow-compositing; you must make + sure to put a window on top of another window of the right style to the + shadows work, etc. This applies to elements with insets and shadows. The + rules are: - Sub windows must go on top of main windows, and screens and list views on - top of subwindows. Only help and main windows can be over the main screen. + Sub windows must go on top of main windows, and screens and list views on + top of subwindows. Only help and main windows can be over the main screen. + With X-Plane 7 any window or element may be placed over any other element. - With X-Plane 7 any window or element may be placed over any other element. - - Some windows are scaled by stretching, some by repeating. The drawing - routines know which scaling method to use. The list view cannot be - rescaled in x-plane 6 because it has both a repeating pattern and a - gradient in one element. All other elements can be rescaled. + Some windows are scaled by stretching, some by repeating. The drawing + routines know which scaling method to use. The list view cannot be rescaled + in X-Plane 6 because it has both a repeating pattern and a gradient in one + element. All other elements can be rescaled. } TYPE XPWindowStyle = ( - { An LCD screen that shows help. } + { An LCD screen that shows help. } xpWindow_Help = 0 - { A dialog box window. } + { A dialog box window. } ,xpWindow_MainWindow = 1 - { A panel or frame within a dialog box window. } + { A panel or frame within a dialog box window. } ,xpWindow_SubWindow = 2 - { An LCD screen within a panel to hold text displays. } + { An LCD screen within a panel to hold text displays. } ,xpWindow_Screen = 4 - { A list view within a panel for scrolling file names, etc. } + { A list view within a panel for scrolling file names, etc. } ,xpWindow_ListView = 5 ); @@ -69,160 +56,152 @@ TYPE { XPDrawWindow - This routine draws a window of the given dimensions at the given offset on - the virtual screen in a given style. The window is automatically scaled as - appropriate using a bitmap scaling technique (scaling or repeating) as - appropriate to the style. + This routine draws a window of the given dimensions at the given offset on + the virtual screen in a given style. The window is automatically scaled as + appropriate using a bitmap scaling technique (scaling or repeating) as + appropriate to the style. } PROCEDURE XPDrawWindow( - inX1 : integer; - inY1 : integer; - inX2 : integer; - inY2 : integer; + inX1 : Integer; + inY1 : Integer; + inX2 : Integer; + inY2 : Integer; inStyle : XPWindowStyle); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPGetWindowDefaultDimensions - This routine returns the default dimensions for a window. Output is either - a minimum or fixed value depending on whether the window is scalable. + This routine returns the default dimensions for a window. Output is either + a minimum or fixed value depending on whether the window is scalable. } PROCEDURE XPGetWindowDefaultDimensions( inStyle : XPWindowStyle; - outWidth : Pinteger; { Can be nil } - outHeight : Pinteger); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outWidth : PInteger; { Can be nil } + outHeight : PInteger); { Can be nil } + cdecl; external XPWIDGETS.DLL; { XPElementStyle - Elements are individually drawable UI things like push buttons, etc. The - style defines what kind of element you are drawing. Elements can be - stretched in one or two dimensions (depending on the element). Some - elements can be lit. + Elements are individually drawable UI things like push buttons, etc. The + style defines what kind of element you are drawing. Elements can be + stretched in one or two dimensions (depending on the element). Some + elements can be lit. - In x-plane 6 some elements must be drawn over metal. Some are scalable and - some are not. Any element can be drawn anywhere in x-plane 7. + In X-Plane 6 some elements must be drawn over metal. Some are scalable and + some are not. Any element can be drawn anywhere in X-Plane 7. - Scalable Axis Required Background + Scalable Axis Required Background } TYPE XPElementStyle = ( - { x metal } + { x metal } xpElement_TextField = 6 - { none metal } + { none metal } ,xpElement_CheckBox = 9 - { none metal } + { none metal } ,xpElement_CheckBoxLit = 10 - { none window header } + { none window header } ,xpElement_WindowCloseBox = 14 - { none window header } + { none window header } ,xpElement_WindowCloseBoxPressed = 15 - { x metal } + { x metal } ,xpElement_PushButton = 16 - { x metal } + { x metal } ,xpElement_PushButtonLit = 17 - { none any } + { none any } ,xpElement_OilPlatform = 24 - { none any } + { none any } ,xpElement_OilPlatformSmall = 25 - { none any } + { none any } ,xpElement_Ship = 26 - { none any } + { none any } ,xpElement_ILSGlideScope = 27 - { none any } + { none any } ,xpElement_MarkerLeft = 28 - { none any } + { none any } ,xpElement_Airport = 29 - { none any } + { none any } ,xpElement_Waypoint = 30 - { none any } + { none any } ,xpElement_NDB = 31 - { none any } + { none any } ,xpElement_VOR = 32 - { none any } + { none any } ,xpElement_RadioTower = 33 - { none any } + { none any } ,xpElement_AircraftCarrier = 34 - { none any } + { none any } ,xpElement_Fire = 35 - { none any } + { none any } ,xpElement_MarkerRight = 36 - { none any } + { none any } ,xpElement_CustomObject = 37 - { none any } + { none any } ,xpElement_CoolingTower = 38 - { none any } + { none any } ,xpElement_SmokeStack = 39 - { none any } + { none any } ,xpElement_Building = 40 - { none any } + { none any } ,xpElement_PowerLine = 41 - { none metal } + { none metal } ,xpElement_CopyButtons = 45 - { none metal } + { none metal } ,xpElement_CopyButtonsWithEditingGrid = 46 - { x, y metal } + { x, y metal } ,xpElement_EditingGrid = 47 - { THIS CAN PROBABLY BE REMOVED } + { THIS CAN PROBABLY BE REMOVED } ,xpElement_ScrollBar = 48 - { none any } + { none any } ,xpElement_VORWithCompassRose = 49 - { none metal } + { none metal } ,xpElement_Zoomer = 51 - { x, y metal } + { x, y metal } ,xpElement_TextFieldMiddle = 52 - { none metal } + { none metal } ,xpElement_LittleDownArrow = 53 - { none metal } + { none metal } ,xpElement_LittleUpArrow = 54 - { none metal } + { none metal } ,xpElement_WindowDragBar = 61 - { none metal } + { none metal } ,xpElement_WindowDragBarSmooth = 62 ); @@ -231,67 +210,60 @@ TYPE { XPDrawElement - XPDrawElement draws a given element at an offset on the virtual screen in - set dimensions. EVEN if the element is not scalable, it will be scaled if - the width and height do not match the preferred dimensions; it'll just look - ugly. Pass inLit to see the lit version of the element; if the element - cannot be lit this is ignored. + XPDrawElement draws a given element at an offset on the virtual screen in + set dimensions. + *Even* if the element is not scalable, it will be scaled if the width and + height do not match the preferred dimensions; it'll just look ugly. Pass + inLit to see the lit version of the element; if the element cannot be lit + this is ignored. } PROCEDURE XPDrawElement( - inX1 : integer; - inY1 : integer; - inX2 : integer; - inY2 : integer; + inX1 : Integer; + inY1 : Integer; + inX2 : Integer; + inY2 : Integer; inStyle : XPElementStyle; - inLit : integer); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inLit : Integer); + cdecl; external XPWIDGETS.DLL; { XPGetElementDefaultDimensions - This routine returns the recommended or minimum dimensions of a given UI - element. outCanBeLit tells whether the element has both a lit and unlit - state. Pass NULL to not receive any of these parameters. + This routine returns the recommended or minimum dimensions of a given UI + element. outCanBeLit tells whether the element has both a lit and unlit + state. Pass `NULL` to not receive any of these parameters. } PROCEDURE XPGetElementDefaultDimensions( inStyle : XPElementStyle; - outWidth : Pinteger; { Can be nil } - outHeight : Pinteger; { Can be nil } - outCanBeLit : Pinteger); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outWidth : PInteger; { Can be nil } + outHeight : PInteger; { Can be nil } + outCanBeLit : PInteger); { Can be nil } + cdecl; external XPWIDGETS.DLL; { XPTrackStyle - A track is a UI element that displays a value vertically or horizontally. - X-Plane has three kinds of tracks: scroll bars, sliders, and progress bars. - Tracks can be displayed either horizontally or vertically; tracks will - choose their own layout based on the larger dimension of their dimensions - (e.g. they know if they are tall or wide). Sliders may be lit or unlit - (showing the user manipulating them). + A track is a UI element that displays a value vertically or horizontally. + X-Plane has three kinds of tracks: scroll bars, sliders, and progress bars. + Tracks can be displayed either horizontally or vertically; tracks will + choose their own layout based on the larger dimension of their dimensions + (e.g. they know if they are tall or wide). Sliders may be lit or unlit + (showing the user manipulating them). - ScrollBar - this is a standard scroll bar with arrows and a thumb to drag. - Slider - this is a simple track with a ball in the middle that can be - slid. Progress - this is a progress indicator showing how a long task is - going. + - ScrollBar: this is a standard scroll bar with arrows and a thumb to drag. + - Slider: this is a simple track with a ball in the middle that can be + slid. + - Progress: this is a progress indicator showing how a long task is going. } TYPE XPTrackStyle = ( - { not over metal can be lit can be rotated } + { not over metal can be lit can be rotated } xpTrack_ScrollBar = 0 - { over metal can be lit can be rotated } + { over metal can be lit can be rotated } ,xpTrack_Slider = 1 - { over metal cannot be lit cannot be rotated } + { over metal cannot be lit cannot be rotated } ,xpTrack_Progress = 2 ); @@ -300,81 +272,71 @@ TYPE { XPDrawTrack - This routine draws a track. You pass in the track dimensions and size; the - track picks the optimal orientation for these dimensions. Pass in the - track's minimum current and maximum values; the indicator will be - positioned appropriately. You can also specify whether the track is lit or - not. + This routine draws a track. You pass in the track dimensions and size; the + track picks the optimal orientation for these dimensions. Pass in the + track's minimum current and maximum values; the indicator will be + positioned appropriately. You can also specify whether the track is lit or + not. } PROCEDURE XPDrawTrack( - inX1 : integer; - inY1 : integer; - inX2 : integer; - inY2 : integer; - inMin : integer; - inMax : integer; - inValue : integer; + inX1 : Integer; + inY1 : Integer; + inX2 : Integer; + inY2 : Integer; + inMin : Integer; + inMax : Integer; + inValue : Integer; inTrackStyle : XPTrackStyle; - inLit : integer); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inLit : Integer); + cdecl; external XPWIDGETS.DLL; { XPGetTrackDefaultDimensions - This routine returns a track's default smaller dimension; all tracks are - scalable in the larger dimension. It also returns whether a track can be - lit. + This routine returns a track's default smaller dimension; all tracks are + scalable in the larger dimension. It also returns whether a track can be + lit. } PROCEDURE XPGetTrackDefaultDimensions( inStyle : XPTrackStyle; - outWidth : Pinteger; - outCanBeLit : Pinteger); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outWidth : PInteger; + outCanBeLit : PInteger); + cdecl; external XPWIDGETS.DLL; { XPGetTrackMetrics - This routine returns the metrics of a track. If you want to write UI code - to manipulate a track, this routine helps you know where the mouse - locations are. For most other elements, the rectangle the element is drawn - in is enough information. However, the scrollbar drawing routine does some - automatic placement; this routine lets you know where things ended up. You - pass almost everything you would pass to the draw routine. You get out the - orientation, and other useful stuff. + This routine returns the metrics of a track. If you want to write UI code + to manipulate a track, this routine helps you know where the mouse + locations are. For most other elements, the rectangle the element is drawn + in is enough information. However, the scrollbar drawing routine does some + automatic placement; this routine lets you know where things ended up. You + pass almost everything you would pass to the draw routine. You get out the + orientation, and other useful stuff. - Besides orientation, you get five dimensions for the five parts of a - scrollbar, which are the down button, down area (area before the thumb), - the thumb, and the up area and button. For horizontal scrollers, the left - button decreases; for vertical scrollers, the top button decreases. + Besides orientation, you get five dimensions for the five parts of a + scrollbar, which are the down button, down area (area before the thumb), + the thumb, and the up area and button. For horizontal scrollers, the left + button decreases; for vertical scrollers, the top button decreases. } PROCEDURE XPGetTrackMetrics( - inX1 : integer; - inY1 : integer; - inX2 : integer; - inY2 : integer; - inMin : integer; - inMax : integer; - inValue : integer; + inX1 : Integer; + inY1 : Integer; + inX2 : Integer; + inY2 : Integer; + inMin : Integer; + inMax : Integer; + inValue : Integer; inTrackStyle : XPTrackStyle; - outIsVertical : Pinteger; - outDownBtnSize : Pinteger; - outDownPageSize : Pinteger; - outThumbSize : Pinteger; - outUpPageSize : Pinteger; - outUpBtnSize : Pinteger); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outIsVertical : PInteger; + outDownBtnSize : PInteger; + outDownPageSize : PInteger; + outThumbSize : PInteger; + outUpPageSize : PInteger; + outUpBtnSize : PInteger); + cdecl; external XPWIDGETS.DLL; + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/Widgets/XPWidgetDefs.pas b/XPSDK/Delphi/Widgets/XPWidgetDefs.pas index 2e55830..1cc342f 100644 --- a/XPSDK/Delphi/Widgets/XPWidgetDefs.pas +++ b/XPSDK/Delphi/Widgets/XPWidgetDefs.pas @@ -1,43 +1,34 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPWidgetDefs; INTERFACE -{ - -} -USES XPLMDefs; +USES + XPLMDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * WIDGET DEFINITIONS ___________________________________________________________________________} { - A widget is a call-back driven screen entity like a push-button, window, - text entry field, etc. + A widget is a call-back driven screen entity like a push-button, window, + text entry field, etc. - Use the widget API to create widgets of various classes. You can nest them - into trees of widgets to create complex user interfaces. + Use the widget API to create widgets of various classes. You can nest them + into trees of widgets to create complex user interfaces. } - TYPE { XPWidgetID - A Widget ID is an opaque unique non-zero handle identifying your widget. - Use 0 to specify "no widget". This type is defined as wide enough to hold - a pointer. You receive a widget ID when you create a new widget and then - use that widget ID to further refer to the widget. + A Widget ID is an opaque unique non-zero handle identifying your widget. + Use 0 to specify "no widget". This type is defined as wide enough to hold a + pointer. You receive a widget ID when you create a new widget and then use + that widget ID to further refer to the widget. } XPWidgetID = pointer; PXPWidgetID = ^XPWidgetID; @@ -45,46 +36,48 @@ TYPE { XPWidgetPropertyID - Properties are values attached to instances of your widgets. A property is - identified by a 32-bit ID and its value is the width of a pointer. + Properties are values attached to instances of your widgets. A property is + identified by a 32-bit ID and its value is the width of a pointer. - Each widget instance may have a property or not have it. When you set a - property on a widget for the first time, the property is added to the - widget; it then stays there for the life of the widget. + Each widget instance may have a property or not have it. When you set a + property on a widget for the first time, the property is added to the + widget; it then stays there for the life of the widget. - Some property IDs are predefined by the widget package; you can make up - your own property IDs as well. + Some property IDs are predefined by the widget package; you can make up + your own property IDs as well. } XPWidgetPropertyID = ( - { A window's refcon is an opaque value used by client code to find other data } - { based on it. } + { A window's refcon is an opaque value used by client code to find other data} + { based on it. } xpProperty_Refcon = 0 - { These properties are used by the utlities to implement dragging. } + { These properties are used by the utlities to implement dragging. } ,xpProperty_Dragging = 1 ,xpProperty_DragXOff = 2 ,xpProperty_DragYOff = 3 - { Is the widget hilited? (For widgets that support this kind of thing.) } + { Is the widget hilited? (For widgets that support this kind of thing.) } ,xpProperty_Hilited = 4 - { Is there a C++ object attached to this widget? } + { Is there a C++ object attached to this widget? } ,xpProperty_Object = 5 - { If this property is 1, the widget package will use OpenGL to restrict } - { drawing to the Wiget's exposed rectangle. } + { If this property is 1, the widget package will use OpenGL to restrict } + { drawing to the Wiget's exposed rectangle. } ,xpProperty_Clip = 6 - { Is this widget enabled (for those that have a disabled state too)? } + { Is this widget enabled (for those that have a disabled state too)? } ,xpProperty_Enabled = 7 - { NOTE: Property IDs 1 - 999 are reserved for the widget's library. } - { } - { NOTE: Property IDs 1000 - 9999 are allocated to the standard widget classes } - { provided with the library Properties 1000 - 1099 are for widget class 0, } - { 1100 - 1199 for widget class 1, etc. } + { NOTE: Property IDs 1 - 999 are reserved for the widgets library. } + { } + { NOTE: Property IDs 1000 - 9999 are allocated to the standard widget classes} + { provided with the library. } + { } + { Properties 1000 - 1099 are for widget class 0, 1100 - 1199 for widget class} + { 1, etc. } ,xpProperty_UserStart = 10000 ); @@ -93,78 +86,78 @@ TYPE { XPMouseState_t - When the mouse is clicked or dragged, a pointer to this structure is passed - to your widget function. + When the mouse is clicked or dragged, a pointer to this structure is passed + to your widget function. } XPMouseState_t = RECORD - x : integer; - y : integer; - { Mouse Button number, left = 0 (right button not yet supported. } - button : integer; + x : Integer; + y : Integer; + { Mouse Button number, left = 0 (right button not yet supported. } + button : Integer; {$IFDEF XPLM200} - { Scroll wheel delta (button in this case would be the wheel axis number). } - delta : integer; -{$ENDIF} + { Scroll wheel delta (button in this case would be the wheel axis number). } + delta : Integer; +{$ENDIF XPLM200} END; PXPMouseState_t = ^XPMouseState_t; { XPKeyState_t - When a key is pressed, a pointer to this struct is passed to your widget - function. + When a key is pressed, a pointer to this struct is passed to your widget + function. } XPKeyState_t = RECORD - { The ASCII key that was pressed. WARNING: this may be 0 for some non-ASCII } - { key sequences. } - key : char; - { The flags. Make sure to check this if you only want key-downs! } + { The ASCII key that was pressed. WARNING: this may be 0 for some non-ASCII } + { key sequences. } + key : XPLMChar; + { The flags. Make sure to check this if you only want key-downs! } flags : XPLMKeyFlags; - { The virtual key code for the key } - vkey : char; + { The virtual key code for the key } + vkey : XPLMChar; END; PXPKeyState_t = ^XPKeyState_t; { XPWidgetGeometryChange_t - This structure contains the deltas for your widget's geometry when it - changes. + This structure contains the deltas for your widget's geometry when it + changes. } XPWidgetGeometryChange_t = RECORD - dx : integer; - { +Y = the widget moved up } - dy : integer; - dwidth : integer; - dheight : integer; + dx : Integer; + { +Y = the widget moved up } + dy : Integer; + dwidth : Integer; + dheight : Integer; END; PXPWidgetGeometryChange_t = ^XPWidgetGeometryChange_t; { XPDispatchMode - The dispatching modes describe how the widgets library sends out messages. - Currently there are three modes: + The dispatching modes describe how the widgets library sends out messages. + Currently there are three modes: } XPDispatchMode = ( - { The message will only be sent to the target widget. } + { The message will only be sent to the target widget. } xpMode_Direct = 0 - { The message is sent to the target widget, then up the chain of parents } - { until the message is handled or a parentless widget is reached. } + { The message is sent to the target widget, then up the chain of parents } + { until the message is handled or a parentless widget is reached. } ,xpMode_UpChain = 1 - { The message is sent to the target widget and then all of its children } - { recursively depth-first. } + { The message is sent to the target widget and then all of its children } + { recursively depth-first. } ,xpMode_Recursive = 2 - { The message is snet just to the target, but goes to every callback, even if } - { it is handled. } + { The message is snet just to the target, but goes to every callback, even if} + { it is handled. } ,xpMode_DirectAllCallbacks = 3 - { The message is only sent to the very first handler even if it is not } - { accepted. (This is really only useful for some internal Widget Lib } - { functions. } + { The message is only sent to the very first handler even if it is not } + { accepted. (This is really only useful for some internal widget library } + { functions.) } ,xpMode_Once = 4 ); @@ -173,240 +166,235 @@ TYPE { XPWidgetClass - Widget classes define predefined widget types. A widget class basically - specifies from a library the widget function to be used for the widget. - Most widgets can be made right from classes. + Widget classes define predefined widget types. A widget class basically + specifies from a library the widget function to be used for the widget. + Most widgets can be made right from classes. } - XPWidgetClass = integer; + XPWidgetClass = Integer; PXPWidgetClass = ^XPWidgetClass; CONST - { An unspecified widget class. Other widget classes are in } - { XPStandardWidgets.h } + { An unspecified widget class. Other widget classes are in } + { XPStandardWidgets.h } xpWidgetClass_None = 0; {___________________________________________________________________________ * WIDGET MESSAGES ___________________________________________________________________________} -{ - -} - { XPWidgetMessage - Widgets receive 32-bit messages indicating what action is to be taken or - notifications of events. The list of messages may be expanded. + Widgets receive 32-bit messages indicating what action is to be taken or + notifications of events. The list of messages may be expanded. } TYPE XPWidgetMessage = ( - { No message, should not be sent. } + { No message, should not be sent. } xpMsg_None = 0 - { The create message is sent once per widget that is created with your widget } - { function and once for any widget that has your widget function attached. } - { } - { Dispatching: Direct } - { } - { Param 1: 1 if you are being added as a subclass, 0 if the widget is first } - { being created. } + { The create message is sent once per widget that is created with your widget} + { function and once for any widget that has your widget function attached. } + { } + { Dispatching: Direct } + { } + { Param 1: 1 if you are being added as a subclass, 0 if the widget is first } + { being created. } ,xpMsg_Create = 1 - { The destroy message is sent once for each message that is destroyed that } - { has your widget function. } - { } - { Dispatching: Direct for all } - { } - { Param 1: 1 if being deleted by a recursive delete to the parent, 0 for } - { explicit deletion. } + { The destroy message is sent once for each message that is destroyed that } + { has your widget function. } + { } + { Dispatching: Direct for all } + { } + { Param 1: 1 if being deleted by a recursive delete to the parent, 0 for } + { explicit deletion. } ,xpMsg_Destroy = 2 - { The paint message is sent to your widget to draw itself. The paint message } - { is the bare-bones message; in response you must draw yourself, draw your } - { children, set up clipping and culling, check for visibility, etc. If you } - { don't want to do all of this, ignore the paint message and a draw message } - { (see below) will be sent to you. } - { } - { Dispatching: Direct } + { The paint message is sent to your widget to draw itself. The paint message } + { is the bare-bones message; in response you must draw yourself, draw your } + { children, set up clipping and culling, check for visibility, etc. If you } + { don't want to do all of this, ignore the paint message and a draw message } + { (see below) will be sent to you. } + { } + { Dispatching: Direct } ,xpMsg_Paint = 3 - { The draw message is sent to your widget when it is time to draw yourself. } - { OpenGL will be set up to draw in 2-d global screen coordinates, but you } - { should use the XPLM to set up OpenGL state. } - { } - { Dispatching: Direct } + { The draw message is sent to your widget when it is time to draw yourself. } + { OpenGL will be set up to draw in 2-d global screen coordinates, but you } + { should use the XPLM to set up OpenGL state. } + { } + { Dispatching: Direct } ,xpMsg_Draw = 4 - { The key press message is sent once per key that is pressed. The first } - { parameter is the type of key code (integer or char) and the second is the } - { code itself. By handling this event, you consume the key stroke. } - { } - { Handling this message 'consumes' the keystroke; not handling it passes it } - { to your parent widget. } - { } - { Dispatching: Up Chain } - { } - { : Param 1: A pointer to an XPKeyState_t structure with the keystroke. } + { The key press message is sent once per key that is pressed. The first } + { parameter is the type of key code (integer or char) and the second is the } + { code itself. By handling this event, you consume the key stroke. } + { } + { Handling this message 'consumes' the keystroke; not handling it passes it } + { to your parent widget. } + { } + { Dispatching: Up Chain } + { } + { Param 1: A pointer to an XPKeyState_t structure with the keystroke. } ,xpMsg_KeyPress = 5 - { Keyboard focus is being given to you. By handling this message you accept } - { keyboard focus. The first parameter will be one if a child of yours gave } - { up focus to you, 0 if someone set focus on you explicitly. } - { } - { : Handling this message accepts focus; not handling refuses focus. } - { } - { Dispatching: direct } - { } - { Param 1: 1 if you are gaining focus because your child is giving it up, 0 } - { if someone is explicitly giving you focus. } + { Keyboard focus is being given to you. By handling this message you accept } + { keyboard focus. The first parameter will be one if a child of yours gave up} + { focus to you, 0 if someone set focus on you explicitly. } + { } + { Handling this message accepts focus; not handling refuses focus. } + { } + { Dispatching: direct } + { } + { Param 1: 1 if you are gaining focus because your child is giving it up, 0 } + { if someone is explicitly giving you focus. } ,xpMsg_KeyTakeFocus = 6 - { Keyboard focus is being taken away from you. The first parameter will be } - { one if you are losing focus because another widget is taking it, or 0 if } - { someone called the API to make you lose focus explicitly. } - { } - { Dispatching: Direct } - { } - { Param 1: 1 if focus is being taken by another widget, 0 if code requested } - { to remove focus. } + { Keyboard focus is being taken away from you. The first parameter will be } + { one if you are losing focus because another widget is taking it, or 0 if } + { someone called the API to make you lose focus explicitly. } + { } + { Dispatching: Direct } + { } + { Param 1: 1 if focus is being taken by another widget, 0 if code requested } + { to remove focus. } ,xpMsg_KeyLoseFocus = 7 - { You receive one mousedown event per click with a mouse-state structure } - { pointed to by parameter 1, by accepting this you eat the click, otherwise } - { your parent gets it. You will not receive drag and mouse up messages if } - { you do not accept the down message. } - { } - { Handling this message consumes the mouse click, not handling it passes it } - { to the next widget. You can act 'transparent' as a window by never handling } - { moues clicks to certain areas. } - { } - { Dispatching: Up chain NOTE: Technically this is direct dispatched, but the } - { widgets library will shop it to each widget until one consumes the click, } - { making it effectively "up chain". } - { } - { Param 1: A pointer to an XPMouseState_t containing the mouse status. } + { You receive one mousedown event per click with a mouse-state structure } + { pointed to by parameter 1, by accepting this you eat the click, otherwise } + { your parent gets it. You will not receive drag and mouse up messages if you} + { do not accept the down message. } + { } + { Handling this message consumes the mouse click, not handling it passes it } + { to the next widget. You can act 'transparent' as a window by never handling} + { moues clicks to certain areas. } + { } + { Dispatching: Up chain NOTE: Technically this is direct dispatched, but the } + { widgets library will shop it to each widget until one consumes the click, } + { making it effectively "up chain". } + { } + { Param 1: A pointer to an XPMouseState_t containing the mouse status. } ,xpMsg_MouseDown = 8 - { You receive a series of mouse drag messages (typically one per frame in the } - { sim) as the mouse is moved once you have accepted a mouse down message. } - { Parameter one points to a mouse-state structure describing the mouse } - { location. You will continue to receive these until the mouse button is } - { released. You may receive multiple mouse state messages with the same mouse } - { position. You will receive mouse drag events even if the mouse is dragged } - { out of your current or original bounds at the time of the mouse down. } - { } - { Dispatching: Direct } - { } - { Param 1: A pointer to an XPMouseState_t containing the mouse status. } + { You receive a series of mouse drag messages (typically one per frame in the} + { sim) as the mouse is moved once you have accepted a mouse down message. } + { Parameter one points to a mouse-state structure describing the mouse } + { location. You will continue to receive these until the mouse button is } + { released. You may receive multiple mouse state messages with the same mouse} + { position. You will receive mouse drag events even if the mouse is dragged } + { out of your current or original bounds at the time of the mouse down. } + { } + { Dispatching: Direct } + { } + { Param 1: A pointer to an XPMouseState_t containing the mouse status. } ,xpMsg_MouseDrag = 9 - { The mouseup event is sent once when the mouse button is released after a } - { drag or click. You only receive this message if you accept the mouseDown } - { message. Parameter one points to a mouse state structure. } - { } - { Dispatching: Direct } - { } - { Param 1: A pointer to an XPMouseState_t containing the mouse status. } + { The mouseup event is sent once when the mouse button is released after a } + { drag or click. You only receive this message if you accept the mouseDown } + { message. Parameter one points to a mouse state structure. } + { } + { Dispatching: Direct } + { } + { Param 1: A pointer to an XPMouseState_t containing the mouse status. } ,xpMsg_MouseUp = 10 - { Your geometry or a child's geometry is being changed. } - { } - { Dispatching: Up chain } - { } - { Param 1: The widget ID of the original reshaped target. } - { } - { Param 2: A pointer to a XPWidgetGeometryChange_t struct describing the } - { change. } + { Your geometry or a child's geometry is being changed. } + { } + { Dispatching: Up chain } + { } + { Param 1: The widget ID of the original reshaped target. } + { } + { Param 2: A pointer to a XPWidgetGeometryChange_t struct describing the } + { change. } ,xpMsg_Reshape = 11 - { Your exposed area has changed. } - { } - { Dispatching: Direct } + { Your exposed area has changed. } + { } + { Dispatching: Direct } ,xpMsg_ExposedChanged = 12 - { A child has been added to you. The child's ID is passed in parameter one. } - { } - { } - { Dispatching: Direct } - { } - { Param 1: The Widget ID of the child being added. } + { A child has been added to you. The child's ID is passed in parameter one. } + { } + { Dispatching: Direct } + { } + { Param 1: The Widget ID of the child being added. } ,xpMsg_AcceptChild = 13 - { A child has been removed from to you. The child's ID is passed in } - { parameter one. } - { } - { Dispatching: Direct } - { } - { Param 1: The Widget ID of the child being removed. } + { A child has been removed from to you. The child's ID is passed in parameter} + { one. } + { } + { Dispatching: Direct } + { } + { Param 1: The Widget ID of the child being removed. } ,xpMsg_LoseChild = 14 - { You now have a new parent, or have no parent. The parent's ID is passed } - { in, or 0 for no parent. } - { } - { Dispatching: Direct } - { } - { Param 1: The Widget ID of your parent } + { You now have a new parent, or have no parent. The parent's ID is passed in,} + { or 0 for no parent. } + { } + { Dispatching: Direct } + { } + { Param 1: The Widget ID of your parent } ,xpMsg_AcceptParent = 15 - { You or a child has been shown. Note that this does not include you being } - { shown because your parent was shown, you were put in a new parent, your } - { root was shown, etc. } - { } - { Dispatching: Up chain } - { } - { Param 1: The widget ID of the shown widget. } + { You or a child has been shown. Note that this does not include you being } + { shown because your parent was shown, you were put in a new parent, your } + { root was shown, etc. } + { } + { Dispatching: Up chain } + { } + { Param 1: The widget ID of the shown widget. } ,xpMsg_Shown = 16 - { You have been hidden. See limitations above. } - { } - { Dispatching: Up chain } - { } - { Param 1: The widget ID of the hidden widget. } + { You have been hidden. See limitations above. } + { } + { Dispatching: Up chain } + { } + { Param 1: The widget ID of the hidden widget. } ,xpMsg_Hidden = 17 - { Your descriptor has changed. } - { } - { Dispatching: Direct } + { Your descriptor has changed. } + { } + { Dispatching: Direct } ,xpMsg_DescriptorChanged = 18 - { A property has changed. Param 1 contains the property ID. } - { } - { Dispatching: Direct } - { } - { Param 1: The Property ID being changed. } - { } - { Param 2: The new property value } + { A property has changed. Param 1 contains the property ID. } + { } + { Dispatching: Direct } + { } + { Param 1: The Property ID being changed. } + { } + { Param 2: The new property value } ,xpMsg_PropertyChanged = 19 {$IFDEF XPLM200} - { The mouse wheel has moved. } - { } - { Return 1 to consume the mouse wheel move, or 0 to pass the message to a } - { parent. Dispatching: Up chain } - { } - { Param 1: A pointer to an XPMouseState_t containing the mouse status. } + { The mouse wheel has moved. } + { } + { Return 1 to consume the mouse wheel move, or 0 to pass the message to a } + { parent. Dispatching: Up chain } + { } + { Param 1: A pointer to an XPMouseState_t containing the mouse status. } ,xpMsg_MouseWheel = 20 -{$ENDIF} +{$ENDIF XPLM200} {$IFDEF XPLM200} - { The cursor is over your widget. If you consume this message, change the } - { XPLMCursorStatus value to indicate the desired result, with the same rules } - { as in XPLMDisplay.h. } - { } - { Return 1 to consume this message, 0 to pass it on. } - { } - { Dispatching: Up chain Param 1: A pointer to an XPMouseState_t struct } - { containing the mouse status. } - { } - { Param 2: A pointer to a XPLMCursorStatus - set this to the cursor result } - { you desire. } + { The cursor is over your widget. If you consume this message, change the } + { XPLMCursorStatus value to indicate the desired result, with the same rules } + { as in XPLMDisplay.h. } + { } + { Return 1 to consume this message, 0 to pass it on. } + { } + { Dispatching: Up chain Param 1: A pointer to an XPMouseState_t struct } + { containing the mouse status. } + { } + { Param 2: A pointer to a XPLMCursorStatus - set this to the cursor result } + { you desire. } ,xpMsg_CursorAdjust = 21 -{$ENDIF} +{$ENDIF XPLM200} - { NOTE: Message IDs 1000 - 9999 are allocated to the standard widget classes } - { provided with the library with 1000 - 1099 for widget class 0, 1100 - 1199 } - { for widget class 1, etc. Message IDs 10,000 and beyond are for plugin use. } + { NOTE: Message IDs 1000 - 9999 are allocated to the standard widget classes } + { provided with the library with 1000 - 1099 for widget class 0, 1100 - 1199 } + { for widget class 1, etc. Message IDs 10,000 and beyond are for plugin use. } ,xpMsg_UserStart = 10000 ); @@ -415,27 +403,25 @@ TYPE {___________________________________________________________________________ * WIDGET CALLBACK FUNCTION ___________________________________________________________________________} -{ - -} - { XPWidgetFunc_t - This function defines your custom widget's behavior. It will be called by - the widgets library to send messages to your widget. The message and - widget ID are passed in, as well as two ptr-width signed parameters whose - meaning varies with the message. Return 1 to indicate that you have - processed the message, 0 to indicate that you have not. For any message - that is not understood, return 0. + This function defines your custom widget's behavior. It will be called by + the widgets library to send messages to your widget. The message and widget + ID are passed in, as well as two ptr-width signed parameters whose meaning + varies with the message. Return 1 to indicate that you have processed the + message, 0 to indicate that you have not. For any message that is not + understood, return 0. } TYPE XPWidgetFunc_t = FUNCTION( inMessage : XPWidgetMessage; inWidget : XPWidgetID; inParam1 : intptr_t; - inParam2 : intptr_t) : integer; cdecl; + inParam2 : intptr_t) : Integer; cdecl; + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/Widgets/XPWidgetUtils.pas b/XPSDK/Delphi/Widgets/XPWidgetUtils.pas index 9dcb1d2..9621126 100644 --- a/XPSDK/Delphi/Widgets/XPWidgetUtils.pas +++ b/XPSDK/Delphi/Widgets/XPWidgetUtils.pas @@ -1,74 +1,70 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPWidgetUtils; INTERFACE { - XPWidgetUtils - USAGE NOTES + ## USAGE NOTES - The XPWidgetUtils library contains useful functions that make writing and - using widgets less of a pain. + The XPWidgetUtils library contains useful functions that make writing and + using widgets less of a pain. - One set of functions are the widget behavior functions. These functions - each add specific useful behaviors to widgets. They can be used in two - manners: + One set of functions are the widget behavior functions. These functions + each add specific useful behaviors to widgets. They can be used in two + manners: - 1. You can add a widget behavior function to a widget as a callback proc - using the XPAddWidgetCallback function. The widget will gain that - behavior. Remember that the last function you add has highest priority. - You can use this to change or augment the behavior of an existing finished - widget. - - 2. You can call a widget function from inside your own widget function. - This allows you to include useful behaviors in custom-built widgets. A - number of the standard widgets get their behavior from this library. To do - this, call the behavior function from your function first. If it returns - 1, that means it handled the event and you don't need to; simply return 1. + 1. You can add a widget behavior function to a widget as a callback proc + using the XPAddWidgetCallback function. The widget will gain that + behavior. Remember that the last function you add has highest priority. + You can use this to change or augment the behavior of an existing + finished widget. + 2. You can call a widget function from inside your own widget function. + This allows you to include useful behaviors in custom-built widgets. A + number of the standard widgets get their behavior from this library. To + do this, call the behavior function from your function first. If it + returns 1, that means it handled the event and you don't need to; simply + return 1. } -USES XPWidgetDefs; +USES + XPWidgetDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * GENERAL UTILITIES ___________________________________________________________________________} -{ - -} - { XPWidgetCreate_t - This structure contains all of the parameters needed to create a wiget. It - is used with XPUCreateWidgets to create widgets in bulk from an array. All - parameters correspond to those of XPCreateWidget except for the container - index. If the container index is equal to the index of a widget in the - array, the widget in the array passed to XPUCreateWidgets is used as the - parent of this widget. Note that if you pass an index greater than your - own position in the array, the parent you are requesting will not exist - yet. If the container index is NO_PARENT, the parent widget is specified as - NULL. If the container index is PARAM_PARENT, the widget passed into - XPUCreateWidgets is used. + This structure contains all of the parameters needed to create a wiget. It + is used with XPUCreateWidgets to create widgets in bulk from an array. All + parameters correspond to those of XPCreateWidget except for the container + index. + + If the container index is equal to the index of a widget in the array, the + widget in the array passed to XPUCreateWidgets is used as the parent of + this widget. Note that if you pass an index greater than your own position + in the array, the parent you are requesting will not exist yet. + + If the container index is NO_PARENT, the parent widget is specified as + NULL. If the container index is PARAM_PARENT, the widget passed into + XPUCreateWidgets is used. } TYPE XPWidgetCreate_t = RECORD - left : integer; - top : integer; - right : integer; - bottom : integer; - visible : integer; - descriptor : Pchar; - isRoot : integer; - containerIndex : integer; + left : Integer; + top : Integer; + right : Integer; + bottom : Integer; + visible : Integer; + descriptor : XPLMString; + { Whether ethis widget is a root wiget } + isRoot : Integer; + { The index of the widget to contain within, or a constant } + containerIndex : Integer; widgetClass : XPWidgetClass; END; PXPWidgetCreate_t = ^XPWidgetCreate_t; @@ -82,144 +78,120 @@ CONST { XPUCreateWidgets - This function creates a series of widgets from a table...see - XPCreateWidget_t above. Pass in an array of widget creation structures and - an array of widget IDs that will receive each widget. + This function creates a series of widgets from a table (see + XPCreateWidget_t above). Pass in an array of widget creation structures and + an array of widget IDs that will receive each widget. - Widget parents are specified by index into the created widget table, - allowing you to create nested widget structures. You can create multiple - widget trees in one table. Generally you should create widget trees from - the top down. + Widget parents are specified by index into the created widget table, + allowing you to create nested widget structures. You can create multiple + widget trees in one table. Generally you should create widget trees from + the top down. - You can also pass in a widget ID that will be used when the widget's parent - is listed as PARAM_PARENT; this allows you to embed widgets created with - XPUCreateWidgets in a widget created previously. + You can also pass in a widget ID that will be used when the widget's parent + is listed as PARAM_PARENT; this allows you to embed widgets created with + XPUCreateWidgets in a widget created previously. } PROCEDURE XPUCreateWidgets( inWidgetDefs : PXPWidgetCreate_t; - inCount : integer; + inCount : Integer; inParamParent : XPWidgetID; ioWidgets : PXPWidgetID); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPUMoveWidgetBy - Simply moves a widget by an amount, +x = right, +y=up, without resizing the - widget. + Simply moves a widget by an amount, +x = right, +y=up, without resizing the + widget. } PROCEDURE XPUMoveWidgetBy( inWidget : XPWidgetID; - inDeltaX : integer; - inDeltaY : integer); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inDeltaX : Integer; + inDeltaY : Integer); + cdecl; external XPWIDGETS.DLL; {___________________________________________________________________________ * LAYOUT MANAGERS ___________________________________________________________________________} { - The layout managers are widget behavior functions for handling where - widgets move. Layout managers can be called from a widget function or - attached to a widget later. + The layout managers are widget behavior functions for handling where + widgets move. Layout managers can be called from a widget function or + attached to a widget later. } - { XPUFixedLayout - This function causes the widget to maintain its children in fixed position - relative to itself as it is resized. Use this on the top level 'window' - widget for your window. + This function causes the widget to maintain its children in fixed position + relative to itself as it is resized. Use this on the top level 'window' + widget for your window. } FUNCTION XPUFixedLayout( inMessage : XPWidgetMessage; inWidget : XPWidgetID; inParam1 : intptr_t; - inParam2 : intptr_t) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inParam2 : intptr_t) : Integer; + cdecl; external XPWIDGETS.DLL; {___________________________________________________________________________ * WIDGET PROC BEHAVIORS ___________________________________________________________________________} { - These widget behavior functions add other useful behaviors to widgets. - These functions cannot be attached to a widget; they must be called from - your widget function. + These widget behavior functions add other useful behaviors to widgets. + These functions cannot be attached to a widget; they must be called from + your widget function. } - { XPUSelectIfNeeded - This causes the widget to bring its window to the foreground if it is not - already. inEatClick specifies whether clicks in the background should be - consumed by bringin the window to the foreground. + This causes the widget to bring its window to the foreground if it is not + already. inEatClick specifies whether clicks in the background should be + consumed by bringin the window to the foreground. } FUNCTION XPUSelectIfNeeded( inMessage : XPWidgetMessage; inWidget : XPWidgetID; inParam1 : intptr_t; inParam2 : intptr_t; - inEatClick : integer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inEatClick : Integer) : Integer; + cdecl; external XPWIDGETS.DLL; { XPUDefocusKeyboard - This causes a click in the widget to send keyboard focus back to X-Plane. - This stops editing of any text fields, etc. + This causes a click in the widget to send keyboard focus back to X-Plane. + This stops editing of any text fields, etc. } FUNCTION XPUDefocusKeyboard( inMessage : XPWidgetMessage; inWidget : XPWidgetID; inParam1 : intptr_t; inParam2 : intptr_t; - inEatClick : integer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inEatClick : Integer) : Integer; + cdecl; external XPWIDGETS.DLL; { XPUDragWidget - XPUDragWidget drags the widget in response to mouse clicks. Pass in not - only the event, but the global coordinates of the drag region, which might - be a sub-region of your widget (for example, a title bar). + XPUDragWidget drags the widget in response to mouse clicks. Pass in not + only the event, but the global coordinates of the drag region, which might + be a sub-region of your widget (for example, a title bar). } FUNCTION XPUDragWidget( inMessage : XPWidgetMessage; inWidget : XPWidgetID; inParam1 : intptr_t; inParam2 : intptr_t; - inLeft : integer; - inTop : integer; - inRight : integer; - inBottom : integer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inLeft : Integer; + inTop : Integer; + inRight : Integer; + inBottom : Integer) : Integer; + cdecl; external XPWIDGETS.DLL; + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/Widgets/XPWidgets.pas b/XPSDK/Delphi/Widgets/XPWidgets.pas index 44623dc..46ae542 100644 --- a/XPSDK/Delphi/Widgets/XPWidgets.pas +++ b/XPSDK/Delphi/Widgets/XPWidgets.pas @@ -1,665 +1,527 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPWidgets; INTERFACE { - WIDGETS - THEORY OF OPERATION AND NOTES + ## THEORY OF OPERATION AND NOTES - Widgets are persistent view 'objects' for X-Plane. A widget is an object - referenced by its opaque handle (widget ID) and the APIs in this file. You - cannot access the widget's guts directly. Every Widget has the following - intrinsic data: + Widgets are persistent view 'objects' for X-Plane. A widget is an object + referenced by its opaque handle (widget ID) and the APIs in this file. You + cannot access the widget's guts directly. Every Widget has the following + intrinsic data: - - A bounding box defined in global screen coordinates with 0,0 in the - bottom left and +y = up, +x = right. + - A bounding box defined in global screen coordinates with 0,0 in the + bottom left and +y = up, +x = right. + - A visible box, which is the intersection of the bounding box with the + widget's parents visible box. + - Zero or one parent widgets. (Always zero if the widget is a root widget. + - Zero or more child widgets. + - Whether the widget is a root. Root widgets are the top level plugin + windows. + - Whether the widget is visible. + - A text string descriptor, whose meaning varies from widget to widget. + - An arbitrary set of 32 bit integral properties defined by 32-bit integral + keys. This is how specific widgets store specific data. + - A list of widget callbacks proc that implements the widgets behaviors. - - A visible box, which is the intersection of the bounding box with the - widget's parents visible box. + The Widgets library sends messages to widgets to request specific behaviors + or notify the widget of things. - - Zero or one parent widgets. (Always zero if the widget is a root widget. + Widgets may have more than one callback function, in which case messages + are sent to the most recently added callback function until the message is + handled. Messages may also be sent to parents or children; see the + XPWidgetDefs.h header file for the different widget message dispatching + functions. By adding a callback function to a window you can 'subclass' its + behavior. + A set of standard widgets are provided that serve common UI purposes. You + can also customize or implement entirely custom widgets. - - Zero or more child widgets. + Widgets are different than other view hierarchies (most notably Win32, + which they bear a striking resemblance to) in the following ways: - - Whether the widget is a root. Root widgets are the top level plugin - windows. - - - Whether the widget is visible. - - - A text string descriptor, whose meaning varies from widget to widget. - - - An arbitrary set of 32 bit integral properties defined by 32-bit integral - keys. This is how specific widgets - - store specific data. - - - A list of widget callbacks proc that implements the widgets behaviors. - - The Widgets library sends messages to widgets to request specific behaviors - or notify the widget of things. - - Widgets may have more than one callback function, in which case messages - are sent to the most recently added callback function until the message is - handled. Messages may also be sent to parents or children; see the - XPWidgetDefs.h header file for the different widget message dispatching - functions. By adding a callback function to a window you can 'subclass' - its behavior. - - A set of standard widgets are provided that serve common UI purposes. You - can also customize or implement entirely custom widgets. - - Widgets are different than other view hierarchies (most notably Win32, - which they bear a striking resemblance to) in the following ways: - - - Not all behavior can be patched. State that is managed by the XPWidgets - DLL and not by individual widgets cannot be customized. - - - All coordinates are in global screen coordinates. Coordinates are not - relative to an enclosing widget, nor are they relative to a display window. - - - - Widget messages are always dispatched synchronously, and there is no - concept of scheduling an update or a dirty region. Messages originate from - X-Plane as the sim cycle goes by. Since x-plane is constantly redrawing, - so are widgets; there is no need to mark a part of a widget as 'needing - redrawing' because redrawing happens frequently whether the widget needs it - or not. - - - Any widget may be a 'root' widget, causing it to be drawn; there is no - relationship between widget class and rootness. Root widgets are - imlemented as XPLMDisply windows. + - Not all behavior can be patched. State that is managed by the XPWidgets + DLL and not by individual widgets cannot be customized. + - All coordinates are in global screen coordinates. Coordinates are not + relative to an enclosing widget, nor are they relative to a display + window. + - Widget messages are always dispatched synchronously, and there is no + concept of scheduling an update or a dirty region. Messages originate + from X-Plane as the sim cycle goes by. Since X-Plane is constantly + redrawing, so are widgets; there is no need to mark a part of a widget as + 'needing redrawing' because redrawing happens frequently whether the + widget needs it or not. + - Any widget may be a 'root' widget, causing it to be drawn; there is no + relationship between widget class and rootness. Root widgets are + imlemented as XPLMDisply windows. } -USES XPWidgetDefs; +USES + XPWidgetDefs, XPLMDisplay; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * WIDGET CREATION AND MANAGEMENT ___________________________________________________________________________} -{ - -} - { XPCreateWidget - This function creates a new widget and returns the new widget's ID to you. - If the widget creation fails for some reason, it returns NULL. Widget - creation will fail either if you pass a bad class ID or if there is not - adequate memory. + This function creates a new widget and returns the new widget's ID to you. + If the widget creation fails for some reason, it returns NULL. Widget + creation will fail either if you pass a bad class ID or if there is not + adequate memory. - Input Parameters: + Input Parameters: - - Top, left, bottom, and right in global screen coordinates defining the - widget's location on the screen. + - Top, left, bottom, and right in global screen coordinates defining the + widget's location on the screen. + - inVisible is 1 if the widget should be drawn, 0 to start the widget as + hidden. + - inDescriptor is a null terminated string that will become the widget's + descriptor. + - inIsRoot is 1 if this is going to be a root widget, 0 if it will not be. + - inContainer is the ID of this widget's container. It must be 0 for a root + widget. for a non-root widget, pass the widget ID of the widget to place + this widget within. If this widget is not going to start inside another + widget, pass 0; this new widget will then just be floating off in space + (and will not be drawn until it is placed in a widget. + - inClass is the class of the widget to draw. Use one of the predefined + class-IDs to create a standard widget. - - inVisible is 1 if the widget should be drawn, 0 to start the widget as - hidden. - - - inDescriptor is a null terminated string that will become the widget's - descriptor. - - - inIsRoot is 1 if this is going to be a root widget, 0 if it will not be. - - - inContainer is the ID of this widget's container. It must be 0 for a - root widget. for a non-root widget, pass the widget ID of the widget to - place this widget within. If this widget is not going to start inside - another widget, pass 0; this new widget will then just be floating off in - space (and will not be drawn until it is placed in a widget. - - - inClass is the class of the widget to draw. Use one of the predefined - class-IDs to create a standard widget. - - A note on widget embedding: a widget is only called (and will be drawn, - etc.) if it is placed within a widget that will be called. Root widgets - are always called. So it is possible to have whole chains of widgets that - are simply not called. You can preconstruct widget trees and then place - them into root widgets later to activate them if you wish. + A note on widget embedding: a widget is only called (and will be drawn, + etc.) if it is placed within a widget that will be called. Root widgets are + always called. So it is possible to have whole chains of widgets that are + simply not called. You can preconstruct widget trees and then place them + into root widgets later to activate them if you wish. } FUNCTION XPCreateWidget( - inLeft : integer; - inTop : integer; - inRight : integer; - inBottom : integer; - inVisible : integer; - inDescriptor : Pchar; - inIsRoot : integer; + inLeft : Integer; + inTop : Integer; + inRight : Integer; + inBottom : Integer; + inVisible : Integer; + inDescriptor : XPLMString; + inIsRoot : Integer; inContainer : XPWidgetID; inClass : XPWidgetClass) : XPWidgetID; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPCreateCustomWidget - This function is the same as XPCreateWidget except that instead of passing - a class ID, you pass your widget callback function pointer defining the - widget. Use this function to define a custom widget. All parameters are - the same as XPCreateWidget, except that the widget class has been replaced - with the widget function. + This function is the same as XPCreateWidget except that instead of passing + a class ID, you pass your widget callback function pointer defining the + widget. Use this function to define a custom widget. All parameters are the + same as XPCreateWidget, except that the widget class has been replaced with + the widget function. } FUNCTION XPCreateCustomWidget( - inLeft : integer; - inTop : integer; - inRight : integer; - inBottom : integer; - inVisible : integer; - inDescriptor : Pchar; - inIsRoot : integer; + inLeft : Integer; + inTop : Integer; + inRight : Integer; + inBottom : Integer; + inVisible : Integer; + inDescriptor : XPLMString; + inIsRoot : Integer; inContainer : XPWidgetID; inCallback : XPWidgetFunc_t) : XPWidgetID; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPDestroyWidget - This class destroys a widget. Pass in the ID of the widget to kill. If - you pass 1 for inDestroyChilren, the widget's children will be destroyed - first, then this widget will be destroyed. (Furthermore, the widget's - children will be destroyed with the inDestroyChildren flag set to 1, so the - destruction will recurse down the widget tree.) If you pass 0 for this - flag, the child widgets will simply end up with their parent set to 0. + This class destroys a widget. Pass in the ID of the widget to kill. If you + pass 1 for inDestroyChilren, the widget's children will be destroyed first, + then this widget will be destroyed. (Furthermore, the widget's children + will be destroyed with the inDestroyChildren flag set to 1, so the + destruction will recurse down the widget tree.) If you pass 0 for this + flag, the child widgets will simply end up with their parent set to 0. } PROCEDURE XPDestroyWidget( inWidget : XPWidgetID; - inDestroyChildren : integer); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inDestroyChildren : Integer); + cdecl; external XPWIDGETS.DLL; { XPSendMessageToWidget - This sends any message to a widget. You should probably not go around - simulating the predefined messages that the widgets library defines for - you. You may however define custom messages for your widgets and send them - with this method. + This sends any message to a widget. You should probably not go around + simulating the predefined messages that the widgets library defines for + you. You may however define custom messages for your widgets and send them + with this method. - This method supports several dispatching patterns; see XPDispatchMode for - more info. The function returns 1 if the message was handled, 0 if it was - not. + This method supports several dispatching patterns; see XPDispatchMode for + more info. The function returns 1 if the message was handled, 0 if it was + not. - For each widget that receives the message (see the dispatching modes), each - widget function from the most recently installed to the oldest one - receives the message in order until it is handled. + For each widget that receives the message (see the dispatching modes), each + widget function from the most recently installed to the oldest one receives + the message in order until it is handled. } FUNCTION XPSendMessageToWidget( inWidget : XPWidgetID; inMessage : XPWidgetMessage; inMode : XPDispatchMode; inParam1 : intptr_t; - inParam2 : intptr_t) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inParam2 : intptr_t) : Integer; + cdecl; external XPWIDGETS.DLL; {___________________________________________________________________________ * WIDGET POSITIONING AND VISIBILITY ___________________________________________________________________________} -{ - -} - { XPPlaceWidgetWithin - This function changes which container a widget resides in. You may NOT use - this function on a root widget! inSubWidget is the widget that will be - moved. Pass a widget ID in inContainer to make inSubWidget be a child of - inContainer. It will become the last/closest widget in the container. - Pass 0 to remove the widget from any container. Any call to this other - than passing the widget ID of the old parent of the affected widget will - cause the widget to be removed from its old parent. Placing a widget within - its own parent simply makes it the last widget. + This function changes which container a widget resides in. You may NOT use + this function on a root widget! inSubWidget is the widget that will be + moved. Pass a widget ID in inContainer to make inSubWidget be a child of + inContainer. It will become the last/closest widget in the container. Pass + 0 to remove the widget from any container. Any call to this other than + passing the widget ID of the old parent of the affected widget will cause + the widget to be removed from its old parent. Placing a widget within its + own parent simply makes it the last widget. - NOTE: this routine does not reposition the sub widget in global - coordinates. If the container has layout management code, it will - reposition the subwidget for you, otherwise you must do it with - SetWidgetGeometry. + NOTE: this routine does not reposition the sub widget in global + coordinates. If the container has layout management code, it will + reposition the subwidget for you, otherwise you must do it with + SetWidgetGeometry. } PROCEDURE XPPlaceWidgetWithin( inSubWidget : XPWidgetID; inContainer : XPWidgetID); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPCountChildWidgets - This routine returns the number of widgets another widget contains. + This routine returns the number of widgets another widget contains. } FUNCTION XPCountChildWidgets( - inWidget : XPWidgetID) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inWidget : XPWidgetID) : Integer; + cdecl; external XPWIDGETS.DLL; { XPGetNthChildWidget - This routine returns the widget ID of a child widget by index. Indexes are - 0 based, from 0 to one minus the number of widgets in the parent, - inclusive. If the index is invalid, 0 is returned. + This routine returns the widget ID of a child widget by index. Indexes are + 0 based, from 0 to one minus the number of widgets in the parent, + inclusive. If the index is invalid, 0 is returned. } FUNCTION XPGetNthChildWidget( inWidget : XPWidgetID; - inIndex : integer) : XPWidgetID; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inIndex : Integer) : XPWidgetID; + cdecl; external XPWIDGETS.DLL; { XPGetParentWidget - This routine returns the parent of a widget, or 0 if the widget has no - parent. Root widgets never have parents and therefore always return 0. + Returns the parent of a widget, or 0 if the widget has no parent. Root + widgets never have parents and therefore always return 0. } FUNCTION XPGetParentWidget( inWidget : XPWidgetID) : XPWidgetID; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPShowWidget - This routine makes a widget visible if it is not already. Note that if a - widget is not in a rooted widget hierarchy or one of its parents is not - visible, it will still not be visible to the user. + This routine makes a widget visible if it is not already. Note that if a + widget is not in a rooted widget hierarchy or one of its parents is not + visible, it will still not be visible to the user. } PROCEDURE XPShowWidget( inWidget : XPWidgetID); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPHideWidget - Makes a widget invisible. See XPShowWidget for considerations of when a - widget might not be visible despite its own visibility state. + Makes a widget invisible. See XPShowWidget for considerations of when a + widget might not be visible despite its own visibility state. } PROCEDURE XPHideWidget( inWidget : XPWidgetID); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPIsWidgetVisible - This returns 1 if a widget is visible, 0 if it is not. Note that this - routine takes into consideration whether a parent is invisible. Use this - routine to tell if the user can see the widget. + This returns 1 if a widget is visible, 0 if it is not. Note that this + routine takes into consideration whether a parent is invisible. Use this + routine to tell if the user can see the widget. } FUNCTION XPIsWidgetVisible( - inWidget : XPWidgetID) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inWidget : XPWidgetID) : Integer; + cdecl; external XPWIDGETS.DLL; { XPFindRootWidget - XPFindRootWidget returns the Widget ID of the root widget that contains the - passed in widget or NULL if the passed in widget is not in a rooted - hierarchy. + Returns the Widget ID of the root widget that contains the passed in widget + or NULL if the passed in widget is not in a rooted hierarchy. } FUNCTION XPFindRootWidget( inWidget : XPWidgetID) : XPWidgetID; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPBringRootWidgetToFront - This routine makes the specified widget be in the front most widget - hierarchy. If this widget is a root widget, its widget hierarchy comes to - front, otherwise the widget's root is brought to the front. If this widget - is not in an active widget hiearchy (e.g. there is no root widget at the - top of the tree), this routine does nothing. + This routine makes the specified widget be in the front most widget + hierarchy. If this widget is a root widget, its widget hierarchy comes to + front, otherwise the widget's root is brought to the front. If this widget + is not in an active widget hiearchy (e.g. there is no root widget at the + top of the tree), this routine does nothing. } PROCEDURE XPBringRootWidgetToFront( inWidget : XPWidgetID); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPIsWidgetInFront - This routine returns true if this widget's hierarchy is the front most - hierarchy. It returns false if the widget's hierarchy is not in front, or - if the widget is not in a rooted hierarchy. + This routine returns true if this widget's hierarchy is the front most + hierarchy. It returns false if the widget's hierarchy is not in front, or + if the widget is not in a rooted hierarchy. } FUNCTION XPIsWidgetInFront( - inWidget : XPWidgetID) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inWidget : XPWidgetID) : Integer; + cdecl; external XPWIDGETS.DLL; { XPGetWidgetGeometry - This routine returns the bounding box of a widget in global coordinates. - Pass NULL for any parameter you are not interested in. + This routine returns the bounding box of a widget in global coordinates. + Pass NULL for any parameter you are not interested in. } PROCEDURE XPGetWidgetGeometry( inWidget : XPWidgetID; - outLeft : Pinteger; { Can be nil } - outTop : Pinteger; { Can be nil } - outRight : Pinteger; { Can be nil } - outBottom : Pinteger); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outLeft : PInteger; { Can be nil } + outTop : PInteger; { Can be nil } + outRight : PInteger; { Can be nil } + outBottom : PInteger); { Can be nil } + cdecl; external XPWIDGETS.DLL; { XPSetWidgetGeometry - This function changes the bounding box of a widget. + This function changes the bounding box of a widget. } PROCEDURE XPSetWidgetGeometry( inWidget : XPWidgetID; - inLeft : integer; - inTop : integer; - inRight : integer; - inBottom : integer); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inLeft : Integer; + inTop : Integer; + inRight : Integer; + inBottom : Integer); + cdecl; external XPWIDGETS.DLL; { XPGetWidgetForLocation - Given a widget and a location, this routine returns the widget ID of the - child of that widget that owns that location. If inRecursive is true then - this will return a child of a child of a widget as it tries to find the - deepest widget at that location. If inVisibleOnly is true, then only - visible widgets are considered, otherwise all widgets are considered. The - widget ID passed for inContainer will be returned if the location is in - that widget but not in a child widget. 0 is returned if the location is - not in the container. + Given a widget and a location, this routine returns the widget ID of the + child of that widget that owns that location. If inRecursive is true then + this will return a child of a child of a widget as it tries to find the + deepest widget at that location. If inVisibleOnly is true, then only + visible widgets are considered, otherwise all widgets are considered. The + widget ID passed for inContainer will be returned if the location is in + that widget but not in a child widget. 0 is returned if the location is not + in the container. - NOTE: if a widget's geometry extends outside its parents geometry, it will - not be returned by this call for mouse locations outside the parent - geometry. The parent geometry limits the child's eligibility for mouse - location. + NOTE: if a widget's geometry extends outside its parents geometry, it will + not be returned by this call for mouse locations outside the parent + geometry. The parent geometry limits the child's eligibility for mouse + location. } FUNCTION XPGetWidgetForLocation( inContainer : XPWidgetID; - inXOffset : integer; - inYOffset : integer; - inRecursive : integer; - inVisibleOnly : integer) : XPWidgetID; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inXOffset : Integer; + inYOffset : Integer; + inRecursive : Integer; + inVisibleOnly : Integer) : XPWidgetID; + cdecl; external XPWIDGETS.DLL; { XPGetWidgetExposedGeometry - This routine returns the bounds of the area of a widget that is completely - within its parent widgets. Since a widget's bounding box can be outside - its parent, part of its area will not be elligible for mouse clicks and - should not draw. Use XPGetWidgetGeometry to find out what area defines - your widget's shape, but use this routine to find out what area to actually - draw into. Note that the widget library does not use OpenGL clipping to - keep frame rates up, although you could use it internally. + This routine returns the bounds of the area of a widget that is completely + within its parent widgets. Since a widget's bounding box can be outside its + parent, part of its area will not be elligible for mouse clicks and should + not draw. Use XPGetWidgetGeometry to find out what area defines your + widget's shape, but use this routine to find out what area to actually draw + into. Note that the widget library does not use OpenGL clipping to keep + frame rates up, although you could use it internally. } PROCEDURE XPGetWidgetExposedGeometry( inWidgetID : XPWidgetID; - outLeft : Pinteger; { Can be nil } - outTop : Pinteger; { Can be nil } - outRight : Pinteger; { Can be nil } - outBottom : Pinteger); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outLeft : PInteger; { Can be nil } + outTop : PInteger; { Can be nil } + outRight : PInteger; { Can be nil } + outBottom : PInteger); { Can be nil } + cdecl; external XPWIDGETS.DLL; {___________________________________________________________________________ * ACCESSING WIDGET DATA ___________________________________________________________________________} -{ - -} - { XPSetWidgetDescriptor - Every widget has a descriptor, which is a text string. What the text - string is used for varies from widget to widget; for example, a push - button's text is its descriptor, a caption shows its descriptor, and a text - field's descriptor is the text being edited. In other words, the usage for - the text varies from widget to widget, but this API provides a universal - and convenient way to get at it. While not all UI widgets need their - descriptor, many do. + Every widget has a descriptor, which is a text string. What the text string + is used for varies from widget to widget; for example, a push button's text + is its descriptor, a caption shows its descriptor, and a text field's + descriptor is the text being edited. In other words, the usage for the text + varies from widget to widget, but this API provides a universal and + convenient way to get at it. While not all UI widgets need their + descriptor, many do. } PROCEDURE XPSetWidgetDescriptor( inWidget : XPWidgetID; - inDescriptor : Pchar); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inDescriptor : XPLMString); + cdecl; external XPWIDGETS.DLL; { XPGetWidgetDescriptor - This routine returns the widget's descriptor. Pass in the length of the - buffer you are going to receive the descriptor in. The descriptor will be - null terminated for you. This routine returns the length of the actual - descriptor; if you pass NULL for outDescriptor, you can get the - descriptor's length without getting its text. If the length of the - descriptor exceeds your buffer length, the buffer will not be null - terminated (this routine has 'strncpy' semantics). + This routine returns the widget's descriptor. Pass in the length of the + buffer you are going to receive the descriptor in. The descriptor will be + null terminated for you. This routine returns the length of the actual + descriptor; if you pass NULL for outDescriptor, you can get the + descriptor's length without getting its text. If the length of the + descriptor exceeds your buffer length, the buffer will not be null + terminated (this routine has 'strncpy' semantics). } FUNCTION XPGetWidgetDescriptor( inWidget : XPWidgetID; - outDescriptor : Pchar; - inMaxDescLength : integer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outDescriptor : XPLMString; + inMaxDescLength : Integer) : Integer; + cdecl; external XPWIDGETS.DLL; + + { + XPGetWidgetUnderlyingWindow + + Returns the window (from the XPLMDisplay API) that backs your widget + window. If you have opted in to modern windows, via a call to + XPLMEnableFeature("XPLM_USE_NATIVE_WIDGET_WINDOWS", 1), you can use the + returned window ID for display APIs like XPLMSetWindowPositioningMode(), + allowing you to pop the widget window out into a real OS window, or move it + into VR. + } + FUNCTION XPGetWidgetUnderlyingWindow( + inWidget : XPWidgetID) : XPLMWindowID; + cdecl; external XPWIDGETS.DLL; { XPSetWidgetProperty - This function sets a widget's property. Properties are arbitrary values - associated by a widget by ID. + This function sets a widget's property. Properties are arbitrary values + associated by a widget by ID. } PROCEDURE XPSetWidgetProperty( inWidget : XPWidgetID; inProperty : XPWidgetPropertyID; inValue : intptr_t); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPGetWidgetProperty - This routine returns the value of a widget's property, or 0 if the property - is not defined. If you need to know whether the property is defined, pass - a pointer to an int for inExists; the existence of that property will be - returned in the int. Pass NULL for inExists if you do not need this - information. + This routine returns the value of a widget's property, or 0 if the property + is not defined. If you need to know whether the property is defined, pass a + pointer to an int for inExists; the existence of that property will be + returned in the int. Pass NULL for inExists if you do not need this + information. } FUNCTION XPGetWidgetProperty( inWidget : XPWidgetID; inProperty : XPWidgetPropertyID; - inExists : Pinteger) : intptr_t; { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inExists : PInteger) : intptr_t; { Can be nil } + cdecl; external XPWIDGETS.DLL; {___________________________________________________________________________ * KEYBOARD MANAGEMENT ___________________________________________________________________________} -{ - -} - { XPSetKeyboardFocus - XPSetKeyboardFocus controls which widget will receive keystrokes. Pass the - Widget ID of the widget to get the keys. Note that if the widget does not - care about keystrokes, they will go to the parent widget, and if no widget - cares about them, they go to X-Plane. + Controls which widget will receive keystrokes. Pass the widget ID of the + widget to get the keys. Note that if the widget does not care about + keystrokes, they will go to the parent widget, and if no widget cares about + them, they go to X-Plane. - If you set the keyboard focus to Widget ID 0, X-Plane gets keyboard focus. + If you set the keyboard focus to widget ID 0, X-Plane gets keyboard focus. - This routine returns the widget ID that ended up with keyboard focus, or 0 - for x-plane. + This routine returns the widget ID that ended up with keyboard focus, or 0 + for X-Plane. - Keyboard focus is not changed if the new widget will not accept it. For - setting to x-plane, keyboard focus is always accepted. - - } + Keyboard focus is not changed if the new widget will not accept it. For + setting to X-Plane, keyboard focus is always accepted. + } FUNCTION XPSetKeyboardFocus( inWidget : XPWidgetID) : XPWidgetID; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPLoseKeyboardFocus - This causes the specified widget to lose focus; focus is passed to its - parent, or the next parent that will accept it. This routine does nothing - if this widget does not have focus. + This causes the specified widget to lose focus; focus is passed to its + parent, or the next parent that will accept it. This routine does nothing + if this widget does not have focus. } PROCEDURE XPLoseKeyboardFocus( inWidget : XPWidgetID); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPGetWidgetWithFocus - This routine returns the widget that has keyboard focus, or 0 if X-Plane - has keyboard focus or some other plugin window that does not have widgets - has focus. + This routine returns the widget that has keyboard focus, or 0 if X-Plane + has keyboard focus or some other plugin window that does not have widgets + has focus. } FUNCTION XPGetWidgetWithFocus: XPWidgetID; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; {___________________________________________________________________________ * CREATING CUSTOM WIDGETS ___________________________________________________________________________} -{ - -} - { XPAddWidgetCallback - This function adds a new widget callback to a widget. This widget callback - supercedes any existing ones and will receive messages first; if it does - not handle messages they will go on to be handled by pre-existing widgets. + This function adds a new widget callback to a widget. This widget callback + supercedes any existing ones and will receive messages first; if it does + not handle messages they will go on to be handled by pre-existing widgets. - The widget function will remain on the widget for the life of the widget. - The creation message will be sent to the new callback immediately with the - widget ID, and the destruction message will be sent before the other widget - function receives a destruction message. + The widget function will remain on the widget for the life of the widget. + The creation message will be sent to the new callback immediately with the + widget ID, and the destruction message will be sent before the other widget + function receives a destruction message. - This provides a way to 'subclass' an existing widget. By providing a - second hook that only handles certain widget messages, you can customize or - extend widget behavior. + This provides a way to 'subclass' an existing widget. By providing a second + hook that only handles certain widget messages, you can customize or extend + widget behavior. } PROCEDURE XPAddWidgetCallback( inWidget : XPWidgetID; inNewCallback : XPWidgetFunc_t); -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; { XPGetWidgetClassFunc - Given a widget class, this function returns the callbacks that power that - widget class. + Given a widget class, this function returns the callbacks that power that + widget class. } FUNCTION XPGetWidgetClassFunc( inWidgetClass : XPWidgetClass) : XPWidgetFunc_t; -{$IFDEF DELPHI} - cdecl; external 'XPWIDGETS.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPWIDGETS.DLL; + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMCamera.pas b/XPSDK/Delphi/XPLM/XPLMCamera.pas index 44b121c..ad76fa4 100644 --- a/XPSDK/Delphi/XPLM/XPLMCamera.pas +++ b/XPSDK/Delphi/XPLM/XPLMCamera.pas @@ -1,69 +1,64 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMCamera; INTERFACE { - XPLMCamera - THEORY OF OPERATION The XPLMCamera APIs allow plug-ins to - control the camera angle in X-Plane. This has a number of applications, - including but not limited to: + The XPLMCamera APIs allow plug-ins to control the camera angle in X-Plane. + This has a number of applications, including but not limited to: - - Creating new views (including dynamic/user-controllable views) for the - user. + - Creating new views (including dynamic/user-controllable views) for the + user. + - Creating applications that use X-Plane as a renderer of scenery, + aircrafts, or both. - - Creating applications that use X-Plane as a renderer of scenery, - aircrafts, or both. + The camera is controlled via six parameters: a location in OpenGL + coordinates and pitch, roll and yaw, similar to an airplane's position. + OpenGL coordinate info is described in detail in the XPLMGraphics + documentation; generally you should use the XPLMGraphics routines to + convert from world to local coordinates. The camera's orientation starts + facing level with the ground directly up the negative-Z axis (approximately + north) with the horizon horizontal. It is then rotated clockwise for yaw, + pitched up for positive pitch, and rolled clockwise around the vector it is + looking along for roll. - The camera is controlled via six parameters: a location in OpenGL - coordinates and pitch, roll and yaw, similar to an airplane's position. - OpenGL coordinate info is described in detail in the XPLMGraphics - documentation; generally you should use the XPLMGraphics routines to - convert from world to local coordinates. The camera's orientation starts - facing level with the ground directly up the negative-Z axis - (approximately north) with the horizon horizontal. It is then rotated - clockwise for yaw, pitched up for positive pitch, and rolled clockwise - around the vector it is looking along for roll. + You control the camera either either until the user selects a new view or + permanently (the later being similar to how UDP camera control works). You + control the camera by registering a callback per frame from which you + calculate the new camera positions. This guarantees smooth camera motion. - You control the camera either either until the user selects a new view or - permanently (the later being similar to how UDP camera control works). You - control the camera by registering a callback per frame from which you - calculate the new camera positions. This guarantees smooth camera motion. + Use the XPLMDataAccess APIs to get information like the position of the + aircraft, etc. for complex camera positioning. - Use the XPLMDataAccess APIs to get information like the position of the - aircraft, etc. for complex camera positioning. + Note: if your goal is to move the virtual pilot in the cockpit, this API is + not needed; simply update the datarefs for the pilot's head position. + + For custom exterior cameras, set the camera's mode to an external view + first to get correct sound and 2-d panel behavior. } -USES XPLMDefs; +USES + XPLMDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * CAMERA CONTROL ___________________________________________________________________________} -{ - -} - { XPLMCameraControlDuration - This enumeration states how long you want to retain control of the camera. - You can retain it indefinitely or until the user selects a new view. + This enumeration states how long you want to retain control of the camera. + You can retain it indefinitely or until the user selects a new view. } TYPE XPLMCameraControlDuration = ( - { Control the camera until the user picks a new view. } + { Control the camera until the user picks a new view. } xplm_ControlCameraUntilViewChanges = 1 - { Control the camera until your plugin is disabled or another plugin forcably } - { takes control. } + { Control the camera until your plugin is disabled or another plugin forcably} + { takes control. } ,xplm_ControlCameraForever = 2 ); @@ -72,103 +67,89 @@ TYPE { XPLMCameraPosition_t - This structure contains a full specification of the camera. X, Y, and Z - are the camera's position in OpenGL coordiantes; pitch, roll, and yaw are - rotations from a camera facing flat north in degrees. Positive pitch means - nose up, positive roll means roll right, and positive yaw means yaw right, - all in degrees. Zoom is a zoom factor, with 1.0 meaning normal zoom and 2.0 - magnifying by 2x (objects appear larger). + This structure contains a full specification of the camera. X, Y, and Z are + the camera's position in OpenGL coordiantes; pitch, roll, and yaw are + rotations from a camera facing flat north in degrees. Positive pitch means + nose up, positive roll means roll right, and positive yaw means yaw right, + all in degrees. Zoom is a zoom factor, with 1.0 meaning normal zoom and 2.0 + magnifying by 2x (objects appear larger). } XPLMCameraPosition_t = RECORD - x : single; - y : single; - z : single; - pitch : single; - heading : single; - roll : single; - zoom : single; + x : Single; + y : Single; + z : Single; + pitch : Single; + heading : Single; + roll : Single; + zoom : Single; END; PXPLMCameraPosition_t = ^XPLMCameraPosition_t; { XPLMCameraControl_f - You use an XPLMCameraControl function to provide continuous control over - the camera. You are passed in a structure in which to put the new camera - position; modify it and return 1 to reposition the camera. Return 0 to - surrender control of the camera; camera control will be handled by X-Plane - on this draw loop. The contents of the structure as you are called are - undefined. + You use an XPLMCameraControl function to provide continuous control over + the camera. You are passed in a structure in which to put the new camera + position; modify it and return 1 to reposition the camera. Return 0 to + surrender control of the camera; camera control will be handled by X-Plane + on this draw loop. The contents of the structure as you are called are + undefined. - If X-Plane is taking camera control away from you, this function will be - called with inIsLosingControl set to 1 and ioCameraPosition NULL. + If X-Plane is taking camera control away from you, this function will be + called with inIsLosingControl set to 1 and ioCameraPosition NULL. } XPLMCameraControl_f = FUNCTION( outCameraPosition : PXPLMCameraPosition_t; { Can be nil } - inIsLosingControl : integer; - inRefcon : pointer) : integer; cdecl; + inIsLosingControl : Integer; + inRefcon : pointer) : Integer; cdecl; { XPLMControlCamera - This function repositions the camera on the next drawing cycle. You must - pass a non-null control function. Specify in inHowLong how long you'd like - control (indefinitely or until a key is pressed). + This function repositions the camera on the next drawing cycle. You must + pass a non-null control function. Specify in inHowLong how long you'd like + control (indefinitely or until a new view mode is set by the user). } PROCEDURE XPLMControlCamera( inHowLong : XPLMCameraControlDuration; inControlFunc : XPLMCameraControl_f; inRefcon : pointer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMDontControlCamera - This function stops you from controlling the camera. If you have a camera - control function, it will not be called with an inIsLosingControl flag. - X-Plane will control the camera on the next cycle. + This function stops you from controlling the camera. If you have a camera + control function, it will not be called with an inIsLosingControl flag. + X-Plane will control the camera on the next cycle. - For maximum compatibility you should not use this routine unless you are in - posession of the camera. + For maximum compatibility you should not use this routine unless you are in + posession of the camera. } PROCEDURE XPLMDontControlCamera; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMIsCameraBeingControlled - This routine returns 1 if the camera is being controlled, zero if it is - not. If it is and you pass in a pointer to a camera control duration, the - current control duration will be returned. + This routine returns 1 if the camera is being controlled, zero if it is + not. If it is and you pass in a pointer to a camera control duration, the + current control duration will be returned. } FUNCTION XPLMIsCameraBeingControlled( - outCameraControlDuration: PXPLMCameraControlDuration) : integer; { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outCameraControlDuration: PXPLMCameraControlDuration) : Integer; { Can be nil } + cdecl; external XPLM_DLL; { XPLMReadCameraPosition - This function reads the current camera position. + This function reads the current camera position. } PROCEDURE XPLMReadCameraPosition( outCameraPosition : PXPLMCameraPosition_t); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMDataAccess.pas b/XPSDK/Delphi/XPLM/XPLMDataAccess.pas index e82ded4..1ad210e 100644 --- a/XPSDK/Delphi/XPLM/XPLMDataAccess.pas +++ b/XPSDK/Delphi/XPLM/XPLMDataAccess.pas @@ -1,85 +1,100 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMDataAccess; INTERFACE { - XPLM Data Access API - Theory of Operation + The data access API gives you a generic, flexible, high performance way to + read and write data to and from X-Plane and other plug-ins. For example, + this API allows you to read and set the nav radios, get the plane location, + determine the current effective graphics frame rate, etc. - The data access API gives you a generic, flexible, high performance way to - read and write data to and from X-Plane and other plug-ins. For example, - this API allows you to read and set the nav radios, get the plane location, - determine the current effective graphics frame rate, etc. + The data access APIs are the way that you read and write data from the sim + as well as other plugins. - The data access APIs are the way that you read and write data from the sim - as well as other plugins. + The API works using opaque data references. A data reference is a source of + data; you do not know where it comes from, but once you have it you can + read the data quickly and possibly write it. - The API works using opaque data references. A data reference is a source - of data; you do not know where it comes from, but once you have it you can - read the data quickly and possibly write it. To get a data reference, you - look it up. + Dataref Lookup + -------------- - Data references are identified by verbose string names - (sim/cockpit/radios/nav1_freq_hz). The actual numeric value of the data - reference is implementation defined and is likely to change each time the - simulator is run (or the plugin that provides the datareference is - reloaded). + Data references are identified by verbose, permanent string names; by + convention these names use path separates to form a hierarchy of datarefs, + e.g. (sim/cockpit/radios/nav1_freq_hz). The actual opaque numeric value of + the data reference, as returned by the XPLM API, is implementation defined + and changes each time X-Plane is launched; therefore you need to look up + the dataref by path every time your plugin runs. - The task of looking up a data reference is relatively expensive; look up - your data references once based on verbose strings, and save the opaque - data reference value for the duration of your plugin's operation. Reading - and writing data references is relatively fast (the cost is equivalent to - two function calls through function pointers). + The task of looking up a data reference is relatively expensive; look up + your data references once based on the verbose path strings, and save the + opaque data reference value for the duration of your plugin's operation. + Reading and writing data references is relatively fast (the cost is + equivalent to two function calls through function pointers). - This allows data access to be high performance, while leaving in - abstraction; since data references are opaque and are searched for, the - underlying data access system can be rebuilt. + X-Plane publishes over 4000 datarefs; a complete list may be found in the + reference section of the SDK online documentation (from the SDK home page, + choose Documentation). - A note on typing: you must know the correct data type to read and write. - APIs are provided for reading and writing data in a number of ways. You - can also double check the data type for a data ref. Note that automatic - conversion is not done for you. + Dataref Types + ------------- - A note for plugins sharing data with other plugins: the load order of - plugins is not guaranteed. To make sure that every plugin publishing data - has published their data references before other plugins try to subscribe, - publish your data references in your start routine but resolve them the - first time your 'enable' routine is called, or the first time they are - needed in code. + A note on typing: you must know the correct data type to read and write. + APIs are provided for reading and writing data in a number of ways. You can + also double check the data type for a data ref. Automatic type conversion + is not done for you. - X-Plane publishes well over 1000 datarefs; a complete list may be found in - the reference section of the SDK online documentation (from the SDK home - page, choose Documentation). + Dataref types are a set, e.g. a dataref can be more than one type. When + this happens, you can choose which API you want to use to read. For + example, it is not uncommon for a dataref to be of type float and double. + This means you can use either XPLMGetDatad or XPLMGetDataf to read it. + + Creating New Datarefs + --------------------- + + X-Plane provides datarefs that come with the sim, but plugins can also + create their own datarefs. A plugin creates a dataref by registering + function callbacks to read and write the dataref. The XPLM will call your + plugin each time some other plugin (or X-Plane) tries to read or write the + dataref. You must provide a read (and optional write) callback for each + data type you support. + + A note for plugins sharing data with other plugins: the load order of + plugins is not guaranteed. To make sure that every plugin publishing data + has published their data references before other plugins try to subscribe, + publish your data references in your start routine but resolve them the + first time your 'enable' routine is called, or the first time they are + needed in code. + + When a plugin that created a dataref is unloaded, it becomes "orphaned". + The dataref handle continues to be usable, but the dataref is not writable, + and reading it will always return 0 (or 0 items for arrays). If the plugin + is reloaded and re-registers the dataref, the handle becomes un-orphaned + and works again. } -USES XPLMDefs; +USES + XPLMDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * READING AND WRITING DATA ___________________________________________________________________________} { - These routines allow you to access a wide variety of data from within - x-plane and modify some of it. + These routines allow you to access data from within X-Plane and sometimes + modify it. } - TYPE { XPLMDataRef - A data ref is an opaque handle to data provided by the simulator or another - plugin. It uniquely identifies one variable (or array of variables) over - the lifetime of your plugin. You never hard code these values; you always - get them from XPLMFindDataRef. + A data ref is an opaque handle to data provided by the simulator or another + plugin. It uniquely identifies one variable (or array of variables) over + the lifetime of your plugin. You never hard code these values; you always + get them from XPLMFindDataRef. } XPLMDataRef = pointer; PXPLMDataRef = ^XPLMDataRef; @@ -87,33 +102,35 @@ TYPE { XPLMDataTypeID - This is an enumeration that defines the type of the data behind a data - reference. This allows you to sanity check that the data type matches what - you expect. But for the most part, you will know the type of data you are - expecting from the online documentation. + This is an enumeration that defines the type of the data behind a data + reference. This allows you to sanity check that the data type matches what + you expect. But for the most part, you will know the type of data you are + expecting from the online documentation. - Data types each take a bit field, so sets of data types may be formed. + Data types each take a bit field; it is legal to have a single dataref be + more than one type of data. Whe this happens, you can pick any matching + get/set API. } XPLMDataTypeID = ( - { Data of a type the current XPLM doesn't do. } + { Data of a type the current XPLM doesn't do. } xplmType_Unknown = 0 - { A single 4-byte integer, native endian. } + { A single 4-byte integer, native endian. } ,xplmType_Int = 1 - { A single 4-byte float, native endian. } + { A single 4-byte float, native endian. } ,xplmType_Float = 2 - { A single 8-byte double, native endian. } + { A single 8-byte double, native endian. } ,xplmType_Double = 4 - { An array of 4-byte floats, native endian. } + { An array of 4-byte floats, native endian. } ,xplmType_FloatArray = 8 - { An array of 4-byte integers, native endian. } + { An array of 4-byte integers, native endian. } ,xplmType_IntArray = 16 - { A variable block of data. } + { A variable block of data. } ,xplmType_Data = 32 ); @@ -122,502 +139,431 @@ TYPE { XPLMFindDataRef - Given a c-style string that names the data ref, this routine looks up the - actual opaque XPLMDataRef that you use to read and write the data. The - string names for datarefs are published on the x-plane SDK web site. + Given a c-style string that names the data ref, this routine looks up the + actual opaque XPLMDataRef that you use to read and write the data. The + string names for datarefs are published on the X-Plane SDK web site. - This function returns NULL if the data ref cannot be found. + This function returns NULL if the data ref cannot be found. - NOTE: this function is relatively expensive; save the XPLMDataRef this - function returns for future use. Do not look up your data ref by string - every time you need to read or write it. + NOTE: this function is relatively expensive; save the XPLMDataRef this + function returns for future use. Do not look up your data ref by string + every time you need to read or write it. } FUNCTION XPLMFindDataRef( - inDataRefName : Pchar) : XPLMDataRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inDataRefName : XPLMString) : XPLMDataRef; + cdecl; external XPLM_DLL; { XPLMCanWriteDataRef - Given a data ref, this routine returns true if you can successfully set - the data, false otherwise. Some datarefs are read-only. + Given a data ref, this routine returns true if you can successfully set the + data, false otherwise. Some datarefs are read-only. + + NOTE: even if a dataref is marked writable, it may not act writable. This + can happen for datarefs that X-Plane writes to on every frame of + simulation. In some cases, the dataref is writable but you have to set a + separate "override" dataref to 1 to stop X-Plane from writing it. } FUNCTION XPLMCanWriteDataRef( - inDataRef : XPLMDataRef) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inDataRef : XPLMDataRef) : Integer; + cdecl; external XPLM_DLL; { XPLMIsDataRefGood - WARNING: This function is deprecated and should not be used. Datarefs are - valid until plugins are reloaded or the sim quits. Plugins sharing - datarefs should support these semantics by not unregistering datarefs - during operation. (You should however unregister datarefs when your plugin - is unloaded, as part of general resource cleanup.) + This function returns true if the passed in handle is a valid dataref that + is not orphaned. - This function returns whether a data ref is still valid. If it returns - false, you should refind the data ref from its original string. Calling an - accessor function on a bad data ref will return a default value, typically - 0 or 0-length data. + Note: there is normally no need to call this function; datarefs returned by + XPLMFindDataRef remain valid (but possibly orphaned) unless there is a + complete plugin reload (in which case your plugin is reloaded anyway). + Orphaned datarefs can be safely read and return 0. Therefore you never need + to call XPLMIsDataRefGood to 'check' the safety of a dataref. + (XPLMIsDatarefGood performs some slow checking of the handle validity, so + it has a perormance cost.) } FUNCTION XPLMIsDataRefGood( - inDataRef : XPLMDataRef) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inDataRef : XPLMDataRef) : Integer; + cdecl; external XPLM_DLL; { XPLMGetDataRefTypes - This routine returns the types of the data ref for accessor use. If a data - ref is available in multiple data types, they will all be returned. + This routine returns the types of the data ref for accessor use. If a data + ref is available in multiple data types, the bit-wise OR of these types + will be returned. } FUNCTION XPLMGetDataRefTypes( inDataRef : XPLMDataRef) : XPLMDataTypeID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; {___________________________________________________________________________ * DATA ACCESSORS ___________________________________________________________________________} { - These routines read and write the data references. For each supported data - type there is a reader and a writer. + These routines read and write the data references. For each supported data + type there is a reader and a writer. - If the data ref is invalid or the plugin that provides it is disabled or - there is a type mismatch, the functions that read data will return 0 as a - default value or not modify the passed in memory. The plugins that write - data will not write under these circumstances or if the data ref is - read-only. NOTE: to keep the overhead of reading datarefs low, these - routines do not do full validation of a dataref; passing a junk value for - a dataref can result in crashing the sim. + If the data ref is orphaned or the plugin that provides it is disabled or + there is a type mismatch, the functions that read data will return 0 as a + default value or not modify the passed in memory. The plugins that write + data will not write under these circumstances or if the data ref is + read-only. - For array-style datarefs, you specify the number of items to read/write and - the offset into the array; the actual number of items read or written is - returned. This may be less to prevent an array-out-of-bounds error. + NOTE: to keep the overhead of reading datarefs low, these routines do not + do full validation of a dataref; passing a junk value for a dataref can + result in crashing the sim. The get/set APIs do check for NULL. + + For array-style datarefs, you specify the number of items to read/write and + the offset into the array; the actual number of items read or written is + returned. This may be less to prevent an array-out-of-bounds error. } - { XPLMGetDatai - Read an integer data ref and return its value. The return value is the - dataref value or 0 if the dataref is invalid/NULL or the plugin is - disabled. + Read an integer data ref and return its value. The return value is the + dataref value or 0 if the dataref is NULL or the plugin is disabled. } FUNCTION XPLMGetDatai( - inDataRef : XPLMDataRef) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inDataRef : XPLMDataRef) : Integer; + cdecl; external XPLM_DLL; { XPLMSetDatai - Write a new value to an integer data ref. This routine is a no-op if the - plugin publishing the dataref is disabled, the dataref is invalid, or the - dataref is not writable. + Write a new value to an integer data ref. This routine is a no-op if the + plugin publishing the dataref is disabled, the dataref is NULL, or the + dataref is not writable. } PROCEDURE XPLMSetDatai( inDataRef : XPLMDataRef; - inValue : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inValue : Integer); + cdecl; external XPLM_DLL; { XPLMGetDataf - Read a single precision floating point dataref and return its value. The - return value is the dataref value or 0.0 if the dataref is invalid/NULL or - the plugin is disabled. + Read a single precision floating point dataref and return its value. The + return value is the dataref value or 0.0 if the dataref is NULL or the + plugin is disabled. } FUNCTION XPLMGetDataf( - inDataRef : XPLMDataRef) : single; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inDataRef : XPLMDataRef) : Single; + cdecl; external XPLM_DLL; { XPLMSetDataf - Write a new value to a single precision floating point data ref. This - routine is a no-op if the plugin publishing the dataref is disabled, the - dataref is invalid, or the dataref is not writable. + Write a new value to a single precision floating point data ref. This + routine is a no-op if the plugin publishing the dataref is disabled, the + dataref is NULL, or the dataref is not writable. } PROCEDURE XPLMSetDataf( inDataRef : XPLMDataRef; - inValue : single); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inValue : Single); + cdecl; external XPLM_DLL; { XPLMGetDatad - Read a double precision floating point dataref and return its value. The - return value is the dataref value or 0.0 if the dataref is invalid/NULL or - the plugin is disabled. + Read a double precision floating point dataref and return its value. The + return value is the dataref value or 0.0 if the dataref is NULL or the + plugin is disabled. } FUNCTION XPLMGetDatad( - inDataRef : XPLMDataRef) : real; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inDataRef : XPLMDataRef) : Real; + cdecl; external XPLM_DLL; { XPLMSetDatad - Write a new value to a double precision floating point data ref. This - routine is a no-op if the plugin publishing the dataref is disabled, the - dataref is invalid, or the dataref is not writable. + Write a new value to a double precision floating point data ref. This + routine is a no-op if the plugin publishing the dataref is disabled, the + dataref is NULL, or the dataref is not writable. } PROCEDURE XPLMSetDatad( inDataRef : XPLMDataRef; - inValue : real); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inValue : Real); + cdecl; external XPLM_DLL; { XPLMGetDatavi - Read a part of an integer array dataref. If you pass NULL for outVaules, - the routine will return the size of the array, ignoring inOffset and inMax. + Read a part of an integer array dataref. If you pass NULL for outValues, + the routine will return the size of the array, ignoring inOffset and inMax. + If outValues is not NULL, then up to inMax values are copied from the + dataref into outValues, starting at inOffset in the dataref. If inMax + + inOffset is larger than the size of the dataref, less than inMax values + will be copied. The number of values copied is returned. - If outValues is not NULL, then up to inMax values are copied from the - dataref into outValues, starting at inOffset in the dataref. If inMax + - inOffset is larger than the size of the dataref, less than inMax values - will be copied. The number of values copied is returned. - - Note: the semantics of array datarefs are entirely implemented by the - plugin (or X-Plane) that provides the dataref, not the SDK itself; the - above description is how these datarefs are intended to work, but a rogue - plugin may have different behavior. + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. } FUNCTION XPLMGetDatavi( inDataRef : XPLMDataRef; - outValues : Pinteger; { Can be nil } - inOffset : integer; - inMax : integer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outValues : PInteger; { Can be nil } + inOffset : Integer; + inMax : Integer) : Integer; + cdecl; external XPLM_DLL; { XPLMSetDatavi - Write part or all of an integer array dataref. The values passed by - inValues are written into the dataref starting at inOffset. Up to inCount - values are written; however if the values would write "off the end" of the - dataref array, then fewer values are written. + Write part or all of an integer array dataref. The values passed by + inValues are written into the dataref starting at inOffset. Up to inCount + values are written; however if the values would write "off the end" of the + dataref array, then fewer values are written. - Note: the semantics of array datarefs are entirely implemented by the - plugin (or X-Plane) that provides the dataref, not the SDK itself; the - above description is how these datarefs are intended to work, but a rogue - plugin may have different behavior. + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. } PROCEDURE XPLMSetDatavi( inDataRef : XPLMDataRef; - inValues : Pinteger; - inoffset : integer; - inCount : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inValues : PInteger; + inoffset : Integer; + inCount : Integer); + cdecl; external XPLM_DLL; { XPLMGetDatavf - Read a part of a single precision floating point array dataref. If you - pass NULL for outVaules, the routine will return the size of the array, - ignoring inOffset and inMax. + Read a part of a single precision floating point array dataref. If you pass + NULL for outVaules, the routine will return the size of the array, ignoring + inOffset and inMax. - If outValues is not NULL, then up to inMax values are copied from the - dataref into outValues, starting at inOffset in the dataref. If inMax + - inOffset is larger than the size of the dataref, less than inMax values - will be copied. The number of values copied is returned. + If outValues is not NULL, then up to inMax values are copied from the + dataref into outValues, starting at inOffset in the dataref. If inMax + + inOffset is larger than the size of the dataref, less than inMax values + will be copied. The number of values copied is returned. - Note: the semantics of array datarefs are entirely implemented by the - plugin (or X-Plane) that provides the dataref, not the SDK itself; the - above description is how these datarefs are intended to work, but a rogue - plugin may have different behavior. + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. } FUNCTION XPLMGetDatavf( inDataRef : XPLMDataRef; - outValues : Psingle; { Can be nil } - inOffset : integer; - inMax : integer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outValues : PSingle; { Can be nil } + inOffset : Integer; + inMax : Integer) : Integer; + cdecl; external XPLM_DLL; { XPLMSetDatavf - Write part or all of a single precision floating point array dataref. The - values passed by inValues are written into the dataref starting at - inOffset. Up to inCount values are written; however if the values would - write "off the end" of the dataref array, then fewer values are written. + Write part or all of a single precision floating point array dataref. The + values passed by inValues are written into the dataref starting at + inOffset. Up to inCount values are written; however if the values would + write "off the end" of the dataref array, then fewer values are written. - Note: the semantics of array datarefs are entirely implemented by the - plugin (or X-Plane) that provides the dataref, not the SDK itself; the - above description is how these datarefs are intended to work, but a rogue - plugin may have different behavior. + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. } PROCEDURE XPLMSetDatavf( inDataRef : XPLMDataRef; - inValues : Psingle; - inoffset : integer; - inCount : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inValues : PSingle; + inoffset : Integer; + inCount : Integer); + cdecl; external XPLM_DLL; { XPLMGetDatab - Read a part of a byte array dataref. If you pass NULL for outVaules, the - routine will return the size of the array, ignoring inOffset and inMax. + Read a part of a byte array dataref. If you pass NULL for outVaules, the + routine will return the size of the array, ignoring inOffset and inMax. - If outValues is not NULL, then up to inMax values are copied from the - dataref into outValues, starting at inOffset in the dataref. If inMax + - inOffset is larger than the size of the dataref, less than inMax values - will be copied. The number of values copied is returned. + If outValues is not NULL, then up to inMax values are copied from the + dataref into outValues, starting at inOffset in the dataref. If inMax + + inOffset is larger than the size of the dataref, less than inMax values + will be copied. The number of values copied is returned. - Note: the semantics of array datarefs are entirely implemented by the - plugin (or X-Plane) that provides the dataref, not the SDK itself; the - above description is how these datarefs are intended to work, but a rogue - plugin may have different behavior. + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. } FUNCTION XPLMGetDatab( inDataRef : XPLMDataRef; outValue : pointer; { Can be nil } - inOffset : integer; - inMaxBytes : integer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inOffset : Integer; + inMaxBytes : Integer) : Integer; + cdecl; external XPLM_DLL; { XPLMSetDatab - Write part or all of a byte array dataref. The values passed by inValues - are written into the dataref starting at inOffset. Up to inCount values - are written; however if the values would write "off the end" of the dataref - array, then fewer values are written. + Write part or all of a byte array dataref. The values passed by inValues + are written into the dataref starting at inOffset. Up to inCount values are + written; however if the values would write "off the end" of the dataref + array, then fewer values are written. - Note: the semantics of array datarefs are entirely implemented by the - plugin (or X-Plane) that provides the dataref, not the SDK itself; the - above description is how these datarefs are intended to work, but a rogue - plugin may have different behavior. + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. } PROCEDURE XPLMSetDatab( inDataRef : XPLMDataRef; inValue : pointer; - inOffset : integer; - inLength : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inOffset : Integer; + inLength : Integer); + cdecl; external XPLM_DLL; {___________________________________________________________________________ - * PUBLISHING YOUR PLUGINS DATA + * PUBLISHING YOUR PLUGIN'S DATA ___________________________________________________________________________} { - These functions allow you to create data references that other plug-ins can - access via the above data access APIs. Data references published by other - plugins operate the same as ones published by x-plane in all manners except - that your data reference will not be available to other plugins if/when - your plugin is disabled. + These functions allow you to create data references that other plug-ins and + X-Plane can access via the above data access APIs. Data references + published by other plugins operate the same as ones published by X-Plane in + all manners except that your data reference will not be available to other + plugins if/when your plugin is disabled. - You share data by registering data provider callback functions. When a - plug-in requests your data, these callbacks are then called. You provide - one callback to return the value when a plugin 'reads' it and another to - change the value when a plugin 'writes' it. + You share data by registering data provider callback functions. When a + plug-in requests your data, these callbacks are then called. You provide + one callback to return the value when a plugin 'reads' it and another to + change the value when a plugin 'writes' it. - Important: you must pick a prefix for your datarefs other than "sim/" - - this prefix is reserved for X-Plane. The X-Plane SDK website contains a - registry where authors can select a unique first word for dataref names, to - prevent dataref collisions between plugins. + Important: you must pick a prefix for your datarefs other than "sim/" - + this prefix is reserved for X-Plane. The X-Plane SDK website contains a + registry where authors can select a unique first word for dataref names, to + prevent dataref collisions between plugins. } - { XPLMGetDatai_f - Data provider function pointers. + Data provider function pointers. - These define the function pointers you provide to get or set data. Note - that you are passed a generic pointer for each one. This is the same - pointer you pass in your register routine; you can use it to find global - variables, etc. + These define the function pointers you provide to get or set data. Note + that you are passed a generic pointer for each one. This is the same + pointer you pass in your register routine; you can use it to locate plugin + variables, etc. - The semantics of your callbacks are the same as the dataref accessor above - - basically routines like XPLMGetDatai are just pass-throughs from a caller - to your plugin. Be particularly mindful in implementing array dataref - read-write accessors; you are responsible for avoiding overruns, supporting - offset read/writes, and handling a read with a NULL buffer. + The semantics of your callbacks are the same as the dataref accessor above + - basically routines like XPLMGetDatai are just pass-throughs from a caller + to your plugin. Be particularly mindful in implementing array dataref + read-write accessors; you are responsible for avoiding overruns, supporting + offset read/writes, and handling a read with a NULL buffer. } TYPE XPLMGetDatai_f = FUNCTION( - inRefcon : pointer) : integer; cdecl; + inRefcon : pointer) : Integer; cdecl; { - XPLMSetDatai_f - + XPLMSetDatai_f } XPLMSetDatai_f = PROCEDURE( inRefcon : pointer; - inValue : integer); cdecl; + inValue : Integer); cdecl; { - XPLMGetDataf_f - + XPLMGetDataf_f } XPLMGetDataf_f = FUNCTION( - inRefcon : pointer) : single; cdecl; + inRefcon : pointer) : Single; cdecl; { - XPLMSetDataf_f - + XPLMSetDataf_f } XPLMSetDataf_f = PROCEDURE( inRefcon : pointer; - inValue : single); cdecl; + inValue : Single); cdecl; { - XPLMGetDatad_f - + XPLMGetDatad_f } XPLMGetDatad_f = FUNCTION( - inRefcon : pointer) : real; cdecl; + inRefcon : pointer) : Real; cdecl; { - XPLMSetDatad_f - + XPLMSetDatad_f } XPLMSetDatad_f = PROCEDURE( inRefcon : pointer; - inValue : real); cdecl; + inValue : Real); cdecl; { - XPLMGetDatavi_f - + XPLMGetDatavi_f } XPLMGetDatavi_f = FUNCTION( inRefcon : pointer; - outValues : Pinteger; { Can be nil } - inOffset : integer; - inMax : integer) : integer; cdecl; + outValues : PInteger; { Can be nil } + inOffset : Integer; + inMax : Integer) : Integer; cdecl; { - XPLMSetDatavi_f - + XPLMSetDatavi_f } XPLMSetDatavi_f = PROCEDURE( inRefcon : pointer; - inValues : Pinteger; - inOffset : integer; - inCount : integer); cdecl; + inValues : PInteger; + inOffset : Integer; + inCount : Integer); cdecl; { - XPLMGetDatavf_f - + XPLMGetDatavf_f } XPLMGetDatavf_f = FUNCTION( inRefcon : pointer; - outValues : Psingle; { Can be nil } - inOffset : integer; - inMax : integer) : integer; cdecl; + outValues : PSingle; { Can be nil } + inOffset : Integer; + inMax : Integer) : Integer; cdecl; { - XPLMSetDatavf_f - + XPLMSetDatavf_f } XPLMSetDatavf_f = PROCEDURE( inRefcon : pointer; - inValues : Psingle; - inOffset : integer; - inCount : integer); cdecl; + inValues : PSingle; + inOffset : Integer; + inCount : Integer); cdecl; { - XPLMGetDatab_f - + XPLMGetDatab_f } XPLMGetDatab_f = FUNCTION( inRefcon : pointer; outValue : pointer; { Can be nil } - inOffset : integer; - inMaxLength : integer) : integer; cdecl; + inOffset : Integer; + inMaxLength : Integer) : Integer; cdecl; { - XPLMSetDatab_f - + XPLMSetDatab_f } XPLMSetDatab_f = PROCEDURE( inRefcon : pointer; inValue : pointer; - inOffset : integer; - inLength : integer); cdecl; + inOffset : Integer; + inLength : Integer); cdecl; { XPLMRegisterDataAccessor - This routine creates a new item of data that can be read and written. Pass - in the data's full name for searching, the type(s) of the data for - accessing, and whether the data can be written to. For each data type you - support, pass in a read accessor function and a write accessor function if - necessary. Pass NULL for data types you do not support or write accessors - if you are read-only. + This routine creates a new item of data that can be read and written. Pass + in the data's full name for searching, the type(s) of the data for + accessing, and whether the data can be written to. For each data type you + support, pass in a read accessor function and a write accessor function if + necessary. Pass NULL for data types you do not support or write accessors + if you are read-only. - You are returned a data ref for the new item of data created. You can use - this data ref to unregister your data later or read or write from it. + You are returned a data ref for the new item of data created. You can use + this data ref to unregister your data later or read or write from it. } FUNCTION XPLMRegisterDataAccessor( - inDataName : Pchar; + inDataName : XPLMString; inDataType : XPLMDataTypeID; - inIsWritable : integer; + inIsWritable : Integer; inReadInt : XPLMGetDatai_f; inWriteInt : XPLMSetDatai_f; inReadFloat : XPLMGetDataf_f; @@ -632,80 +578,66 @@ TYPE inWriteData : XPLMSetDatab_f; inReadRefcon : pointer; inWriteRefcon : pointer) : XPLMDataRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMUnregisterDataAccessor - Use this routine to unregister any data accessors you may have registered. - You unregister a data ref by the XPLMDataRef you get back from - registration. Once you unregister a data ref, your function pointer will - not be called anymore. - - For maximum compatibility, do not unregister your data accessors until - final shutdown (when your XPluginStop routine is called). This allows - other plugins to find your data reference once and use it for their entire - time of operation. + Use this routine to unregister any data accessors you may have registered. + You unregister a data ref by the XPLMDataRef you get back from + registration. Once you unregister a data ref, your function pointer will + not be called anymore. } PROCEDURE XPLMUnregisterDataAccessor( inDataRef : XPLMDataRef); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; {___________________________________________________________________________ * SHARING DATA BETWEEN MULTIPLE PLUGINS ___________________________________________________________________________} { - The data reference registration APIs from the previous section allow a - plugin to publish data in a one-owner manner; the plugin that publishes the - data reference owns the real memory that the data ref uses. This is - satisfactory for most cases, but there are also cases where plugnis need to - share actual data. + The data reference registration APIs from the previous section allow a + plugin to publish data in a one-owner manner; the plugin that publishes the + data reference owns the real memory that the data ref uses. This is + satisfactory for most cases, but there are also cases where plugnis need to + share actual data. - With a shared data reference, no one plugin owns the actual memory for the - data reference; the plugin SDK allocates that for you. When the first - plugin asks to 'share' the data, the memory is allocated. When the data is - changed, every plugin that is sharing the data is notified. + With a shared data reference, no one plugin owns the actual memory for the + data reference; the plugin SDK allocates that for you. When the first + plugin asks to 'share' the data, the memory is allocated. When the data is + changed, every plugin that is sharing the data is notified. - Shared data references differ from the 'owned' data references from the - previous section in a few ways: + Shared data references differ from the 'owned' data references from the + previous section in a few ways: - - With shared data references, any plugin can create the data reference; - with owned plugins one plugin must create the data reference and others - subscribe. (This can be a problem if you don't know which set of plugins - will be present). + * With shared data references, any plugin can create the data reference; + with owned plugins one plugin must create the data reference and others + subscribe. (This can be a problem if you don't know which set of plugins + will be present). - - With shared data references, every plugin that is sharing the data is - notified when the data is changed. With owned data references, only the - one owner is notified when the data is changed. + * With shared data references, every plugin that is sharing the data is + notified when the data is changed. With owned data references, only the + one owner is notified when the data is changed. - - With shared data references, you cannot access the physical memory of the - data reference; you must use the XPLMGet... and XPLMSet... APIs. With an - owned data reference, the one owning data reference can manipulate the - data reference's memory in any way it sees fit. + * With shared data references, you cannot access the physical memory of the + data reference; you must use the XPLMGet... and XPLMSet... APIs. With an + owned data reference, the one owning data reference can manipulate the + data reference's memory in any way it sees fit. - Shared data references solve two problems: if you need to have a data - reference used by several plugins but do not know which plugins will be - installed, or if all plugins sharing data need to be notified when that - data is changed, use shared data references. + Shared data references solve two problems: if you need to have a data + reference used by several plugins but do not know which plugins will be + installed, or if all plugins sharing data need to be notified when that + data is changed, use shared data references. } - { XPLMDataChanged_f - An XPLMDataChanged_f is a callback that the XPLM calls whenever any other - plug-in modifies shared data. A refcon you provide is passed back to help - identify which data is being changed. In response, you may want to call one - of the XPLMGetDataxxx routines to find the new value of the data. + An XPLMDataChanged_f is a callback that the XPLM calls whenever any other + plug-in modifies shared data. A refcon you provide is passed back to help + identify which data is being changed. In response, you may want to call one + of the XPLMGetDataxxx routines to find the new value of the data. } TYPE XPLMDataChanged_f = PROCEDURE( @@ -714,51 +646,45 @@ TYPE { XPLMShareData - This routine connects a plug-in to shared data, creating the shared data if - necessary. inDataName is a standard path for the data ref, and inDataType - specifies the type. This function will create the data if it does not - exist. If the data already exists but the type does not match, an error is - returned, so it is important that plug-in authors collaborate to establish - public standards for shared data. + This routine connects a plug-in to shared data, creating the shared data if + necessary. inDataName is a standard path for the data ref, and inDataType + specifies the type. This function will create the data if it does not + exist. If the data already exists but the type does not match, an error is + returned, so it is important that plug-in authors collaborate to establish + public standards for shared data. - If a notificationFunc is passed in and is not NULL, that notification - function will be called whenever the data is modified. The notification - refcon will be passed to it. This allows your plug-in to know which shared - data was changed if multiple shared data are handled by one callback, or if - the plug-in does not use global variables. + If a notificationFunc is passed in and is not NULL, that notification + function will be called whenever the data is modified. The notification + refcon will be passed to it. This allows your plug-in to know which shared + data was changed if multiple shared data are handled by one callback, or if + the plug-in does not use global variables. - A one is returned for successfully creating or finding the shared data; a - zero if the data already exists but is of the wrong type. + A one is returned for successfully creating or finding the shared data; a + zero if the data already exists but is of the wrong type. } FUNCTION XPLMShareData( - inDataName : Pchar; + inDataName : XPLMString; inDataType : XPLMDataTypeID; inNotificationFunc : XPLMDataChanged_f; - inNotificationRefcon: pointer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inNotificationRefcon: pointer) : Integer; + cdecl; external XPLM_DLL; { XPLMUnshareData - This routine removes your notification function for shared data. Call it - when done with the data to stop receiving change notifications. Arguments - must match XPLMShareData. The actual memory will not necessarily be freed, - since other plug-ins could be using it. + This routine removes your notification function for shared data. Call it + when done with the data to stop receiving change notifications. Arguments + must match XPLMShareData. The actual memory will not necessarily be freed, + since other plug-ins could be using it. } FUNCTION XPLMUnshareData( - inDataName : Pchar; + inDataName : XPLMString; inDataType : XPLMDataTypeID; inNotificationFunc : XPLMDataChanged_f; - inNotificationRefcon: pointer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inNotificationRefcon: pointer) : Integer; + cdecl; external XPLM_DLL; + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMDefs.pas b/XPSDK/Delphi/XPLM/XPLMDefs.pas index 57ffba1..b614085 100644 --- a/XPSDK/Delphi/XPLM/XPLMDefs.pas +++ b/XPSDK/Delphi/XPLM/XPLMDefs.pas @@ -1,28 +1,22 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMDefs; INTERFACE { - This file is contains the cross-platform and basic definitions for the - X-Plane SDK. + This file is contains the cross-platform and basic definitions for the + X-Plane SDK. - The preprocessor macros APL and IBM must be defined to specify the - compilation target; define APL to 1 and IBM 0 to compile on Macintosh and - APL to 0 and IBM to 1 for Windows. You must specify these macro definitions - before including XPLMDefs.h or any other XPLM headers. You can do this - using the -D command line option or a preprocessor header. + The preprocessor macros APL and IBM must be defined to specify the + compilation target; define APL to 1 and IBM 0 to compile on Macintosh and + APL to 0 and IBM to 1 for Windows. You must specify these macro definitions + before including XPLMDefs.h or any other XPLM headers. You can do this + using the -D command line option or a preprocessor header. } {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {$IFDEF LINUX} {$DEFINE KYLIX} {$ENDIF} @@ -41,86 +35,85 @@ TYPE * DLL Definitions ___________________________________________________________________________} { - These definitions control the importing and exporting of functions within - the DLL. + These definitions control the importing and exporting of functions within + the DLL. - You can prefix your five required callbacks with the PLUGIN_API macro to - declare them as exported C functions. The XPLM_API macro identifies - functions that are provided to you via the plugin SDK. (Link against - XPLM.lib to use these functions.) + You can prefix your five required callbacks with the PLUGIN_API macro to + declare them as exported C functions. The XPLM_API macro identifies + functions that are provided to you via the plugin SDK. (Link against + XPLM.lib to use these functions.) } - {___________________________________________________________________________ * GLOBAL DEFINITIONS ___________________________________________________________________________} { - These definitions are used in all parts of the SDK. + These definitions are used in all parts of the SDK. } - TYPE { XPLMPluginID - Each plug-in is identified by a unique integer ID. This ID can be used to - disable or enable a plug-in, or discover what plug-in is 'running' at the - time. A plug-in ID is unique within the currently running instance of - X-Plane unless plug-ins are reloaded. Plug-ins may receive a different - unique ID each time they are loaded. + Each plug-in is identified by a unique integer ID. This ID can be used to + disable or enable a plug-in, or discover what plug-in is 'running' at the + time. A plug-in ID is unique within the currently running instance of + X-Plane unless plug-ins are reloaded. Plug-ins may receive a different + unique ID each time they are loaded. This includes the unloading and + reloading of plugins that are part of the user's aircraft. - For persistent identification of plug-ins, use XPLMFindPluginBySignature in - XPLMUtiltiies.h + For persistent identification of plug-ins, use XPLMFindPluginBySignature in + XPLMUtiltiies.h - -1 indicates no plug-in. + -1 indicates no plug-in. } - XPLMPluginID = integer; + XPLMPluginID = Integer; PXPLMPluginID = ^XPLMPluginID; CONST - { No plugin. } + { No plugin. } XPLM_NO_PLUGIN_ID = (-1); - { X-Plane itself } + { X-Plane itself } XPLM_PLUGIN_XPLANE = (0); - { The current XPLM revision is 2.10 (210). } - kXPLM_Version = (210); + { The current XPLM revision is 4.00 (400). } + kXPLM_Version = (400); { XPLMKeyFlags - These bitfields define modifier keys in a platform independent way. When a - key is pressed, a series of messages are sent to your plugin. The down - flag is set in the first of these messages, and the up flag in the last. - While the key is held down, messages are sent with neither to indicate that - the key is being held down as a repeated character. + These bitfields define modifier keys in a platform independent way. When a + key is pressed, a series of messages are sent to your plugin. The down + flag is set in the first of these messages, and the up flag in the last. + While the key is held down, messages are sent with neither to indicate that + the key is being held down as a repeated character. - The control flag is mapped to the control flag on Macintosh and PC. - Generally X-Plane uses the control key and not the command key on - Macintosh, providing a consistent interface across platforms that does not - necessarily match the Macintosh user interface guidelines. There is not - yet a way for plugins to access the Macintosh control keys without using - #ifdefed code. + The control flag is mapped to the control flag on Macintosh and PC. + Generally X-Plane uses the control key and not the command key on + Macintosh, providing a consistent interface across platforms that does not + necessarily match the Macintosh user interface guidelines. There is not + yet a way for plugins to access the Macintosh control keys without using + #ifdefed code. } TYPE XPLMKeyFlags = ( - { The shift key is down } + { The shift key is down } xplm_ShiftFlag = 1 - { The option or alt key is down } + { The option or alt key is down } ,xplm_OptionAltFlag = 2 - { The control key is down* } + { The control key is down* } ,xplm_ControlFlag = 4 - { The key is being pressed down } + { The key is being pressed down } ,xplm_DownFlag = 8 - { The key is being released } + { The key is being released } ,xplm_UpFlag = 16 ); @@ -130,19 +123,19 @@ TYPE * ASCII CONTROL KEY CODES ___________________________________________________________________________} { - These definitions define how various control keys are mapped to ASCII key - codes. Not all key presses generate an ASCII value, so plugin code should - be prepared to see null characters come from the keyboard...this usually - represents a key stroke that has no equivalent ASCII, like a page-down - press. Use virtual key codes to find these key strokes. ASCII key codes - take into account modifier keys; shift keys will affect capitals and - punctuation; control key combinations may have no vaild ASCII and produce - NULL. To detect control-key combinations, use virtual key codes, not ASCII - keys. + These definitions define how various control keys are mapped to ASCII key + codes. Not all key presses generate an ASCII value, so plugin code should + be prepared to see null characters come from the keyboard...this usually + represents a key stroke that has no equivalent ASCII, like a page-down + press. Use virtual key codes to find these key strokes. + + ASCII key codes take into account modifier keys; shift keys will affect + capitals and punctuation; control key combinations may have no vaild ASCII + and produce NULL. To detect control-key combinations, use virtual key + codes, not ASCII keys. } - CONST XPLM_KEY_RETURN = 13; @@ -186,35 +179,32 @@ CONST * VIRTUAL KEY CODES ___________________________________________________________________________} { - These are cross-platform defines for every distinct keyboard press on the - computer. Every physical key on the keyboard has a virtual key code. So - the "two" key on the top row of the main keyboard has a different code - from the "two" key on the numeric key pad. But the 'w' and 'W' character - are indistinguishable by virtual key code because they are the same - physical key (one with and one without the shift key). + These are cross-platform defines for every distinct keyboard press on the + computer. Every physical key on the keyboard has a virtual key code. So + the "two" key on the top row of the main keyboard has a different code from + the "two" key on the numeric key pad. But the 'w' and 'W' character are + indistinguishable by virtual key code because they are the same physical + key (one with and one without the shift key). - Use virtual key codes to detect keystrokes that do not have ASCII - equivalents, allow the user to map the numeric keypad separately from the - main keyboard, and detect control key and other modifier-key combinations - that generate ASCII control key sequences (many of which are not available - directly via character keys in the SDK). + Use virtual key codes to detect keystrokes that do not have ASCII + equivalents, allow the user to map the numeric keypad separately from the + main keyboard, and detect control key and other modifier-key combinations + that generate ASCII control key sequences (many of which are not available + directly via character keys in the SDK). - To assign virtual key codes we started with the Microsoft set but made some - additions and changes. A few differences: + To assign virtual key codes we started with the Microsoft set but made some + additions and changes. A few differences: - 1. Modifier keys are not available as virtual key codes. You cannot get - distinct modifier press and release messages. Please do not try to use - modifier keys as regular keys; doing so will almost certainly interfere - with users' abilities to use the native x-plane key bindings. - - 2. Some keys that do not exist on both Mac and PC keyboards are removed. - - 3. Do not assume that the values of these keystrokes are interchangeable - with MS v-keys. + 1. Modifier keys are not available as virtual key codes. You cannot get + distinct modifier press and release messages. Please do not try to use + modifier keys as regular keys; doing so will almost certainly interfere + with users' abilities to use the native X-Plane key bindings. + 2. Some keys that do not exist on both Mac and PC keyboards are removed. + 3. Do not assume that the values of these keystrokes are interchangeable + with MS v-keys. } - CONST XPLM_VK_BACK = $08; @@ -258,7 +248,7 @@ CONST XPLM_VK_HELP = $2F; - { XPLM_VK_0 thru XPLM_VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) } + { XPLM_VK_0 thru XPLM_VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) } XPLM_VK_0 = $30; XPLM_VK_1 = $31; @@ -279,7 +269,7 @@ CONST XPLM_VK_9 = $39; - { XPLM_VK_A thru XPLM_VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) } + { XPLM_VK_A thru XPLM_VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) } XPLM_VK_A = $41; XPLM_VK_B = $42; @@ -412,8 +402,8 @@ CONST XPLM_VK_F24 = $87; - { The following definitions are extended and are not based on the Microsoft } - { key set. } + { The following definitions are extended and are not based on the Microsoft } + { key set. } XPLM_VK_EQUAL = $B0; XPLM_VK_MINUS = $B1; @@ -442,5 +432,7 @@ CONST XPLM_VK_NUMPAD_EQ = $BD; + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMDisplay.pas b/XPSDK/Delphi/XPLM/XPLMDisplay.pas index 751b5b5..ee4242c 100644 --- a/XPSDK/Delphi/XPLM/XPLMDisplay.pas +++ b/XPSDK/Delphi/XPLM/XPLMDisplay.pas @@ -1,158 +1,208 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMDisplay; INTERFACE { - XPLM Display APIs - THEORY OF OPERATION + This API provides the basic hooks to draw in X-Plane and create user + interface. All X-Plane drawing is done in OpenGL. The X-Plane plug-in + manager takes care of properly setting up the OpenGL context and matrices. + You do not decide when in your code's execution to draw; X-Plane tells you + (via callbacks) when it is ready to have your plugin draw. - This API provides the basic hooks to draw in X-Plane and create user - interface. All X-Plane drawing is done in OpenGL. The X-Plane plug-in - manager takes care of properly setting up the OpenGL context and matrices. - You do not decide when in your code's execution to draw; X-Plane tells you - when it is ready to have your plugin draw. + X-Plane's drawing strategy is straightforward: every "frame" the screen is + rendered by drawing the 3-D scene (dome, ground, objects, airplanes, etc.) + and then drawing the cockpit on top of it. Alpha blending is used to + overlay the cockpit over the world (and the gauges over the panel, etc.). + X-Plane user interface elements (including windows like the map, the main + menu, etc.) are then drawn on top of the cockpit. - X-Plane's drawing strategy is straightforward: every "frame" the screen is - rendered by drawing the 3-d scene (dome, ground, objects, airplanes, etc.) - and then drawing the cockpit on top of it. Alpha blending is used to - overlay the cockpit over the world (and the gauges over the panel, etc.). + There are two ways you can draw: directly and in a window. - There are two ways you can draw: directly and in a window. + Direct drawing (deprecated!---more on that below) involves drawing to the + screen before or after X-Plane finishes a phase of drawing. When you draw + directly, you can specify whether X-Plane is to complete this phase or not. + This allows you to do three things: draw before X-Plane does (under it), + draw after X-Plane does (over it), or draw instead of X-Plane. - Direct drawing involves drawing to the screen before or after X-Plane - finishes a phase of drawing. When you draw directly, you can specify - whether x-plane is to complete this phase or not. This allows you to do - three things: draw before x-plane does (under it), draw after x-plane does - (over it), or draw instead of x-plane. + To draw directly, you register a callback and specify which phase you want + to intercept. The plug-in manager will call you over and over to draw that + phase. - To draw directly, you register a callback and specify what phase you want - to intercept. The plug-in manager will call you over and over to draw that - phase. + Direct drawing allows you to override scenery, panels, or anything. Note + that you cannot assume that you are the only plug-in drawing at this phase. - Direct drawing allows you to override scenery, panels, or anything. Note - that you cannot assume that you are the only plug-in drawing at this - phase. + Direct drawing is deprecated; at some point in the X-Plane 11 run, it will + likely become unsupported entirely as X-Plane transitions from OpenGL to + modern graphics API backends (e.g., Vulkan, Metal, etc.). In the long term, + plugins should use the XPLMInstance API for drawing 3-D objects---this will + be much more efficient than general 3-D OpenGL drawing, and it will + actually be supported by the new graphics backends. We do not yet know what + the post-transition API for generic 3-D drawing will look like (if it + exists at all). - Window drawing provides slightly higher level functionality. With window - drawing you create a window that takes up a portion of the screen. Window - drawing is always two dimensional. Window drawing is front-to-back - controlled; you can specify that you want your window to be brought on - top, and other plug-ins may put their window on top of you. Window drawing - also allows you to sign up for key presses and receive mouse clicks. + In contrast to direct drawing, window drawing provides a higher level + functionality. With window drawing, you create a 2-D window that takes up a + portion of the screen. Window drawing is always two dimensional. Window + drawing is front-to-back controlled; you can specify that you want your + window to be brought on top, and other plug-ins may put their window on top + of you. Window drawing also allows you to sign up for key presses and + receive mouse clicks. - There are three ways to get keystrokes: + Drawing into the screen of an avionics device, like a GPS or a Primary + Flight Display, is a way to extend or replace X-Plane's avionics. Most + screens can be displayed both in a 3d cockpit or + 2d panel, and also in separate popup windows. By installing drawing + callbacks for a certain avionics device, you can change or extend the + appearance of that device regardless whether it's installed in a 3d + cockpit or used in a separate display for home cockpits because you leave + the window managing to X-Plane. - If you create a window, the window can take keyboard focus. It will then - receive all keystrokes. If no window has focus, X-Plane receives - keystrokes. Use this to implement typing in dialog boxes, etc. Only one - window may have focus at a time; your window will be notified if it loses - focus. + There are three ways to get keystrokes: - If you need to associate key strokes with commands/functions in your - plug-in, use a hot key. A hoy is a key-specific callback. Hotkeys are - sent based on virtual key strokes, so any key may be distinctly mapped with - any modifiers. Hot keys can be remapped by other plug-ins. As a plug-in, - you don't have to worry about what your hot key ends up mapped to; other - plug-ins may provide a UI for remapping keystrokes. So hotkeys allow a - user to resolve conflicts and customize keystrokes. - - If you need low level access to the keystroke stream, install a key - sniffer. Key sniffers can be installed above everything or right in front - of the sim. + 1. If you create a window, the window can take keyboard focus. It will + then receive all keystrokes. If no window has focus, X-Plane receives + keystrokes. Use this to implement typing in dialog boxes, etc. Only + one window may have focus at a time; your window will be notified if it + loses focus. + 2. If you need low level access to the keystroke stream, install a key + sniffer. Key sniffers can be installed above everything or right in + front of the sim. + 3. If you would like to associate key strokes with commands/functions in + your plug-in, you should simply register a command (via + XPLMCreateCommand()) and allow users to bind whatever key they choose to + that command. Another (now deprecated) method of doing so is to use a + hot key---a key-specific callback. Hotkeys are sent based on virtual + key strokes, so any key may be distinctly mapped with any modifiers. + Hot keys can be remapped by other plug-ins. As a plug-in, you don't + have to worry about what your hot key ends up mapped to; other plug-ins + may provide a UI for remapping keystrokes. So hotkeys allow a user to + resolve conflicts and customize keystrokes. } -USES XPLMDefs; +USES + XPLMDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * DRAWING CALLBACKS ___________________________________________________________________________} { - Basic drawing callbacks, for low level intercepting of render loop. The - purpose of drawing callbacks is to provide targeted additions or - replacements to x-plane's graphics environment (for example, to add extra - custom objects, or replace drawing of the AI aircraft). Do not assume that - the drawing callbacks will be called in the order implied by the - enumerations. Also do not assume that each drawing phase ends before - another begins; they may be nested. + Basic drawing callbacks, for low level intercepting of X-Plane's render + loop. The purpose of drawing callbacks is to provide targeted additions or + replacements to X-Plane's graphics environment (for example, to add extra + custom objects, or replace drawing of the AI aircraft). Do not assume that + the drawing callbacks will be called in the order implied by the + enumerations. Also do not assume that each drawing phase ends before + another begins; they may be nested. + + Note that all APIs in this section are deprecated, and will likely be + removed during the X-Plane 11 run as part of the transition to + Vulkan/Metal/etc. See the XPLMInstance API for future-proof drawing of 3-D + objects. } - { XPLMDrawingPhase - This constant indicates which part of drawing we are in. Drawing is done - from the back to the front. We get a callback before or after each item. - Metaphases provide access to the beginning and end of the 3d (scene) and 2d - (cockpit) drawing in a manner that is independent of new phases added via - x-plane implementation. + This constant indicates which part of drawing we are in. Drawing is done + from the back to the front. We get a callback before or after each item. + Metaphases provide access to the beginning and end of the 3d (scene) and + 2d (cockpit) drawing in a manner that is independent of new phases added + via X-Plane implementation. - WARNING: As X-Plane's scenery evolves, some drawing phases may cease to - exist and new ones may be invented. If you need a particularly specific - use of these codes, consult Austin and/or be prepared to revise your code - as X-Plane evolves. + **NOTE**: As of XPLM302 the legacy 3D drawing phases (xplm_Phase_FirstScene + to xplm_Phase_LastScene) are deprecated. When running under X-Plane 11.50 + with the modern Vulkan or Metal backend, X-Plane will no longer call + these drawing phases. There is a new drawing phase, xplm_Phase_Modern3D, + which is supported under OpenGL and Vulkan which is called out roughly + where the old before xplm_Phase_Airplanes phase was for blending. This + phase is *NOT* supported under Metal and comes with potentially + substantial performance overhead. Please do *NOT* opt into this phase if + you don't do any actual drawing that requires the depth buffer in some + way! + + **WARNING**: As X-Plane's scenery evolves, some drawing phases may cease to + exist and new ones may be invented. If you need a particularly specific + use of these codes, consult Austin and/or be prepared to revise your code + as X-Plane evolves. } TYPE XPLMDrawingPhase = ( - { This is the earliest point at which you can draw in 3-d. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated as of XPLM302. This is the earliest point at which you can draw } + { in 3-d. } xplm_Phase_FirstScene = 0 +{$ENDIF XPLM_DEPRECATED} - { Drawing of land and water. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated as of XPLM302. Drawing of land and water. } ,xplm_Phase_Terrain = 5 +{$ENDIF XPLM_DEPRECATED} - { Drawing runways and other airport detail. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated as of XPLM302. Drawing runways and other airport detail. } ,xplm_Phase_Airports = 10 +{$ENDIF XPLM_DEPRECATED} - { Drawing roads, trails, trains, etc. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated as of XPLM302. Drawing roads, trails, trains, etc. } ,xplm_Phase_Vectors = 15 +{$ENDIF XPLM_DEPRECATED} - { 3-d objects (houses, smokestacks, etc. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated as of XPLM302. 3-d objects (houses, smokestacks, etc. } ,xplm_Phase_Objects = 20 +{$ENDIF XPLM_DEPRECATED} - { External views of airplanes, both yours and the AI aircraft. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated as of XPLM302. External views of airplanes, both yours and the } + { AI aircraft. } ,xplm_Phase_Airplanes = 25 +{$ENDIF XPLM_DEPRECATED} - { This is the last point at which you can draw in 3-d. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated as of XPLM302. This is the last point at which you can draw in } + { 3-d. } ,xplm_Phase_LastScene = 30 +{$ENDIF XPLM_DEPRECATED} - { This is the first phase where you can draw in 2-d. } +{$IFDEF XPLM302} + { A chance to do modern 3D drawing. } + ,xplm_Phase_Modern3D = 31 +{$ENDIF XPLM302} + + { This is the first phase where you can draw in 2-d. } ,xplm_Phase_FirstCockpit = 35 - { The non-moving parts of the aircraft panel. } + { The non-moving parts of the aircraft panel. } ,xplm_Phase_Panel = 40 - { The moving parts of the aircraft panel. } + { The moving parts of the aircraft panel. } ,xplm_Phase_Gauges = 45 - { Floating windows from plugins. } + { Floating windows from plugins. } ,xplm_Phase_Window = 50 - { The last change to draw in 2d. } + { The last chance to draw in 2d. } ,xplm_Phase_LastCockpit = 55 {$IFDEF XPLM200} - { 3-d Drawing for the local map. Use regular OpenGL coordinates to draw in } - { this phase. } + { Removed as of XPLM300; Use the full-blown XPLMMap API instead. } ,xplm_Phase_LocalMap3D = 100 -{$ENDIF} +{$ENDIF XPLM200} {$IFDEF XPLM200} - { 2-d Drawing of text over the local map. } + { Removed as of XPLM300; Use the full-blown XPLMMap API instead. } ,xplm_Phase_LocalMap2D = 101 -{$ENDIF} +{$ENDIF XPLM200} {$IFDEF XPLM200} - { Drawing of the side-profile view in the local map screen. } + { Removed as of XPLM300; Use the full-blown XPLMMap API instead. } ,xplm_Phase_LocalMapProfile = 102 -{$ENDIF} +{$ENDIF XPLM200} ); PXPLMDrawingPhase = ^XPLMDrawingPhase; @@ -160,151 +210,331 @@ TYPE { XPLMDrawCallback_f - This is the prototype for a low level drawing callback. You are passed in - the phase and whether it is before or after. If you are before the phase, - return 1 to let x-plane draw or 0 to suppress x-plane drawing. If you are - after the phase the return value is ignored. + This is the prototype for a low level drawing callback. You are passed in + the phase and whether it is before or after. If you are before the phase, + return 1 to let X-Plane draw or 0 to suppress X-Plane drawing. If you are + after the phase the return value is ignored. - Refcon is a unique value that you specify when registering the callback, - allowing you to slip a pointer to your own data to the callback. + Refcon is a unique value that you specify when registering the callback, + allowing you to slip a pointer to your own data to the callback. - Upon entry the OpenGL context will be correctly set up for you and OpenGL - will be in 'local' coordinates for 3d drawing and panel coordinates for 2d - drawing. The OpenGL state (texturing, etc.) will be unknown. + Upon entry the OpenGL context will be correctly set up for you and OpenGL + will be in 'local' coordinates for 3d drawing and panel coordinates for 2d + drawing. The OpenGL state (texturing, etc.) will be unknown. } XPLMDrawCallback_f = FUNCTION( inPhase : XPLMDrawingPhase; - inIsBefore : integer; - inRefcon : pointer) : integer; cdecl; - - { - XPLMKeySniffer_f - - This is the prototype for a low level key-sniffing function. Window-based - UI _should not use this_! The windowing system provides high-level - mediated keyboard access. By comparison, the key sniffer provides low - level keyboard access. - - Key sniffers are provided to allow libraries to provide non-windowed user - interaction. For example, the MUI library uses a key sniffer to do pop-up - text entry. - - inKey is the character pressed, inRefCon is a value you supply during - registration. Return 1 to pass the key on to the next sniffer, the window - mgr, x-plane, or whomever is down stream. Return 0 to consume the key. - - Warning: this API declares virtual keys as a signed character; however the - VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values - (that is 0x80 instead of -0x80). So you may need to cast the incoming vkey - to an unsigned char to get correct comparisons in C. - } - XPLMKeySniffer_f = FUNCTION( - inChar : char; - inFlags : XPLMKeyFlags; - inVirtualKey : char; - inRefcon : pointer) : integer; cdecl; + inIsBefore : Integer; + inRefcon : pointer) : Integer; cdecl; { XPLMRegisterDrawCallback - This routine registers a low level drawing callback. Pass in the phase you - want to be called for and whether you want to be called before or after. - This routine returns 1 if the registration was successful, or 0 if the - phase does not exist in this version of x-plane. You may register a - callback multiple times for the same or different phases as long as the - refcon is unique each time. + This routine registers a low level drawing callback. Pass in the phase you + want to be called for and whether you want to be called before or after. + This routine returns 1 if the registration was successful, or 0 if the + phase does not exist in this version of X-Plane. You may register a + callback multiple times for the same or different phases as long as the + refcon is unique each time. + + Note that this function will likely be removed during the X-Plane 11 run as + part of the transition to Vulkan/Metal/etc. See the XPLMInstance API for + future-proof drawing of 3-D objects. } FUNCTION XPLMRegisterDrawCallback( inCallback : XPLMDrawCallback_f; inPhase : XPLMDrawingPhase; - inWantsBefore : integer; - inRefcon : pointer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inWantsBefore : Integer; + inRefcon : pointer) : Integer; + cdecl; external XPLM_DLL; { XPLMUnregisterDrawCallback - This routine unregisters a draw callback. You must unregister a callback - for each time you register a callback if you have registered it multiple - times with different refcons. The routine returns 1 if it can find the - callback to unregister, 0 otherwise. + This routine unregisters a draw callback. You must unregister a callback + for each time you register a callback if you have registered it multiple + times with different refcons. The routine returns 1 if it can find the + callback to unregister, 0 otherwise. + + Note that this function will likely be removed during the X-Plane 11 run as + part of the transition to Vulkan/Metal/etc. See the XPLMInstance API for + future-proof drawing of 3-D objects. } FUNCTION XPLMUnregisterDrawCallback( inCallback : XPLMDrawCallback_f; inPhase : XPLMDrawingPhase; - inWantsBefore : integer; - inRefcon : pointer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inWantsBefore : Integer; + inRefcon : pointer) : Integer; + cdecl; external XPLM_DLL; + +{$IFDEF XPLM400} +{___________________________________________________________________________ + * AVIONICS API + ___________________________________________________________________________} +{ + Drawing callbacks for before and after X-Plane draws the instrument screen + can be registered for every cockpit device. If the user plane does not + have the device installed, your callback will not be called! Use the + return value to enable or disable X-Plane's drawing. By drawing into the + framebuffer of the avionics device, your modifications will be visible + regardless whether the device's screen is in a 3d cockpit or a popup + window. +} + { - XPLMRegisterKeySniffer + XPLMDeviceID - This routine registers a key sniffing callback. You specify whether you - want to sniff before the window system, or only sniff keys the window - system does not consume. You should ALMOST ALWAYS sniff non-control keys - after the window system. When the window system consumes a key, it is - because the user has "focused" a window. Consuming the key or taking - action based on the key will produce very weird results. Returns 1 if - successful. + This constant indicates the device we want to override or enhance. We can + get a callback before or after each item. } - FUNCTION XPLMRegisterKeySniffer( - inCallback : XPLMKeySniffer_f; - inBeforeWindows : integer; - inRefcon : pointer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} +TYPE + XPLMDeviceID = ( + { GNS430, pilot side. } + xplm_device_GNS430_1 = 0 + + { GNS430, copilot side. } + ,xplm_device_GNS430_2 = 1 + + { GNS530, pilot side. } + ,xplm_device_GNS530_1 = 2 + + { GNS530, copilot side. } + ,xplm_device_GNS530_2 = 3 + + { generic airliner CDU, pilot side. } + ,xplm_device_CDU739_1 = 4 + + { generic airliner CDU, copilot side. } + ,xplm_device_CDU739_2 = 5 + + { G1000 Primary Flight Display, pilot side. } + ,xplm_device_G1000_PFD_1 = 6 + + { G1000 Multifunction Display. } + ,xplm_device_G1000_MFD = 7 + + { G1000 Primary Flight Display, copilot side. } + ,xplm_device_G1000_PFD_2 = 8 + + { Primus CDU, pilot side. } + ,xplm_device_CDU815_1 = 9 + + { Primus CDU, copilot side. } + ,xplm_device_CDU815_2 = 10 + + { Primus Primary Flight Display, pilot side. } + ,xplm_device_Primus_PFD_1 = 11 + + { Primus Primary Flight Display, copilot side. } + ,xplm_device_Primus_PFD_2 = 12 + + { Primus Multifunction Display, pilot side. } + ,xplm_device_Primus_MFD_1 = 13 + + { Primus Multifunction Display, copilot side. } + ,xplm_device_Primus_MFD_2 = 14 + + { Primus Multifunction Display, central. } + ,xplm_device_Primus_MFD_3 = 15 + + { Primus Radio Management Unit, pilot side. } + ,xplm_device_Primus_RMU_1 = 16 + + { Primus Radio Management Unit, copilot side. } + ,xplm_device_Primus_RMU_2 = 17 + + ); + PXPLMDeviceID = ^XPLMDeviceID; { - XPLMUnregisterKeySniffer + XPLMAvionicsCallback_f - This routine unregisters a key sniffer. You must unregister a key sniffer - for every time you register one with the exact same signature. Returns 1 - if successful. + This is the prototype for your drawing callback. You are passed in the + device you are enhancing/replacing, and whether it is before or after + X-Plane drawing. If you are before X-Plane, return 1 to let X-Plane draw or + 0 to suppress X-Plane drawing. If you are after the phase the return value + is ignored. + + Refcon is a unique value that you specify when registering the callback, + allowing you to slip a pointer to your own data to the callback. + + Upon entry the OpenGL context will be correctly set up for you and OpenGL + will be in panel coordinates for 2d drawing. The OpenGL state (texturing, + etc.) will be unknown. } - FUNCTION XPLMUnregisterKeySniffer( - inCallback : XPLMKeySniffer_f; - inBeforeWindows : integer; - inRefcon : pointer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + XPLMAvionicsCallback_f = FUNCTION( + inDeviceID : XPLMDeviceID; + inIsBefore : Integer; + inRefcon : pointer) : Integer; cdecl; + { + XPLMAvionicsID + + This is an opaque identifier for an avionics display that you enhance or + replace. When you register your callbacks (via + XPLMRegisterAvionicsCallbacksEx()), you will specify callbacks to handle + drawing, and get back such a handle. + } + XPLMAvionicsID = pointer; + PXPLMAvionicsID = ^XPLMAvionicsID; + + { + XPLMCustomizeAvionics_t + + The XPLMCustomizeAvionics_t structure defines all of the parameters used to + replace or enhance avionics for using XPLMRegisterAvionicsCallbacksEx(). + The structure will be expanded in future SDK APIs to include more features. + Always set the structSize member to the size of your struct in bytes! + } + XPLMCustomizeAvionics_t = RECORD + { Used to inform XPLMRegisterAvionicsCallbacksEx() of the SDK version you } + { compiled against; should always be set to sizeof(XPLMCustomizeAvionics_t) } + structSize : Integer; + { Which avionics device you want your drawing applied to. } + deviceId : XPLMDeviceID; + { The draw callback to be called before X-Plane draws. } + drawCallbackBefore : XPLMAvionicsCallback_f; + { The draw callback to be called after X-Plane has drawn. } + drawCallbackAfter : XPLMAvionicsCallback_f; + { A reference which will be passed into each of your draw callbacks. Use this} + { to pass information to yourself as needed. } + refcon : pointer; + END; + PXPLMCustomizeAvionics_t = ^XPLMCustomizeAvionics_t; + + { + XPLMRegisterAvionicsCallbacksEx + + This routine registers your callbacks for a device. This returns a handle. + If the returned handle is NULL, there was a problem interpreting your + input, most likely the struct size was wrong for your SDK version. If the + returned handle is not NULL, your callbacks will be called according to + schedule as long as your plugin is not deactivated, or unloaded, or your + call XPLMUnregisterAvionicsCallbacks(). + } + FUNCTION XPLMRegisterAvionicsCallbacksEx( + inParams : PXPLMCustomizeAvionics_t) : XPLMAvionicsID; + cdecl; external XPLM_DLL; + + { + XPLMUnregisterAvionicsCallbacks + + This routine unregisters your callbacks for a device. They will no longer + be called. + } + PROCEDURE XPLMUnregisterAvionicsCallbacks( + inAvionicsId : XPLMAvionicsID); + cdecl; external XPLM_DLL; + +{$ENDIF XPLM400} {___________________________________________________________________________ * WINDOW API ___________________________________________________________________________} { - Window API, for higher level drawing with UI interaction. + The window API provides a high-level abstraction for drawing with UI + interaction. - Note: all 2-d (and thus all window drawing) is done in 'cockpit pixels'. - Even when the OpenGL window contains more than 1024x768 pixels, the cockpit - drawing is magnified so that only 1024x768 pixels are available. + Windows may operate in one of two modes: legacy (for plugins compiled + against old versions of the XPLM, as well as windows created via the + deprecated XPLMCreateWindow() function, rather than XPLMCreateWindowEx()), + or modern (for windows compiled against the XPLM300 or newer API, and + created via XPLMCreateWindowEx()). + + Modern windows have access to new X-Plane 11 windowing features, like + support for new positioning modes (including being "popped out" into their + own first-class window in the operating system). They can also optionally + be decorated in the style of X-Plane 11 windows (like the map). + + Modern windows operate in "boxel" units. A boxel ("box of pixels") is a + unit of virtual pixels which, depending on X-Plane's scaling, may + correspond to an arbitrary NxN "box" of real pixels on screen. Because + X-Plane handles this scaling automatically, you can effectively treat the + units as though you were simply drawing in pixels, and know that when + X-Plane is running with 150% or 200% scaling, your drawing will be + automatically scaled (and likewise all mouse coordinates, screen bounds, + etc. will also be auto-scaled). + + In contrast, legacy windows draw in true screen pixels, and thus tend to + look quite small when X-Plane is operating in a scaled mode. + + Legacy windows have their origin in the lower left of the main X-Plane + window. In contrast, since modern windows are not constrained to the main + window, they have their origin in the lower left of the entire global + desktop space, and the lower left of the main X-Plane window is not + guaranteed to be (0, 0). In both cases, x increases as you move left, and y + increases as you move up. } +TYPE + { + XPLMWindowID + + This is an opaque identifier for a window. You use it to control your + window. When you create a window (via either XPLMCreateWindow() or + XPLMCreateWindowEx()), you will specify callbacks to handle drawing, mouse + interaction, etc. + } + XPLMWindowID = pointer; + PXPLMWindowID = ^XPLMWindowID; + + { + XPLMDrawWindow_f + + A callback to handle 2-D drawing of your window. You are passed in your + window and its refcon. Draw the window. You can use other XPLM functions + from this header to find the current dimensions of your window, etc. When + this callback is called, the OpenGL context will be set properly for 2-D + window drawing. + + **Note**: Because you are drawing your window over a background, you can + make a translucent window easily by simply not filling in your entire + window's bounds. + } + XPLMDrawWindow_f = PROCEDURE( + inWindowID : XPLMWindowID; + inRefcon : pointer); cdecl; + + { + XPLMHandleKey_f + + This function is called when a key is pressed or keyboard focus is taken + away from your window. If losingFocus is 1, you are losing the keyboard + focus, otherwise a key was pressed and inKey contains its character. + + The window ID passed in will be your window for key presses, or the other + window taking focus when losing focus. Note that in the modern plugin + system, often focus is taken by the window manager itself; for this resaon, + the window ID may be zero when losing focus, and you should not write code + that depends onit. + + The refcon passed in will be the one from registration, for both key + presses and losing focus. + + Warning: this API declares virtual keys as a signed character; however the + VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values + (that is 0x80 instead of -0x80). So you may need to cast the incoming vkey + to an unsigned char to get correct comparisons in C. + } + XPLMHandleKey_f = PROCEDURE( + inWindowID : XPLMWindowID; + inKey : XPLMChar; + inFlags : XPLMKeyFlags; + inVirtualKey : XPLMChar; + inRefcon : pointer; + losingFocus : Integer); cdecl; { XPLMMouseStatus - When the mouse is clicked, your mouse click routine is called repeatedly. - It is first called with the mouse down message. It is then called zero or - more times with the mouse-drag message, and finally it is called once with - the mouse up message. All of these messages will be directed to the same - window. + When the mouse is clicked, your mouse click routine is called repeatedly. + It is first called with the mouse down message. It is then called zero or + more times with the mouse-drag message, and finally it is called once with + the mouse up message. All of these messages will be directed to the same + window; you are guaranteed to not receive a drag or mouse-up event without + first receiving the corresponding mouse-down. } -TYPE XPLMMouseStatus = ( xplm_MouseDown = 1 @@ -315,415 +545,1003 @@ TYPE ); PXPLMMouseStatus = ^XPLMMouseStatus; + { + XPLMHandleMouseClick_f + + You receive this call for one of three events: + + - when the user clicks the mouse button down + - (optionally) when the user drags the mouse after a down-click, but before + the up-click + - when the user releases the down-clicked mouse button. + + You receive the x and y of the click, your window, and a refcon. Return 1 + to consume the click, or 0 to pass it through. + + WARNING: passing clicks through windows (as of this writing) causes mouse + tracking problems in X-Plane; do not use this feature! + + The units for x and y values match the units used in your window. Thus, for + "modern" windows (those created via XPLMCreateWindowEx() and compiled + against the XPLM300 library), the units are boxels, while legacy windows + will get pixels. Legacy windows have their origin in the lower left of the + main X-Plane window, while modern windows have their origin in the lower + left of the global desktop space. In both cases, x increases as you move + right, and y increases as you move up. + } + XPLMHandleMouseClick_f = FUNCTION( + inWindowID : XPLMWindowID; + x : Integer; + y : Integer; + inMouse : XPLMMouseStatus; + inRefcon : pointer) : Integer; cdecl; + {$IFDEF XPLM200} { XPLMCursorStatus - XPLMCursorStatus describes how you would like X-Plane to manage the cursor. - See XPLMHandleCursor_f for more info. + XPLMCursorStatus describes how you would like X-Plane to manage the cursor. + See XPLMHandleCursor_f for more info. } +TYPE XPLMCursorStatus = ( - { X-Plane manages the cursor normally, plugin does not affect the cusrsor. } + { X-Plane manages the cursor normally, plugin does not affect the cusrsor. } xplm_CursorDefault = 0 - { X-Plane hides the cursor. } + { X-Plane hides the cursor. } ,xplm_CursorHidden = 1 - { X-Plane shows the cursor as the default arrow. } + { X-Plane shows the cursor as the default arrow. } ,xplm_CursorArrow = 2 - { X-Plane shows the cursor but lets you select an OS cursor. } + { X-Plane shows the cursor but lets you select an OS cursor. } ,xplm_CursorCustom = 3 ); PXPLMCursorStatus = ^XPLMCursorStatus; -{$ENDIF} - - { - XPLMWindowID - - This is an opaque identifier for a window. You use it to control your - window. When you create a window, you will specify callbacks to handle - drawing and mouse interaction, etc. - } - XPLMWindowID = pointer; - PXPLMWindowID = ^XPLMWindowID; - - { - XPLMDrawWindow_f - - This function handles drawing. You are passed in your window and its - refcon. Draw the window. You can use XPLM functions to find the current - dimensions of your window, etc. When this callback is called, the OpenGL - context will be set properly for cockpit drawing. NOTE: Because you are - drawing your window over a background, you can make a translucent window - easily by simply not filling in your entire window's bounds. - } - XPLMDrawWindow_f = PROCEDURE( - inWindowID : XPLMWindowID; - inRefcon : pointer); cdecl; - - { - XPLMHandleKey_f - - This function is called when a key is pressed or keyboard focus is taken - away from your window. If losingFocus is 1, you are losign the keyboard - focus, otherwise a key was pressed and inKey contains its character. You - are also passewd your window and a refcon. Warning: this API declares - virtual keys as a signed character; however the VKEY #define macros in - XPLMDefs.h define the vkeys using unsigned values (that is 0x80 instead of - -0x80). So you may need to cast the incoming vkey to an unsigned char to - get correct comparisons in C. - } - XPLMHandleKey_f = PROCEDURE( - inWindowID : XPLMWindowID; - inKey : char; - inFlags : XPLMKeyFlags; - inVirtualKey : char; - inRefcon : pointer; - losingFocus : integer); cdecl; - - { - XPLMHandleMouseClick_f - - You receive this call when the mouse button is pressed down or released. - Between then these two calls is a drag. You receive the x and y of the - click, your window, and a refcon. Return 1 to consume the click, or 0 to - pass it through. - - WARNING: passing clicks through windows (as of this writing) causes mouse - tracking problems in X-Plane; do not use this feature! - } - XPLMHandleMouseClick_f = FUNCTION( - inWindowID : XPLMWindowID; - x : integer; - y : integer; - inMouse : XPLMMouseStatus; - inRefcon : pointer) : integer; cdecl; +{$ENDIF XPLM200} {$IFDEF XPLM200} { XPLMHandleCursor_f - The SDK calls your cursor status callback when the mouse is over your - plugin window. Return a cursor status code to indicate how you would like - X-Plane to manage the cursor. If you return xplm_CursorDefault, the SDK - will try lower-Z-order plugin windows, then let the sim manage the cursor. + The SDK calls your cursor status callback when the mouse is over your + plugin window. Return a cursor status code to indicate how you would like + X-Plane to manage the cursor. If you return xplm_CursorDefault, the SDK + will try lower-Z-order plugin windows, then let the sim manage the cursor. - Note: you should never show or hide the cursor yourself - these APIs are - typically reference-counted and thus cannot safely and predictably be used - by the SDK. Instead return one of xplm_CursorHidden to hide the cursor or - xplm_CursorArrow/xplm_CursorCustom to show the cursor. + Note: you should never show or hide the cursor yourself---these APIs are + typically reference-counted and thus cannot safely and predictably be used + by the SDK. Instead return one of xplm_CursorHidden to hide the cursor or + xplm_CursorArrow/xplm_CursorCustom to show the cursor. - If you want to implement a custom cursor by drawing a cursor in OpenGL, use - xplm_CursorHidden to hide the OS cursor and draw the cursor using a 2-d - drawing callback (after xplm_Phase_Window is probably a good choice). If - you want to use a custom OS-based cursor, use xplm_CursorCustom to ask - X-Plane to show the cursor but not affect its image. You can then use an - OS specific call like SetThemeCursor (Mac) or SetCursor/LoadCursor - (Windows). + If you want to implement a custom cursor by drawing a cursor in OpenGL, use + xplm_CursorHidden to hide the OS cursor and draw the cursor using a 2-d + drawing callback (after xplm_Phase_Window is probably a good choice, but + see deprecation warnings on the drawing APIs!). If you want to use a + custom OS-based cursor, use xplm_CursorCustom to ask X-Plane to show the + cursor but not affect its image. You can then use an OS specific call like + SetThemeCursor (Mac) or SetCursor/LoadCursor (Windows). + + The units for x and y values match the units used in your window. Thus, for + "modern" windows (those created via XPLMCreateWindowEx() and compiled + against the XPLM300 library), the units are boxels, while legacy windows + will get pixels. Legacy windows have their origin in the lower left of the + main X-Plane window, while modern windows have their origin in the lower + left of the global desktop space. In both cases, x increases as you move + right, and y increases as you move up. } XPLMHandleCursor_f = FUNCTION( inWindowID : XPLMWindowID; - x : integer; - y : integer; + x : Integer; + y : Integer; inRefcon : pointer) : XPLMCursorStatus; cdecl; -{$ENDIF} +{$ENDIF XPLM200} {$IFDEF XPLM200} { XPLMHandleMouseWheel_f - The SDK calls your mouse wheel callback when one of the mouse wheels is - turned within your window. Return 1 to consume the mouse wheel clicks or - 0 to pass them on to a lower window. (You should consume mouse wheel - clicks even if they do nothing if your window appears opaque to the user.) - The number of clicks indicates how far the wheel was turned since the last - callback. The wheel is 0 for the vertical axis or 1 for the horizontal axis - (for OS/mouse combinations that support this). + The SDK calls your mouse wheel callback when one of the mouse wheels is + scrolled within your window. Return 1 to consume the mouse wheel movement + or 0 to pass them on to a lower window. (If your window appears opaque to + the user, you should consume mouse wheel scrolling even if it does + nothing.) The number of "clicks" indicates how far the wheel was turned + since the last callback. The wheel is 0 for the vertical axis or 1 for the + horizontal axis (for OS/mouse combinations that support this). + + The units for x and y values match the units used in your window. Thus, for + "modern" windows (those created via XPLMCreateWindowEx() and compiled + against the XPLM300 library), the units are boxels, while legacy windows + will get pixels. Legacy windows have their origin in the lower left of the + main X-Plane window, while modern windows have their origin in the lower + left of the global desktop space. In both cases, x increases as you move + right, and y increases as you move up. } XPLMHandleMouseWheel_f = FUNCTION( inWindowID : XPLMWindowID; - x : integer; - y : integer; - wheel : integer; - clicks : integer; - inRefcon : pointer) : integer; cdecl; -{$ENDIF} + x : Integer; + y : Integer; + wheel : Integer; + clicks : Integer; + inRefcon : pointer) : Integer; cdecl; +{$ENDIF XPLM200} + +{$IFDEF XPLM300} + { + XPLMWindowLayer + + XPLMWindowLayer describes where in the ordering of windows X-Plane should + place a particular window. Windows in higher layers cover windows in lower + layers. So, a given window might be at the top of its particular layer, but + it might still be obscured by a window in a higher layer. (This happens + frequently when floating windows, like X-Plane's map, are covered by a + modal alert.) + + Your window's layer can only be specified when you create the window (in + the XPLMCreateWindow_t you pass to XPLMCreateWindowEx()). For this reason, + layering only applies to windows created with new X-Plane 11 GUI features. + (Windows created using the older XPLMCreateWindow(), or windows compiled + against a pre-XPLM300 version of the SDK will simply be placed in the + flight overlay window layer.) + } +TYPE + XPLMWindowLayer = ( + { The lowest layer, used for HUD-like displays while flying. } + xplm_WindowLayerFlightOverlay = 0 + + { Windows that "float" over the sim, like the X-Plane 11 map does. If you are} + { not sure which layer to create your window in, choose floating. } + ,xplm_WindowLayerFloatingWindows = 1 + + { An interruptive modal that covers the sim with a transparent black overlay } + { to draw the user's focus to the alert } + ,xplm_WindowLayerModal = 2 + + { "Growl"-style notifications that are visible in a corner of the screen, } + { even over modals } + ,xplm_WindowLayerGrowlNotifications = 3 + + ); + PXPLMWindowLayer = ^XPLMWindowLayer; +{$ENDIF XPLM300} + +{$IFDEF XPLM301} + { + XPLMWindowDecoration + + XPLMWindowDecoration describes how "modern" windows will be displayed. This + impacts both how X-Plane draws your window as well as certain mouse + handlers. + + Your window's decoration can only be specified when you create the window + (in the XPLMCreateWindow_t you pass to XPLMCreateWindowEx()). + } +TYPE + XPLMWindowDecoration = ( + { X-Plane will draw no decoration for your window, and apply no automatic } + { click handlers. The window will not stop click from passing through its } + { bounds. This is suitable for "windows" which request, say, the full screen } + { bounds, then only draw in a small portion of the available area. } + xplm_WindowDecorationNone = 0 + + { The default decoration for "native" windows, like the map. Provides a solid} + { background, as well as click handlers for resizing and dragging the window.} + ,xplm_WindowDecorationRoundRectangle = 1 + + { X-Plane will draw no decoration for your window, nor will it provide resize} + { handlers for your window edges, but it will stop clicks from passing } + { through your windows bounds. } + ,xplm_WindowDecorationSelfDecorated = 2 + + { Like self-decorated, but with resizing; X-Plane will draw no decoration for} + { your window, but it will stop clicks from passing through your windows } + { bounds, and provide automatic mouse handlers for resizing. } + ,xplm_WindowDecorationSelfDecoratedResizable = 3 + + ); + PXPLMWindowDecoration = ^XPLMWindowDecoration; +{$ENDIF XPLM301} {$IFDEF XPLM200} { XPLMCreateWindow_t - The XPMCreateWindow_t structure defines all of the parameters used to - create a window using XPLMCreateWindowEx. The structure will be expanded - in future SDK APIs to include more features. Always set the structSize - member to the size of your struct in bytes! + The XPMCreateWindow_t structure defines all of the parameters used to + create a modern window using XPLMCreateWindowEx(). The structure will be + expanded in future SDK APIs to include more features. Always set the + structSize member to the size of your struct in bytes! + + All windows created by this function in the XPLM300 version of the API are + created with the new X-Plane 11 GUI features. This means your plugin will + get to "know" about the existence of X-Plane windows other than the main + window. All drawing and mouse callbacks for your window will occur in + "boxels," giving your windows automatic support for high-DPI scaling in + X-Plane. In addition, your windows can opt-in to decoration with the + X-Plane 11 window styling, and you can use the + XPLMSetWindowPositioningMode() API to make your window "popped out" into a + first-class operating system window. + + Note that this requires dealing with your window's bounds in "global + desktop" positioning units, rather than the traditional panel coordinate + system. In global desktop coordinates, the main X-Plane window may not have + its origin at coordinate (0, 0), and your own window may have negative + coordinates. Assuming you don't implicitly assume (0, 0) as your origin, + the only API change you should need is to start using + XPLMGetMouseLocationGlobal() rather than XPLMGetMouseLocation(), and + XPLMGetScreenBoundsGlobal() instead of XPLMGetScreenSize(). + + If you ask to be decorated as a floating window, you'll get the blue window + control bar and blue backing that you see in X-Plane 11's normal "floating" + windows (like the map). } +TYPE XPLMCreateWindow_t = RECORD - structSize : integer; - left : integer; - top : integer; - right : integer; - bottom : integer; - visible : integer; + { Used to inform XPLMCreateWindowEx() of the SDK version you compiled } + { against; should always be set to sizeof(XPLMCreateWindow_t) } + structSize : Integer; + { Left bound, in global desktop boxels } + left : Integer; + { Top bound, in global desktop boxels } + top : Integer; + { Right bound, in global desktop boxels } + right : Integer; + { Bottom bound, in global desktop boxels } + bottom : Integer; + visible : Integer; drawWindowFunc : XPLMDrawWindow_f; + { A callback to handle the user left-clicking within your window (or NULL to } + { ignore left clicks) } handleMouseClickFunc : XPLMHandleMouseClick_f; handleKeyFunc : XPLMHandleKey_f; handleCursorFunc : XPLMHandleCursor_f; handleMouseWheelFunc : XPLMHandleMouseWheel_f; + { A reference which will be passed into each of your window callbacks. Use } + { this to pass information to yourself as needed. } refcon : pointer; +{$IFDEF XPLM301} + { Specifies the type of X-Plane 11-style "wrapper" you want around your } + { window, if any } + decorateAsFloatingWindow : XPLMWindowDecoration; +{$ENDIF XPLM301} +{$IFDEF XPLM300} + layer : XPLMWindowLayer; +{$ENDIF XPLM300} +{$IFDEF XPLM300} + { A callback to handle the user right-clicking within your window (or NULL to} + { ignore right clicks) } + handleRightClickFunc : XPLMHandleMouseClick_f; +{$ENDIF XPLM300} END; PXPLMCreateWindow_t = ^XPLMCreateWindow_t; -{$ENDIF} - - { - XPLMGetScreenSize - - This routine returns the size of the size of the X-Plane OpenGL window in - pixels. Please note that this is not the size of the screen when doing - 2-d drawing (the 2-d screen is currently always 1024x768, and graphics are - scaled up by OpenGL when doing 2-d drawing for higher-res monitors). This - number can be used to get a rough idea of the amount of detail the user - will be able to see when drawing in 3-d. - } - PROCEDURE XPLMGetScreenSize( - outWidth : Pinteger; { Can be nil } - outHeight : Pinteger); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMGetMouseLocation - - This routine returns the current mouse location in cockpit pixels. The - bottom left corner of the display is 0,0. Pass NULL to not receive info - about either parameter. - } - PROCEDURE XPLMGetMouseLocation( - outX : Pinteger; { Can be nil } - outY : Pinteger); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMCreateWindow - - This routine creates a new window. Pass in the dimensions and offsets to - the window's bottom left corner from the bottom left of the screen. You - can specify whether the window is initially visible or not. Also, you pass - in three callbacks to run the window and a refcon. This function returns a - window ID you can use to refer to the new window. - - NOTE: windows do not have "frames"; you are responsible for drawing the - background and frame of the window. Higher level libraries have routines - which make this easy. - } - FUNCTION XPLMCreateWindow( - inLeft : integer; - inTop : integer; - inRight : integer; - inBottom : integer; - inIsVisible : integer; - inDrawCallback : XPLMDrawWindow_f; - inKeyCallback : XPLMHandleKey_f; - inMouseCallback : XPLMHandleMouseClick_f; - inRefcon : pointer) : XPLMWindowID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} +{$ENDIF XPLM200} {$IFDEF XPLM200} { XPLMCreateWindowEx - This routine creates a new window - you pass in an XPLMCreateWindow_t - structure with all of the fields set in. You must set the structSize of - the structure to the size of the actual structure you used. Also, you - must provide funtions for every callback - you may not leave them null! - (If you do not support the cursor or mouse wheel, use functions that return - the default values.) The numeric values of the XPMCreateWindow_t structure - correspond to the parameters of XPLMCreateWindow. + This routine creates a new "modern" window. You pass in an + XPLMCreateWindow_t structure with all of the fields set in. You must set + the structSize of the structure to the size of the actual structure you + used. Also, you must provide functions for every callback---you may not + leave them null! (If you do not support the cursor or mouse wheel, use + functions that return the default values.) } FUNCTION XPLMCreateWindowEx( inParams : PXPLMCreateWindow_t) : XPLMWindowID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} + cdecl; external XPLM_DLL; +{$ENDIF XPLM200} + + { + XPLMCreateWindow + + Deprecated as of XPLM300. + + This routine creates a new legacy window. Unlike modern windows (created + via XPLMCreateWindowEx()), legacy windows do not have access to X-Plane 11 + features like automatic scaling for high-DPI screens, native window styles, + or support for being "popped out" into first-class operating system + windows. + + Pass in the dimensions and offsets to the window's bottom left corner from + the bottom left of the screen. You can specify whether the window is + initially visible or not. Also, you pass in three callbacks to run the + window and a refcon. This function returns a window ID you can use to + refer to the new window. + + NOTE: Legacy windows do not have "frames"; you are responsible for drawing + the background and frame of the window. Higher level libraries have + routines which make this easy. + } + FUNCTION XPLMCreateWindow( + inLeft : Integer; + inTop : Integer; + inRight : Integer; + inBottom : Integer; + inIsVisible : Integer; + inDrawCallback : XPLMDrawWindow_f; + inKeyCallback : XPLMHandleKey_f; + inMouseCallback : XPLMHandleMouseClick_f; + inRefcon : pointer) : XPLMWindowID; + cdecl; external XPLM_DLL; { XPLMDestroyWindow - This routine destroys a window. The callbacks are not called after this - call. Keyboard focus is removed from the window before destroying it. + This routine destroys a window. The window's callbacks are not called + after this call. Keyboard focus is removed from the window before + destroying it. } PROCEDURE XPLMDestroyWindow( inWindowID : XPLMWindowID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; + + { + XPLMGetScreenSize + + This routine returns the size of the main X-Plane OpenGL window in pixels. + This number can be used to get a rough idea of the amount of detail the + user will be able to see when drawing in 3-d. + } + PROCEDURE XPLMGetScreenSize( + outWidth : PInteger; { Can be nil } + outHeight : PInteger); { Can be nil } + cdecl; external XPLM_DLL; + +{$IFDEF XPLM300} + { + XPLMGetScreenBoundsGlobal + + This routine returns the bounds of the "global" X-Plane desktop, in boxels. + Unlike the non-global version XPLMGetScreenSize(), this is multi-monitor + aware. There are three primary consequences of multimonitor awareness. + + First, if the user is running X-Plane in full-screen on two or more + monitors (typically configured using one full-screen window per monitor), + the global desktop will be sized to include all X-Plane windows. + + Second, the origin of the screen coordinates is not guaranteed to be (0, + 0). Suppose the user has two displays side-by-side, both running at 1080p. + Suppose further that they've configured their OS to make the left display + their "primary" monitor, and that X-Plane is running in full-screen on + their right monitor only. In this case, the global desktop bounds would be + the rectangle from (1920, 0) to (3840, 1080). If the user later asked + X-Plane to draw on their primary monitor as well, the bounds would change + to (0, 0) to (3840, 1080). + + Finally, if the usable area of the virtual desktop is not a perfect + rectangle (for instance, because the monitors have different resolutions or + because one monitor is configured in the operating system to be above and + to the right of the other), the global desktop will include any wasted + space. Thus, if you have two 1080p monitors, and monitor 2 is configured to + have its bottom left touch monitor 1's upper right, your global desktop + area would be the rectangle from (0, 0) to (3840, 2160). + + Note that popped-out windows (windows drawn in their own operating system + windows, rather than "floating" within X-Plane) are not included in these + bounds. + } + PROCEDURE XPLMGetScreenBoundsGlobal( + outLeft : PInteger; { Can be nil } + outTop : PInteger; { Can be nil } + outRight : PInteger; { Can be nil } + outBottom : PInteger); { Can be nil } + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} + +{$IFDEF XPLM300} + { + XPLMReceiveMonitorBoundsGlobal_f + + This function is informed of the global bounds (in boxels) of a particular + monitor within the X-Plane global desktop space. Note that X-Plane must be + running in full screen on a monitor in order for that monitor to be passed + to you in this callback. + } +TYPE + XPLMReceiveMonitorBoundsGlobal_f = PROCEDURE( + inMonitorIndex : Integer; + inLeftBx : Integer; + inTopBx : Integer; + inRightBx : Integer; + inBottomBx : Integer; + inRefcon : pointer); cdecl; +{$ENDIF XPLM300} + +{$IFDEF XPLM300} + { + XPLMGetAllMonitorBoundsGlobal + + This routine immediately calls you back with the bounds (in boxels) of each + full-screen X-Plane window within the X-Plane global desktop space. Note + that if a monitor is *not* covered by an X-Plane window, you cannot get its + bounds this way. Likewise, monitors with only an X-Plane window (not in + full-screen mode) will not be included. + + If X-Plane is running in full-screen and your monitors are of the same size + and configured contiguously in the OS, then the combined global bounds of + all full-screen monitors will match the total global desktop bounds, as + returned by XPLMGetScreenBoundsGlobal(). (Of course, if X-Plane is running + in windowed mode, this will not be the case. Likewise, if you have + differently sized monitors, the global desktop space will include wasted + space.) + + Note that this function's monitor indices match those provided by + XPLMGetAllMonitorBoundsOS(), but the coordinates are different (since the + X-Plane global desktop may not match the operating system's global desktop, + and one X-Plane boxel may be larger than one pixel due to 150% or 200% + scaling). + } + PROCEDURE XPLMGetAllMonitorBoundsGlobal( + inMonitorBoundsCallback: XPLMReceiveMonitorBoundsGlobal_f; + inRefcon : pointer); + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} + +{$IFDEF XPLM300} + { + XPLMReceiveMonitorBoundsOS_f + + This function is informed of the global bounds (in pixels) of a particular + monitor within the operating system's global desktop space. Note that a + monitor index being passed to you here does not indicate that X-Plane is + running in full screen on this monitor, or even that any X-Plane windows + exist on this monitor. + } +TYPE + XPLMReceiveMonitorBoundsOS_f = PROCEDURE( + inMonitorIndex : Integer; + inLeftPx : Integer; + inTopPx : Integer; + inRightPx : Integer; + inBottomPx : Integer; + inRefcon : pointer); cdecl; +{$ENDIF XPLM300} + +{$IFDEF XPLM300} + { + XPLMGetAllMonitorBoundsOS + + This routine immediately calls you back with the bounds (in pixels) of each + monitor within the operating system's global desktop space. Note that + unlike XPLMGetAllMonitorBoundsGlobal(), this may include monitors that have + no X-Plane window on them. + + Note that this function's monitor indices match those provided by + XPLMGetAllMonitorBoundsGlobal(), but the coordinates are different (since + the X-Plane global desktop may not match the operating system's global + desktop, and one X-Plane boxel may be larger than one pixel). + } + PROCEDURE XPLMGetAllMonitorBoundsOS( + inMonitorBoundsCallback: XPLMReceiveMonitorBoundsOS_f; + inRefcon : pointer); + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} + + { + XPLMGetMouseLocation + + Deprecated in XPLM300. Modern windows should use + XPLMGetMouseLocationGlobal() instead. + + This routine returns the current mouse location in pixels relative to the + main X-Plane window. The bottom left corner of the main window is (0, 0). + Pass NULL to not receive info about either parameter. + + Because this function gives the mouse position relative to the main X-Plane + window (rather than in global bounds), this function should only be used by + legacy windows. Modern windows should instead get the mouse position in + global desktop coordinates using XPLMGetMouseLocationGlobal(). + + Note that unlike XPLMGetMouseLocationGlobal(), if the mouse goes outside + the user's main monitor (for instance, to a pop out window or a secondary + monitor), this function will not reflect it. + } + PROCEDURE XPLMGetMouseLocation( + outX : PInteger; { Can be nil } + outY : PInteger); { Can be nil } + cdecl; external XPLM_DLL; + +{$IFDEF XPLM300} + { + XPLMGetMouseLocationGlobal + + Returns the current mouse location in global desktop boxels. Unlike + XPLMGetMouseLocation(), the bottom left of the main X-Plane window is not + guaranteed to be (0, 0)---instead, the origin is the lower left of the + entire global desktop space. In addition, this routine gives the real mouse + location when the mouse goes to X-Plane windows other than the primary + display. Thus, it can be used with both pop-out windows and secondary + monitors. + + This is the mouse location function to use with modern windows (i.e., those + created by XPLMCreateWindowEx()). + + Pass NULL to not receive info about either parameter. + } + PROCEDURE XPLMGetMouseLocationGlobal( + outX : PInteger; { Can be nil } + outY : PInteger); { Can be nil } + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} { XPLMGetWindowGeometry - This routine returns the position and size of a window in cockpit pixels. - Pass NULL to not receive any paramter. + This routine returns the position and size of a window. The units and + coordinate system vary depending on the type of window you have. + + If this is a legacy window (one compiled against a pre-XPLM300 version of + the SDK, or an XPLM300 window that was not created using + XPLMCreateWindowEx()), the units are pixels relative to the main X-Plane + display. + + If, on the other hand, this is a new X-Plane 11-style window (compiled + against the XPLM300 SDK and created using XPLMCreateWindowEx()), the units + are global desktop boxels. + + Pass NULL to not receive any paramter. } PROCEDURE XPLMGetWindowGeometry( inWindowID : XPLMWindowID; - outLeft : Pinteger; { Can be nil } - outTop : Pinteger; { Can be nil } - outRight : Pinteger; { Can be nil } - outBottom : Pinteger); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outLeft : PInteger; { Can be nil } + outTop : PInteger; { Can be nil } + outRight : PInteger; { Can be nil } + outBottom : PInteger); { Can be nil } + cdecl; external XPLM_DLL; { XPLMSetWindowGeometry - This routine allows you to set the position or height aspects of a window. + This routine allows you to set the position and size of a window. + + The units and coordinate system match those of XPLMGetWindowGeometry(). + That is, modern windows use global desktop boxel coordinates, while legacy + windows use pixels relative to the main X-Plane display. + + Note that this only applies to "floating" windows (that is, windows that + are drawn within the X-Plane simulation windows, rather than being "popped + out" into their own first-class operating system windows). To set the + position of windows whose positioning mode is xplm_WindowPopOut, you'll + need to instead use XPLMSetWindowGeometryOS(). } PROCEDURE XPLMSetWindowGeometry( inWindowID : XPLMWindowID; - inLeft : integer; - inTop : integer; - inRight : integer; - inBottom : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inLeft : Integer; + inTop : Integer; + inRight : Integer; + inBottom : Integer); + cdecl; external XPLM_DLL; + +{$IFDEF XPLM300} + { + XPLMGetWindowGeometryOS + + This routine returns the position and size of a "popped out" window (i.e., + a window whose positioning mode is xplm_WindowPopOut), in operating system + pixels. Pass NULL to not receive any parameter. + } + PROCEDURE XPLMGetWindowGeometryOS( + inWindowID : XPLMWindowID; + outLeft : PInteger; { Can be nil } + outTop : PInteger; { Can be nil } + outRight : PInteger; { Can be nil } + outBottom : PInteger); { Can be nil } + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} + +{$IFDEF XPLM300} + { + XPLMSetWindowGeometryOS + + This routine allows you to set the position and size, in operating system + pixel coordinates, of a popped out window (that is, a window whose + positioning mode is xplm_WindowPopOut, which exists outside the X-Plane + simulation window, in its own first-class operating system window). + + Note that you are responsible for ensuring both that your window is popped + out (using XPLMWindowIsPoppedOut()) and that a monitor really exists at the + OS coordinates you provide (using XPLMGetAllMonitorBoundsOS()). + } + PROCEDURE XPLMSetWindowGeometryOS( + inWindowID : XPLMWindowID; + inLeft : Integer; + inTop : Integer; + inRight : Integer; + inBottom : Integer); + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} + +{$IFDEF XPLM301} + { + XPLMGetWindowGeometryVR + + Returns the width and height, in boxels, of a window in VR. Note that you + are responsible for ensuring your window is in VR (using + XPLMWindowIsInVR()). + } + PROCEDURE XPLMGetWindowGeometryVR( + inWindowID : XPLMWindowID; + outWidthBoxels : PInteger; { Can be nil } + outHeightBoxels : PInteger); { Can be nil } + cdecl; external XPLM_DLL; +{$ENDIF XPLM301} + +{$IFDEF XPLM301} + { + XPLMSetWindowGeometryVR + + This routine allows you to set the size, in boxels, of a window in VR (that + is, a window whose positioning mode is xplm_WindowVR). + + Note that you are responsible for ensuring your window is in VR (using + XPLMWindowIsInVR()). + } + PROCEDURE XPLMSetWindowGeometryVR( + inWindowID : XPLMWindowID; + widthBoxels : Integer; + heightBoxels : Integer); + cdecl; external XPLM_DLL; +{$ENDIF XPLM301} { XPLMGetWindowIsVisible - This routine returns whether a window is visible. + Returns true (1) if the specified window is visible. } FUNCTION XPLMGetWindowIsVisible( - inWindowID : XPLMWindowID) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inWindowID : XPLMWindowID) : Integer; + cdecl; external XPLM_DLL; { XPLMSetWindowIsVisible - This routine shows or hides a window. + This routine shows or hides a window. } PROCEDURE XPLMSetWindowIsVisible( inWindowID : XPLMWindowID; - inIsVisible : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inIsVisible : Integer); + cdecl; external XPLM_DLL; + +{$IFDEF XPLM300} + { + XPLMWindowIsPoppedOut + + True if this window has been popped out (making it a first-class window in + the operating system), which in turn is true if and only if you have set + the window's positioning mode to xplm_WindowPopOut. + + Only applies to modern windows. (Windows created using the deprecated + XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of + the SDK cannot be popped out.) + } + FUNCTION XPLMWindowIsPoppedOut( + inWindowID : XPLMWindowID) : Integer; + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} + +{$IFDEF XPLM301} + { + XPLMWindowIsInVR + + True if this window has been moved to the virtual reality (VR) headset, + which in turn is true if and only if you have set the window's positioning + mode to xplm_WindowVR. + + Only applies to modern windows. (Windows created using the deprecated + XPLMCreateWindow(), or windows compiled against a pre-XPLM301 version of + the SDK cannot be moved to VR.) + } + FUNCTION XPLMWindowIsInVR( + inWindowID : XPLMWindowID) : Integer; + cdecl; external XPLM_DLL; +{$ENDIF XPLM301} + +{$IFDEF XPLM300} + { + XPLMSetWindowGravity + + A window's "gravity" controls how the window shifts as the whole X-Plane + window resizes. A gravity of 1 means the window maintains its positioning + relative to the right or top edges, 0 the left/bottom, and 0.5 keeps it + centered. + + Default gravity is (0, 1, 0, 1), meaning your window will maintain its + position relative to the top left and will not change size as its + containing window grows. + + If you wanted, say, a window that sticks to the top of the screen (with a + constant height), but which grows to take the full width of the window, you + would pass (0, 1, 1, 1). Because your left and right edges would maintain + their positioning relative to their respective edges of the screen, the + whole width of your window would change with the X-Plane window. + + Only applies to modern windows. (Windows created using the deprecated + XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of + the SDK will simply get the default gravity.) + } + PROCEDURE XPLMSetWindowGravity( + inWindowID : XPLMWindowID; + inLeftGravity : Single; + inTopGravity : Single; + inRightGravity : Single; + inBottomGravity : Single); + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} + +{$IFDEF XPLM300} + { + XPLMSetWindowResizingLimits + + Sets the minimum and maximum size of the client rectangle of the given + window. (That is, it does not include any window styling that you might + have asked X-Plane to apply on your behalf.) All resizing operations are + constrained to these sizes. + + Only applies to modern windows. (Windows created using the deprecated + XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of + the SDK will have no minimum or maximum size.) + } + PROCEDURE XPLMSetWindowResizingLimits( + inWindowID : XPLMWindowID; + inMinWidthBoxels : Integer; + inMinHeightBoxels : Integer; + inMaxWidthBoxels : Integer; + inMaxHeightBoxels : Integer); + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} + +{$IFDEF XPLM300} + { + XPLMWindowPositioningMode + + XPLMWindowPositionMode describes how X-Plane will position your window on + the user's screen. X-Plane will maintain this positioning mode even as the + user resizes their window or adds/removes full-screen monitors. + + Positioning mode can only be set for "modern" windows (that is, windows + created using XPLMCreateWindowEx() and compiled against the XPLM300 SDK). + Windows created using the deprecated XPLMCreateWindow(), or windows + compiled against a pre-XPLM300 version of the SDK will simply get the + "free" positioning mode. + } +TYPE + XPLMWindowPositioningMode = ( + { The default positioning mode. Set the window geometry and its future } + { position will be determined by its window gravity, resizing limits, and } + { user interactions. } + xplm_WindowPositionFree = 0 + + { Keep the window centered on the monitor you specify } + ,xplm_WindowCenterOnMonitor = 1 + + { Keep the window full screen on the monitor you specify } + ,xplm_WindowFullScreenOnMonitor = 2 + + { Like gui_window_full_screen_on_monitor, but stretches over *all* monitors } + { and popout windows. This is an obscure one... unless you have a very good } + { reason to need it, you probably don't! } + ,xplm_WindowFullScreenOnAllMonitors = 3 + + { A first-class window in the operating system, completely separate from the } + { X-Plane window(s) } + ,xplm_WindowPopOut = 4 + +{$IFDEF XPLM301} + { A floating window visible on the VR headset } + ,xplm_WindowVR = 5 +{$ENDIF XPLM301} + + ); + PXPLMWindowPositioningMode = ^XPLMWindowPositioningMode; +{$ENDIF XPLM300} + +{$IFDEF XPLM300} + { + XPLMSetWindowPositioningMode + + Sets the policy for how X-Plane will position your window. + + Some positioning modes apply to a particular monitor. For those modes, you + can pass a negative monitor index to position the window on the main + X-Plane monitor (the screen with the X-Plane menu bar at the top). Or, if + you have a specific monitor you want to position your window on, you can + pass a real monitor index as received from, e.g., + XPLMGetAllMonitorBoundsOS(). + + Only applies to modern windows. (Windows created using the deprecated + XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of + the SDK will always use xplm_WindowPositionFree.) + } + PROCEDURE XPLMSetWindowPositioningMode( + inWindowID : XPLMWindowID; + inPositioningMode : XPLMWindowPositioningMode; + inMonitorIndex : Integer); + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} + +{$IFDEF XPLM300} + { + XPLMSetWindowTitle + + Sets the name for a window. This only applies to windows that opted-in to + styling as an X-Plane 11 floating window (i.e., with styling mode + xplm_WindowDecorationRoundRectangle) when they were created using + XPLMCreateWindowEx(). + } + PROCEDURE XPLMSetWindowTitle( + inWindowID : XPLMWindowID; + inWindowTitle : XPLMString); + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} { XPLMGetWindowRefCon - This routine returns a windows refcon, the unique value you can use for - your own purposes. + Returns a window's reference constant, the unique value you can use for + your own purposes. } FUNCTION XPLMGetWindowRefCon( inWindowID : XPLMWindowID) : pointer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMSetWindowRefCon - This routine sets a window's reference constant. Use this to pass data to - yourself in the callbacks. + Sets a window's reference constant. Use this to pass data to yourself in + the callbacks. } PROCEDURE XPLMSetWindowRefCon( inWindowID : XPLMWindowID; inRefcon : pointer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMTakeKeyboardFocus - This routine gives a specific window keyboard focus. Keystrokes will be - sent to that window. Pass a window ID of 0 to pass keyboard strokes - directly to X-Plane. + This routine gives a specific window keyboard focus. Keystrokes will be + sent to that window. Pass a window ID of 0 to remove keyboard focus from + any plugin-created windows and instead pass keyboard strokes directly to + X-Plane. } PROCEDURE XPLMTakeKeyboardFocus( inWindow : XPLMWindowID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; + + { + XPLMHasKeyboardFocus + + Returns true (1) if the indicated window has keyboard focus. Pass a window + ID of 0 to see if no plugin window has focus, and all keystrokes will go + directly to X-Plane. + } + FUNCTION XPLMHasKeyboardFocus( + inWindow : XPLMWindowID) : Integer; + cdecl; external XPLM_DLL; { XPLMBringWindowToFront - This routine brings the window to the front of the Z-order. Windows are - brought to the front when they are created...beyond that you should make - sure you are front before handling mouse clicks. + This routine brings the window to the front of the Z-order for its layer. + Windows are brought to the front automatically when they are created. + Beyond that, you should make sure you are front before handling mouse + clicks. + + Note that this only brings your window to the front of its layer + (XPLMWindowLayer). Thus, if you have a window in the floating window layer + (xplm_WindowLayerFloatingWindows), but there is a modal window (in layer + xplm_WindowLayerModal) above you, you would still not be the true frontmost + window after calling this. (After all, the window layers are strictly + ordered, and no window in a lower layer can ever be above any window in a + higher one.) } PROCEDURE XPLMBringWindowToFront( inWindow : XPLMWindowID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMIsWindowInFront - This routine returns true if you pass inthe ID of the frontmost visible - window. + This routine returns true if the window you passed in is the frontmost + visible window in its layer (XPLMWindowLayer). + + Thus, if you have a window at the front of the floating window layer + (xplm_WindowLayerFloatingWindows), this will return true even if there is a + modal window (in layer xplm_WindowLayerModal) above you. (Not to worry, + though: in such a case, X-Plane will not pass clicks or keyboard input down + to your layer until the window above stops "eating" the input.) + + Note that legacy windows are always placed in layer + xplm_WindowLayerFlightOverlay, while modern-style windows default to + xplm_WindowLayerFloatingWindows. This means it's perfectly consistent to + have two different plugin-created windows (one legacy, one modern) *both* + be in the front (of their different layers!) at the same time. } FUNCTION XPLMIsWindowInFront( - inWindow : XPLMWindowID) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inWindow : XPLMWindowID) : Integer; + cdecl; external XPLM_DLL; + +{___________________________________________________________________________ + * KEY SNIFFERS + ___________________________________________________________________________} +{ + Low-level keyboard handlers. Allows for intercepting keystrokes outside the + normal rules of the user interface. +} + + + { + XPLMKeySniffer_f + + This is the prototype for a low level key-sniffing function. Window-based + UI _should not use this_! The windowing system provides high-level + mediated keyboard access, via the callbacks you attach to your + XPLMCreateWindow_t. By comparison, the key sniffer provides low level + keyboard access. + + Key sniffers are provided to allow libraries to provide non-windowed user + interaction. For example, the MUI library uses a key sniffer to do pop-up + text entry. + + Return 1 to pass the key on to the next sniffer, the window manager, + X-Plane, or whomever is down stream. Return 0 to consume the key. + + Warning: this API declares virtual keys as a signed character; however the + VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values + (that is 0x80 instead of -0x80). So you may need to cast the incoming vkey + to an unsigned char to get correct comparisons in C. + } +TYPE + XPLMKeySniffer_f = FUNCTION( + inChar : XPLMChar; + inFlags : XPLMKeyFlags; + inVirtualKey : XPLMChar; + inRefcon : pointer) : Integer; cdecl; + + { + XPLMRegisterKeySniffer + + This routine registers a key sniffing callback. You specify whether you + want to sniff before the window system, or only sniff keys the window + system does not consume. You should ALMOST ALWAYS sniff non-control keys + after the window system. When the window system consumes a key, it is + because the user has "focused" a window. Consuming the key or taking + action based on the key will produce very weird results. Returns + 1 if successful. + } + FUNCTION XPLMRegisterKeySniffer( + inCallback : XPLMKeySniffer_f; + inBeforeWindows : Integer; + inRefcon : pointer) : Integer; + cdecl; external XPLM_DLL; + + { + XPLMUnregisterKeySniffer + + This routine unregisters a key sniffer. You must unregister a key sniffer + for every time you register one with the exact same signature. Returns 1 + if successful. + } + FUNCTION XPLMUnregisterKeySniffer( + inCallback : XPLMKeySniffer_f; + inBeforeWindows : Integer; + inRefcon : pointer) : Integer; + cdecl; external XPLM_DLL; {___________________________________________________________________________ * HOT KEYS ___________________________________________________________________________} { - Hot Keys - keystrokes that can be managed by others. + Keystrokes that can be managed by others. These are lower-level than window + keyboard handlers (i.e., callbacks you attach to your XPLMCreateWindow_t), + but higher level than key sniffers. } - { XPLMHotKey_f - Your hot key callback simply takes a pointer of your choosing. + Your hot key callback simply takes a pointer of your choosing. } TYPE XPLMHotKey_f = PROCEDURE( @@ -732,7 +1550,7 @@ TYPE { XPLMHotKeyID - Hot keys are identified by opaque IDs. + An opaque ID used to identify a hot key. } XPLMHotKeyID = pointer; PXPLMHotKeyID = ^XPLMHotKeyID; @@ -740,96 +1558,73 @@ TYPE { XPLMRegisterHotKey - This routine registers a hot key. You specify your preferred key stroke - virtual key/flag combination, a description of what your callback does (so - other plug-ins can describe the plug-in to the user for remapping) and a - callback function and opaque pointer to pass in). A new hot key ID is - returned. During execution, the actual key associated with your hot key - may change, but you are insulated from this. + This routine registers a hot key. You specify your preferred key stroke + virtual key/flag combination, a description of what your callback does (so + other plug-ins can describe the plug-in to the user for remapping) and a + callback function and opaque pointer to pass in). A new hot key ID is + returned. During execution, the actual key associated with your hot key + may change, but you are insulated from this. } FUNCTION XPLMRegisterHotKey( - inVirtualKey : char; + inVirtualKey : XPLMChar; inFlags : XPLMKeyFlags; - inDescription : Pchar; + inDescription : XPLMString; inCallback : XPLMHotKey_f; inRefcon : pointer) : XPLMHotKeyID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMUnregisterHotKey - This API unregisters a hot key. You can only register your own hot keys. + Unregisters a hot key. You can only unregister your own hot keys. } PROCEDURE XPLMUnregisterHotKey( inHotKey : XPLMHotKeyID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMCountHotKeys - Returns the number of current hot keys. + Returns the number of current hot keys. } - FUNCTION XPLMCountHotKeys: integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + FUNCTION XPLMCountHotKeys: Integer; + cdecl; external XPLM_DLL; { XPLMGetNthHotKey - Returns a hot key by index, for iteration on all hot keys. + Returns a hot key by index, for iteration on all hot keys. } FUNCTION XPLMGetNthHotKey( - inIndex : integer) : XPLMHotKeyID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inIndex : Integer) : XPLMHotKeyID; + cdecl; external XPLM_DLL; { XPLMGetHotKeyInfo - Returns information about the hot key. Return NULL for any parameter you - don't want info about. The description should be at least 512 chars long. + Returns information about the hot key. Return NULL for any parameter you + don't want info about. The description should be at least 512 chars long. } PROCEDURE XPLMGetHotKeyInfo( inHotKey : XPLMHotKeyID; - outVirtualKey : Pchar; { Can be nil } + outVirtualKey : XPLMString; { Can be nil } outFlags : PXPLMKeyFlags; { Can be nil } - outDescription : Pchar; { Can be nil } + outDescription : XPLMString; { Can be nil } outPlugin : PXPLMPluginID); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMSetHotKeyCombination - XPLMSetHotKeyCombination remaps a hot keys keystrokes. You may remap - another plugin's keystrokes. + Remaps a hot key's keystrokes. You may remap another plugin's keystrokes. } PROCEDURE XPLMSetHotKeyCombination( inHotKey : XPLMHotKeyID; - inVirtualKey : char; + inVirtualKey : XPLMChar; inFlags : XPLMKeyFlags); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMGraphics.pas b/XPSDK/Delphi/XPLM/XPLMGraphics.pas index 713f14a..20ff61a 100644 --- a/XPSDK/Delphi/XPLM/XPLMGraphics.pas +++ b/XPSDK/Delphi/XPLM/XPLMGraphics.pas @@ -1,75 +1,76 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMGraphics; INTERFACE { - Graphics routines for X-Plane and OpenGL. + A few notes on coordinate systems: - A few notes on coordinate systems: + X-Plane uses three kinds of coordinates. Global coordinates are specified + as latitude, longitude and elevation. This coordinate system never changes + but is not very precise. - X-Plane uses three kinds of coordinates. Global coordinates are specified - as latitude, longitude and elevation. This coordinate system never changes - but is not very precise. + OpenGL (or 'local') coordinates are cartesian and shift with the plane. + They offer more precision and are used for 3-d OpenGL drawing. The X axis + is aligned east-west with positive X meaning east. The Y axis is aligned + straight up and down at the point 0,0,0 (but since the earth is round it is + not truly straight up and down at other points). The Z axis is aligned + north-south at 0, 0, 0 with positive Z pointing south (but since the earth + is round it isn't exactly north-south as you move east or west of 0, 0, 0). + One unit is one meter and the point 0,0,0 is on the surface of the earth at + sea level for some latitude and longitude picked by the sim such that the + user's aircraft is reasonably nearby. - OpenGL (or 'local') coordinates are cartesian and shift with the plane. - They offer more precision and are used for 3-d OpenGL drawing. The X axis - is aligned east-west with positive X meaning east. The Y axis is aligned - straight up and down at the point 0,0,0 (but since the earth is round it is - not truly straight up and down at other points). The Z axis is aligned - north-south at 0, 0, 0 with positive Z pointing south (but since the earth - is round it isn't exactly north-south as you move east or west of 0, 0, 0). - One unit is one meter and the point 0,0,0 is on the surface of the earth - at sea level for some latitude and longitude picked by the sim such that - the user's aircraft is reasonably nearby. + 2-d Panel coordinates are 2d, with the X axis horizontal and the Y axis + vertical. The point 0,0 is the bottom left and 1024,768 is the upper + right of the screen. This is true no matter what resolution the user's + monitor is in; when running in higher resolution, graphics will be + scaled. - Cockpit coordinates are 2d, with the X axis horizontal and the Y axis - vertical. The point 0,0 is the bottom left and 1024,768 is the upper right - of the screen. This is true no matter what resolution the user's monitor is - in; when running in higher resolution, graphics will be scaled. - - Use X-Plane's routines to convert between global and local coordinates. Do - not attempt to do this conversion yourself; the precise 'roundness' of - X-Plane's physics model may not match your own, and (to make things - weirder) the user can potentially customize the physics of the current - planet. + Use X-Plane's routines to convert between global and local coordinates. Do + not attempt to do this conversion yourself; the precise 'roundness' of + X-Plane's physics model may not match your own, and (to make things + weirder) the user can potentially customize the physics of the current + planet. } -USES XPLMDefs; +USES + XPLMDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * X-PLANE GRAPHICS ___________________________________________________________________________} { - These routines allow you to use OpenGL with X-Plane. + These routines allow you to use OpenGL with X-Plane. } - { XPLMTextureID - XPLM Texture IDs name well-known textures in the sim for you to use. This - allows you to recycle textures from X-Plane, saving VRAM. + XPLM Texture IDs name well-known textures in the sim for you to use. This + allows you to recycle textures from X-Plane, saving VRAM. + + *Warning*: do not use these enums. The only remaining use they have is to + access the legacy compatibility v10 UI texture; if you need this, get it + via the Widgets library. } TYPE XPLMTextureID = ( - { The bitmap that contains window outlines, button outlines, fonts, etc. } + { The bitmap that contains window outlines, button outlines, fonts, etc. } xplm_Tex_GeneralInterface = 0 - { The exterior paint for the user's aircraft (daytime). } +{$IFDEF XPLM_DEPRECATED} + { The exterior paint for the user's aircraft (daytime). } ,xplm_Tex_AircraftPaint = 1 +{$ENDIF XPLM_DEPRECATED} - { The exterior light map for the user's aircraft. } +{$IFDEF XPLM_DEPRECATED} + { The exterior light map for the user's aircraft. } ,xplm_Tex_AircraftLiteMap = 2 +{$ENDIF XPLM_DEPRECATED} ); PXPLMTextureID = ^XPLMTextureID; @@ -77,274 +78,270 @@ TYPE { XPLMSetGraphicsState - XPLMSetGraphicsState changes OpenGL's graphics state in a number of ways: + XPLMSetGraphicsState changes OpenGL's fixed function pipeline state. You + are not responsible for restoring any state that is accessed via + XPLMSetGraphicsState, but you are responsible for not accessing this state + directly. - inEnableFog - enables or disables fog, equivalent to: glEnable(GL_FOG); + - inEnableFog - enables or disables fog, equivalent to: glEnable(GL_FOG); + - inNumberTexUnits - enables or disables a number of multitexturing units. + If the number is 0, 2d texturing is disabled entirely, as in + glDisable(GL_TEXTURE_2D); Otherwise, 2d texturing is enabled, and a + number of multitexturing units are enabled sequentially, starting with + unit 0, e.g. glActiveTextureARB(GL_TEXTURE0_ARB); glEnable + (GL_TEXTURE_2D); + - inEnableLighting - enables or disables OpenGL lighting, e.g. + glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); + - inEnableAlphaTesting - enables or disables the alpha test per pixel, e.g. + glEnable(GL_ALPHA_TEST); + - inEnableAlphaBlending - enables or disables alpha blending per pixel, + e.g. glEnable(GL_BLEND); + - inEnableDepthTesting - enables per pixel depth testing, as in + glEnable(GL_DEPTH_TEST); + - inEnableDepthWriting - enables writing back of depth information to the + depth bufffer, as in glDepthMask(GL_TRUE); - inNumberTexUnits - enables or disables a number of multitexturing units. If - the number is 0, 2d texturing is disabled entirely, as in - glDisable(GL_TEXTURE_2D); Otherwise, 2d texturing is enabled, and a - number of multitexturing units are enabled sequentially, starting with - unit 0, e.g. glActiveTextureARB(GL_TEXTURE0_ARB); glEnable - (GL_TEXTURE_2D); + The purpose of this function is to change OpenGL state while keeping + X-Plane aware of the state changes; this keeps X-Plane from getting + surprised by OGL state changes, and prevents X-Plane and plug-ins from + having to set all state before all draws; XPLMSetGraphicsState internally + skips calls to change state that is already properly enabled. - inEnableLighting - enables or disables OpenGL lighting, e.g. - glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); + X-Plane does not have a 'default' OGL state for plug-ins with respect to + the above state vector; plug-ins should totally set OGL state using this + API before drawing. Use XPLMSetGraphicsState instead of any of the above + OpenGL calls. - inEnableAlphaTesting - enables or disables the alpha test per pixel, e.g. - glEnable(GL_ALPHA_TEST); + WARNING: Any routine that performs drawing (e.g. XPLMDrawString or widget + code) may change X-Plane's state. Always set state before drawing after + unknown code has executed. - inEnableAlphaBlending - enables or disables alpha blending per pixel, e.g. - glEnable(GL_BLEND); - - inEnableDepthTesting - enables per pixel depth testing, as in - glEnable(GL_DEPTH_TEST); - - inEnableDepthWriting - enables writing back of depth information to the - depth bufffer, as in glDepthMask(GL_TRUE); - - The purpose of this function is to change OpenGL state while keeping - X-Plane aware of the state changes; this keeps X-Plane from getting - surprised by OGL state changes, and prevents X-Plane and plug-ins from - having to set all state before all draws; XPLMSetGraphicsState internally - skips calls to change state that is already properly enabled. - - X-Plane does not have a 'default' OGL state to plug-ins; plug-ins should - totally set OGL state before drawing. Use XPLMSetGraphicsState instead of - any of the above OpenGL calls. - - WARNING: Any routine that performs drawing (e.g. XPLMDrawString or widget - code) may change X-Plane's state. Always set state before drawing after - unknown code has executed. + *Deprecation Warnings*: X-Plane's lighting and fog environemnt is + significantly more complex than the fixed function pipeline can express; + do not assume that lighting and fog state is a good approximation for 3-d + drawing. Prefer to use XPLMInstancing to draw objects. All calls to + XPLMSetGraphicsState should have no fog or lighting. } PROCEDURE XPLMSetGraphicsState( - inEnableFog : integer; - inNumberTexUnits : integer; - inEnableLighting : integer; - inEnableAlphaTesting: integer; - inEnableAlphaBlending: integer; - inEnableDepthTesting: integer; - inEnableDepthWriting: integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inEnableFog : Integer; + inNumberTexUnits : Integer; + inEnableLighting : Integer; + inEnableAlphaTesting: Integer; + inEnableAlphaBlending: Integer; + inEnableDepthTesting: Integer; + inEnableDepthWriting: Integer); + cdecl; external XPLM_DLL; { XPLMBindTexture2d - XPLMBindTexture2d changes what texture is bound to the 2d texturing target. - This routine caches the current 2d texture across all texturing units in - the sim and plug-ins, preventing extraneous binding. For example, consider - several plug-ins running in series; if they all use the 'general interface' - bitmap to do UI, calling this function will skip the rebinding of the - general interface texture on all but the first plug-in, which can provide - better frame rate son some graphics cards. + XPLMBindTexture2d changes what texture is bound to the 2d texturing + target. This routine caches the current 2d texture across all texturing + units in the sim and plug-ins, preventing extraneous binding. For + example, consider several plug-ins running in series; if they all use the + 'general interface' bitmap to do UI, calling this function will skip the + rebinding of the general interface texture on all but the first plug-in, + which can provide better frame rate son some graphics cards. - inTextureID is the ID of the texture object to bind; inTextureUnit is a - zero-based texture unit (e.g. 0 for the first one), up to a maximum of 4 - units. (This number may increase in future versions of x-plane.) + inTextureID is the ID of the texture object to bind; inTextureUnit is a + zero-based texture unit (e.g. 0 for the first one), up to a maximum of 4 + units. (This number may increase in future versions of X-Plane.) - Use this routine instead of glBindTexture(GL_TEXTURE_2D, ....); + Use this routine instead of glBindTexture(GL_TEXTURE_2D, ....); } PROCEDURE XPLMBindTexture2d( - inTextureNum : integer; - inTextureUnit : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inTextureNum : Integer; + inTextureUnit : Integer); + cdecl; external XPLM_DLL; { XPLMGenerateTextureNumbers - This routine generates unused texture numbers that a plug-in can use to - safely bind textures. Use this routine instead of glGenTextures; - glGenTextures will allocate texture numbers in ranges that X-Plane reserves - for its own use but does not always use; for example, it might provide an - ID within the range of textures reserved for terrain...loading a new .env - file as the plane flies might then cause X-Plane to use this texture ID. - X-Plane will then overwrite the plug-ins texture. This routine returns - texture IDs that are out of X-Plane's usage range. + Use this routine instead of glGenTextures to generate new texture object + IDs. This routine historically ensured that plugins don't use texure IDs + that X-Plane is reserving for its own use. } PROCEDURE XPLMGenerateTextureNumbers( - outTextureIDs : Pinteger; - inCount : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outTextureIDs : PInteger; + inCount : Integer); + cdecl; external XPLM_DLL; +{$IFDEF XPLM_DEPRECATED} { XPLMGetTexture - XPLMGetTexture returns the OpenGL texture enumeration of an X-Plane texture - based on a generic identifying code. For example, you can get the texture - for X-Plane's UI bitmaps. This allows you to build new gauges that take - advantage of x-plane's textures, for smooth artwork integration and also - saving texture memory. Note that the texture might not be loaded yet, - depending on what the plane's panel contains. - - OPEN ISSUE: We really need a way to make sure X-Plane loads this texture if - it isn't around, or at least a way to find out whether it is loaded or not. + XPLMGetTexture returns the OpenGL texture ID of an X-Plane texture based on + a generic identifying code. For example, you can get the texture for + X-Plane's UI bitmaps. } FUNCTION XPLMGetTexture( - inTexture : XPLMTextureID) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inTexture : XPLMTextureID) : Integer; + cdecl; external XPLM_DLL; +{$ENDIF XPLM_DEPRECATED} { XPLMWorldToLocal - This routine translates coordinates from latitude, longitude, and altitude - to local scene coordinates. Latitude and longitude are in decimal degrees, - and altitude is in meters MSL (mean sea level). The XYZ coordinates are in - meters in the local OpenGL coordinate system. + This routine translates coordinates from latitude, longitude, and altitude + to local scene coordinates. Latitude and longitude are in decimal degrees, + and altitude is in meters MSL (mean sea level). The XYZ coordinates are in + meters in the local OpenGL coordinate system. } PROCEDURE XPLMWorldToLocal( - inLatitude : real; - inLongitude : real; - inAltitude : real; - outX : Preal; - outY : Preal; - outZ : Preal); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inLatitude : Real; + inLongitude : Real; + inAltitude : Real; + outX : PReal; + outY : PReal; + outZ : PReal); + cdecl; external XPLM_DLL; { XPLMLocalToWorld - This routine translates a local coordinate triplet back into latitude, - longitude, and altitude. Latitude and longitude are in decimal degrees, - and altitude is in meters MSL (mean sea level). The XYZ coordinates are in - meters in the local OpenGL coordinate system. + This routine translates a local coordinate triplet back into latitude, + longitude, and altitude. Latitude and longitude are in decimal degrees, + and altitude is in meters MSL (mean sea level). The XYZ coordinates are in + meters in the local OpenGL coordinate system. - NOTE: world coordinates are less precise than local coordinates; you should - try to avoid round tripping from local to world and back. + NOTE: world coordinates are less precise than local coordinates; you should + try to avoid round tripping from local to world and back. } PROCEDURE XPLMLocalToWorld( - inX : real; - inY : real; - inZ : real; - outLatitude : Preal; - outLongitude : Preal; - outAltitude : Preal); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inX : Real; + inY : Real; + inZ : Real; + outLatitude : PReal; + outLongitude : PReal; + outAltitude : PReal); + cdecl; external XPLM_DLL; { XPLMDrawTranslucentDarkBox - This routine draws a translucent dark box, partially obscuring parts of the - screen but making text easy to read. This is the same graphics primitive - used by X-Plane to show text files and ATC info. + This routine draws a translucent dark box, partially obscuring parts of the + screen but making text easy to read. This is the same graphics primitive + used by X-Plane to show text files and ATC info. } PROCEDURE XPLMDrawTranslucentDarkBox( - inLeft : integer; - inTop : integer; - inRight : integer; - inBottom : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inLeft : Integer; + inTop : Integer; + inRight : Integer; + inBottom : Integer); + cdecl; external XPLM_DLL; {___________________________________________________________________________ * X-PLANE TEXT ___________________________________________________________________________} -{ - -} - - { XPLMFontID - X-Plane features some fixed-character fonts. Each font may have its own - metrics. + X-Plane features some fixed-character fonts. Each font may have its own + metrics. - WARNING: Some of these fonts are no longer supported or may have changed - geometries. For maximum copmatibility, see the comments below. + WARNING: Some of these fonts are no longer supported or may have changed + geometries. For maximum copmatibility, see the comments below. - Note: X-Plane 7 supports proportional-spaced fonts. Since no measuring - routine is available yet, the SDK will normally draw using a fixed-width - font. You can use a dataref to enable proportional font drawing on XP7 if - you want to. + Note: X-Plane 7 supports proportional-spaced fonts. Since no measuring + routine is available yet, the SDK will normally draw using a fixed-width + font. You can use a dataref to enable proportional font drawing on XP7 if + you want to. } TYPE XPLMFontID = ( - { Mono-spaced font for user interface. Available in all versions of the SDK. } + { Mono-spaced font for user interface. Available in all versions of the SDK.} xplmFont_Basic = 0 - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_Menus = 1 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_Metal = 2 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_Led = 3 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_LedWide = 4 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_PanelHUD = 5 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_PanelEFIS = 6 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_PanelGPS = 7 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_RadiosGA = 8 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_RadiosBC = 9 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_RadiosHM = 10 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_RadiosGANarrow = 11 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_RadiosBCNarrow = 12 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_RadiosHMNarrow = 13 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_Timer = 14 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_FullRound = 15 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_SmallRound = 16 +{$ENDIF XPLM_DEPRECATED} - { Deprecated, do not use. } +{$IFDEF XPLM_DEPRECATED} + { Deprecated, do not use. } ,xplmFont_Menus_Localized = 17 +{$ENDIF XPLM_DEPRECATED} {$IFDEF XPLM200} - { Proportional UI font. } + { Proportional UI font. } ,xplmFont_Proportional = 18 -{$ENDIF} +{$ENDIF XPLM200} ); PXPLMFontID = ^XPLMFontID; @@ -352,90 +349,76 @@ TYPE { XPLMDrawString - This routine draws a NULL termianted string in a given font. Pass in the - lower left pixel that the character is to be drawn onto. Also pass the - character and font ID. This function returns the x offset plus the width of - all drawn characters. The color to draw in is specified as a pointer to an - array of three floating point colors, representing RGB intensities from 0.0 - to 1.0. + This routine draws a NULL termianted string in a given font. Pass in the + lower left pixel that the character is to be drawn onto. Also pass the + character and font ID. This function returns the x offset plus the width of + all drawn characters. The color to draw in is specified as a pointer to an + array of three floating point colors, representing RGB intensities from 0.0 + to 1.0. } PROCEDURE XPLMDrawString( - inColorRGB : Psingle; - inXOffset : integer; - inYOffset : integer; - inChar : Pchar; - inWordWrapWidth : Pinteger; { Can be nil } + inColorRGB : PSingle; + inXOffset : Integer; + inYOffset : Integer; + inChar : XPLMString; + inWordWrapWidth : PInteger; { Can be nil } inFontID : XPLMFontID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMDrawNumber - This routine draws a number similar to the digit editing fields in - PlaneMaker and data output display in X-Plane. Pass in a color, a - position, a floating point value, and formatting info. Specify how many - integer and how many decimal digits to show and whether to show a sign, as - well as a character set. This routine returns the xOffset plus width of the - string drawn. + This routine draws a number similar to the digit editing fields in + PlaneMaker and data output display in X-Plane. Pass in a color, a + position, a floating point value, and formatting info. Specify how many + integer and how many decimal digits to show and whether to show a sign, as + well as a character set. This routine returns the xOffset plus width of the + string drawn. } PROCEDURE XPLMDrawNumber( - inColorRGB : Psingle; - inXOffset : integer; - inYOffset : integer; - inValue : real; - inDigits : integer; - inDecimals : integer; - inShowSign : integer; + inColorRGB : PSingle; + inXOffset : Integer; + inYOffset : Integer; + inValue : Real; + inDigits : Integer; + inDecimals : Integer; + inShowSign : Integer; inFontID : XPLMFontID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMGetFontDimensions - This routine returns the width and height of a character in a given font. - It also tells you if the font only supports numeric digits. Pass NULL if - you don't need a given field. Note that for a proportional font the width - will be an arbitrary, hopefully average width. + This routine returns the width and height of a character in a given font. + It also tells you if the font only supports numeric digits. Pass NULL if + you don't need a given field. Note that for a proportional font the width + will be an arbitrary, hopefully average width. } PROCEDURE XPLMGetFontDimensions( inFontID : XPLMFontID; - outCharWidth : Pinteger; { Can be nil } - outCharHeight : Pinteger; { Can be nil } - outDigitsOnly : Pinteger); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outCharWidth : PInteger; { Can be nil } + outCharHeight : PInteger; { Can be nil } + outDigitsOnly : PInteger); { Can be nil } + cdecl; external XPLM_DLL; {$IFDEF XPLM200} { XPLMMeasureString - This routine returns the width in pixels of a string using a given font. - The string is passed as a pointer plus length (and does not need to be null - terminated); this is used to allow for measuring substrings. The return - value is floating point; it is possible that future font drawing may allow - for fractional pixels. + This routine returns the width in pixels of a string using a given font. + The string is passed as a pointer plus length (and does not need to be null + terminated); this is used to allow for measuring substrings. The return + value is floating point; it is possible that future font drawing may allow + for fractional pixels. } FUNCTION XPLMMeasureString( inFontID : XPLMFontID; - inChar : Pchar; - inNumChars : integer) : single; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} + inChar : XPLMString; + inNumChars : Integer) : Single; + cdecl; external XPLM_DLL; +{$ENDIF XPLM200} + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMInstance.pas b/XPSDK/Delphi/XPLM/XPLMInstance.pas new file mode 100644 index 0000000..a38d2bb --- /dev/null +++ b/XPSDK/Delphi/XPLM/XPLMInstance.pas @@ -0,0 +1,125 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMInstance; +INTERFACE +{ + This API provides instanced drawing of X-Plane objects (.obj files). In + contrast to old drawing APIs, which required you to draw your own objects + per-frame, the instancing API allows you to simply register an OBJ for + drawing, then move or manipulate it later (as needed). + + This provides one tremendous benefit: it keeps all dataref operations for + your object in one place. Because datarefs are main thread only, allowing + dataref access anywhere is a serious performance bottleneck for the + simulator---the whole simulator has to pause and wait for each dataref + access. This performance penalty will only grow worse as X-Plane moves + toward an ever more heavily multithreaded engine. + + The instancing API allows X-Plane to isolate all dataref manipulations for + all plugin object drawing to one place, potentially providing huge + performance gains. + + Here's how it works: + + When an instance is created, it provides a list of all datarefs you want to + manipulate in for the OBJ in the future. This list of datarefs replaces the + ad-hoc collections of dataref objects previously used by art assets. Then, + per-frame, you can manipulate the instance by passing in a "block" of + packed floats representing the current values of the datarefs for your + instance. (Note that the ordering of this set of packed floats must exactly + match the ordering of the datarefs when you created your instance.) +} + +USES + XPLMDefs, XPLMScenery; + {$A4} +{___________________________________________________________________________ + * Instance Creation and Destruction + ___________________________________________________________________________} +{ + Registers and unregisters instances. +} + + +TYPE + { + XPLMInstanceRef + + An opaque handle to an instance. + } + XPLMInstanceRef = pointer; + PXPLMInstanceRef = ^XPLMInstanceRef; + + { + XPLMCreateInstance + + XPLMCreateInstance creates a new instance, managed by your plug-in, and + returns a handle to the instance. A few important requirements: + + * The object passed in must be fully loaded and returned from the XPLM + before you can create your instance; you cannot pass a null obj ref, nor + can you change the ref later. + + * If you use any custom datarefs in your object, they must be registered + before the object is loaded. This is true even if their data will be + provided via the instance dataref list. + + * The instance dataref array must be a valid ptr to an array of at least + one item that is null terminated. That is, if you do not want any + datarefs, you must passa ptr to an array with a null item. You cannot + pass null for this. + } + FUNCTION XPLMCreateInstance( + obj : XPLMObjectRef; + datarefs : PXPLMString) : XPLMInstanceRef; + cdecl; external XPLM_DLL; + + { + XPLMDestroyInstance + + XPLMDestroyInstance destroys and deallocates your instance; once called, + you are still responsible for releasing the OBJ ref. + + Tip: you can release your OBJ ref after you call XPLMCreateInstance as long + as you never use it again; the instance will maintain its own reference to + the OBJ and the object OBJ be deallocated when the instance is destroyed. + } + PROCEDURE XPLMDestroyInstance( + instance : XPLMInstanceRef); + cdecl; external XPLM_DLL; + +{___________________________________________________________________________ + * Instance Manipulation + ___________________________________________________________________________} + + { + XPLMInstanceSetPosition + + Updates both the position of the instance and all datarefs you registered + for it. Call this from a flight loop callback or UI callback. + + __DO NOT__ call XPLMInstanceSetPosition from a drawing callback; the whole + point of instancing is that you do not need any drawing callbacks. Setting + instance data from a drawing callback may have undefined consequences, and + the drawing callback hurts FPS unnecessarily. + + The memory pointed to by the data pointer must be large enough to hold one + float for every data ref you have registered, and must contain valid + floating point data. + + BUG: before X-Plane 11.50, if you have no dataref registered, you must + still pass a valid pointer for data and not null. + } + PROCEDURE XPLMInstanceSetPosition( + instance : XPLMInstanceRef; + new_position : PXPLMDrawInfo_t; + data : PSingle); + cdecl; external XPLM_DLL; + + +IMPLEMENTATION + +END. diff --git a/XPSDK/Delphi/XPLM/XPLMMap.pas b/XPSDK/Delphi/XPLM/XPLMMap.pas new file mode 100644 index 0000000..ea00ee0 --- /dev/null +++ b/XPSDK/Delphi/XPLM/XPLMMap.pas @@ -0,0 +1,608 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMMap; +INTERFACE +{ + This API allows you to create new layers within X-Plane maps. Your layers + can draw arbitrary OpenGL, but they conveniently also have access to + X-Plane's built-in icon and label drawing functions. + + As of X-Plane 11, map drawing happens in three stages: + + 1. backgrounds and "fill," + 2. icons, and + 3. labels. + + Thus, all background drawing gets layered beneath all icons, which likewise + get layered beneath all labels. Within each stage, the map obeys a + consistent layer ordering, such that "fill" layers (layers that cover a + large amount of map area, like the terrain and clouds) appear beneath + "markings" layers (like airport icons). This ensures that layers with fine + details don't get obscured by layers with larger details. + + The XPLM map API reflects both aspects of this draw layering: you can + register a layer as providing either markings or fill, and X-Plane will + draw your fill layers beneath your markings layers (regardless of + registration order). Likewise, you are guaranteed that your layer's icons + (added from within an icon callback) will go above your layer's OpenGL + drawing, and your labels will go above your icons. + + The XPLM guarantees that all plugin-created fill layers go on top of all + native X-Plane fill layers, and all plugin-created markings layers go on + top of all X-Plane markings layers (with the exception of the aircraft + icons). It also guarantees that the draw order of your own plugin's layers + will be consistent. But, for layers created by different plugins, the only + guarantee is that we will draw all of one plugin's layers of each type + (fill, then markings), then all of the others'; we don't guarantee which + plugin's fill and markings layers go on top of the other's. + + As of X-Plane 11, maps use true cartographic projections for their drawing, + and different maps may use different projections. For that reason, all + drawing calls include an opaque handle for the projection you should use to + do the drawing. Any time you would draw at a particular latitude/longitude, + you'll need to ask the projection to translate that position into "map + coordinates." (Note that the projection is guaranteed not to change between + calls to your prepare-cache hook, so if you cache your map coordinates + ahead of time, there's no need to re-project them when you actually draw.) + + In addition to mapping normal latitude/longitude locations into map + coordinates, the projection APIs also let you know the current heading for + north. (Since X-Plane 11 maps can rotate to match the heading of the user's + aircraft, it's not safe to assume that north is at zero degrees rotation.) +} + +USES + XPLMDefs; + {$A4} +{$IFDEF XPLM300} +{___________________________________________________________________________ + * DRAWING CALLBACKS + ___________________________________________________________________________} +{ + When you create a new map layer (using XPLMCreateMapLayer), you can provide + any or all of these callbacks. They allow you to insert your own OpenGL + drawing, text labels, and icons into the X-Plane map at the appropriate + places, allowing your layer to behave as similarly to X-Plane's built-in + layers as possible. +} + + +TYPE + { + XPLMMapLayerID + + This is an opaque handle for a plugin-created map layer. Pass it to the map + drawing APIs from an appropriate callback to draw in the layer you created. + } + XPLMMapLayerID = pointer; + PXPLMMapLayerID = ^XPLMMapLayerID; + + { + XPLMMapProjectionID + + This is an opaque handle for a map projection. Pass it to the projection + APIs to translate between map coordinates and latitude/longitudes. + } + XPLMMapProjectionID = pointer; + PXPLMMapProjectionID = ^XPLMMapProjectionID; + + { + XPLMMapStyle + + Indicates the visual style being drawn by the map. In X-Plane, the user can + choose between a number of map types, and different map types may have use + a different visual representation for the same elements (for instance, the + visual style of the terrain layer changes drastically between the VFR and + IFR layers), or certain layers may be disabled entirely in some map types + (e.g., localizers are only visible in the IFR low-enroute style). + } + XPLMMapStyle = ( + xplm_MapStyle_VFR_Sectional = 0 + + ,xplm_MapStyle_IFR_LowEnroute = 1 + + ,xplm_MapStyle_IFR_HighEnroute = 2 + + ); + PXPLMMapStyle = ^XPLMMapStyle; + + { + XPLMMapDrawingCallback_f + + This is the OpenGL map drawing callback for plugin-created map layers. You + can perform arbitrary OpenGL drawing from this callback, with one + exception: changes to the Z-buffer are not permitted, and will result in + map drawing errors. + + All drawing done from within this callback appears beneath all built-in + X-Plane icons and labels, but above the built-in "fill" layers (layers + providing major details, like terrain and water). Note, however, that the + relative ordering between the drawing callbacks of different plugins is not + guaranteed. + } + XPLMMapDrawingCallback_f = PROCEDURE( + inLayer : XPLMMapLayerID; + inMapBoundsLeftTopRightBottom: PSingle; + zoomRatio : Single; + mapUnitsPerUserInterfaceUnit: Single; + mapStyle : XPLMMapStyle; + projection : XPLMMapProjectionID; + inRefcon : pointer); cdecl; + + { + XPLMMapIconDrawingCallback_f + + This is the icon drawing callback that enables plugin-created map layers to + draw icons using X-Plane's built-in icon drawing functionality. You can + request an arbitrary number of PNG icons to be drawn via + XPLMDrawMapIconFromSheet() from within this callback, but you may not + perform any OpenGL drawing here. + + Icons enqueued by this function will appear above all OpenGL drawing + (performed by your optional XPLMMapDrawingCallback_f), and above all + built-in X-Plane map icons of the same layer type ("fill" or "markings," as + determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note, + however, that the relative ordering between the drawing callbacks of + different plugins is not guaranteed. + } + XPLMMapIconDrawingCallback_f = PROCEDURE( + inLayer : XPLMMapLayerID; + inMapBoundsLeftTopRightBottom: PSingle; + zoomRatio : Single; + mapUnitsPerUserInterfaceUnit: Single; + mapStyle : XPLMMapStyle; + projection : XPLMMapProjectionID; + inRefcon : pointer); cdecl; + + { + XPLMMapLabelDrawingCallback_f + + This is the label drawing callback that enables plugin-created map layers + to draw text labels using X-Plane's built-in labeling functionality. You + can request an arbitrary number of text labels to be drawn via + XPLMDrawMapLabel() from within this callback, but you may not perform any + OpenGL drawing here. + + Labels enqueued by this function will appear above all OpenGL drawing + (performed by your optional XPLMMapDrawingCallback_f), and above all + built-in map icons and labels of the same layer type ("fill" or "markings," + as determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note, + however, that the relative ordering between the drawing callbacks of + different plugins is not guaranteed. + } + XPLMMapLabelDrawingCallback_f = PROCEDURE( + inLayer : XPLMMapLayerID; + inMapBoundsLeftTopRightBottom: PSingle; + zoomRatio : Single; + mapUnitsPerUserInterfaceUnit: Single; + mapStyle : XPLMMapStyle; + projection : XPLMMapProjectionID; + inRefcon : pointer); cdecl; + +{$ENDIF XPLM300} +{$IFDEF XPLM300} +{___________________________________________________________________________ + * LAYER MANAGEMENT CALLBACKS + ___________________________________________________________________________} +{ + These are various "bookkeeping" callbacks that your map layer can receive + (if you provide the callback in your XPLMCreateMapLayer_t). They allow you + to manage the lifecycle of your layer, as well as cache any + computationally-intensive preparation you might need for drawing. +} + + + { + XPLMMapPrepareCacheCallback_f + + A callback used to allow you to cache whatever information your layer needs + to draw in the current map area. + + This is called each time the map's total bounds change. This is typically + triggered by new DSFs being loaded, such that X-Plane discards old, + now-distant DSFs and pulls in new ones. At that point, the available bounds + of the map also change to match the new DSF area. + + By caching just the information you need to draw in this area, your future + draw calls can be made faster, since you'll be able to simply "splat" your + precomputed information each frame. + + We guarantee that the map projection will not change between successive + prepare cache calls, nor will any draw call give you bounds outside these + total map bounds. So, if you cache the projected map coordinates of all the + items you might want to draw in the total map area, you can be guaranteed + that no draw call will be asked to do any new work. + } +TYPE + XPLMMapPrepareCacheCallback_f = PROCEDURE( + inLayer : XPLMMapLayerID; + inTotalMapBoundsLeftTopRightBottom: PSingle; + projection : XPLMMapProjectionID; + inRefcon : pointer); cdecl; + + { + XPLMMapWillBeDeletedCallback_f + + Called just before your map layer gets deleted. Because SDK-created map + layers have the same lifetime as the X-Plane map that contains them, if the + map gets unloaded from memory, your layer will too. + } + XPLMMapWillBeDeletedCallback_f = PROCEDURE( + inLayer : XPLMMapLayerID; + inRefcon : pointer); cdecl; + +{$ENDIF XPLM300} +{$IFDEF XPLM300} +{___________________________________________________________________________ + * MAP LAYER CREATION AND DESTRUCTION + ___________________________________________________________________________} +{ + Enables the creation of new map layers. Layers are created for a particular + instance of the X-Plane map. For instance, if you want your layer to appear + in both the normal map interface and the Instructor Operator Station (IOS), + you would need two separate calls to XPLMCreateMapLayer(), with two + different values for your XPLMCreateMapLayer_t::layer_name. + + Your layer's lifetime will be determined by the lifetime of the map it is + created in. If the map is destroyed (on the X-Plane side), your layer will + be too, and you'll receive a callback to your + XPLMMapWillBeDeletedCallback_f. +} + + + { + XPLMMapLayerType + + Indicates the type of map layer you are creating. Fill layers will always + be drawn beneath markings layers. + } +TYPE + XPLMMapLayerType = ( + { A layer that draws "fill" graphics, like weather patterns, terrain, etc. } + { Fill layers frequently cover a large portion of the visible map area. } + xplm_MapLayer_Fill = 0 + + { A layer that provides markings for particular map features, like NAVAIDs, } + { airports, etc. Even dense markings layers cover a small portion of the } + { total map area. } + ,xplm_MapLayer_Markings = 1 + + ); + PXPLMMapLayerType = ^XPLMMapLayerType; + +CONST + { Globally unique identifier for X-Plane's Map window, used as the } + { mapToCreateLayerIn parameter in XPLMCreateMapLayer_t } + XPLM_MAP_USER_INTERFACE = "XPLM_MAP_USER_INTERFACE"; + + { Globally unique identifier for X-Plane's Instructor Operator Station } + { window, used as the mapToCreateLayerIn parameter in XPLMCreateMapLayer_t } + XPLM_MAP_IOS = "XPLM_MAP_IOS"; + + { + XPLMCreateMapLayer_t + + This structure defines all of the parameters used to create a map layer + using XPLMCreateMapLayer. The structure will be expanded in future SDK APIs + to include more features. Always set the structSize member to the size of + your struct in bytes! + + Each layer must be associated with exactly one map instance in X-Plane. + That map, and that map alone, will call your callbacks. Likewise, when that + map is deleted, your layer will be as well. + } +TYPE + XPLMCreateMapLayer_t = RECORD + { Used to inform XPLMCreateMapLayer() of the SDK version you compiled } + { against; should always be set to sizeof(XPLMCreateMapLayer_t) } + structSize : Integer; + { Globally unique string identifying the map you want this layer to appear } + { in. As of XPLM300, this is limited to one of XPLM_MAP_USER_INTERFACE or } + { XPLM_MAP_IOS } + mapToCreateLayerIn : XPLMString; + { The type of layer you are creating, used to determine draw order (all } + { plugin-created markings layers are drawn above all plugin-created fill } + { layers) } + layerType : XPLMMapLayerType; + { Optional callback to inform you this layer is being deleted (due to its } + { owning map being destroyed) } + willBeDeletedCallback : XPLMMapWillBeDeletedCallback_f; + { Optional callback you want to use to prepare your draw cache when the map } + { bounds change (set to NULL if you don't want this callback) } + prepCacheCallback : XPLMMapPrepareCacheCallback_f; + { Optional callback you want to use for arbitrary OpenGL drawing, which goes } + { beneath all icons in the map's layering system (set to NULL if you don't } + { want this callback) } + drawCallback : XPLMMapDrawingCallback_f; + { Optional callback you want to use for drawing icons, which go above all } + { built-in X-Plane icons (except the aircraft) in the map's layering system } + { (set to NULL if you don't want this callback) } + iconCallback : XPLMMapIconDrawingCallback_f; + { Optional callback you want to use for drawing map labels, which go above } + { all built-in X-Plane icons and labels (except those of aircraft) in the } + { map's layering system (set to NULL if you don't want this callback) } + labelCallback : XPLMMapLabelDrawingCallback_f; + { True if you want a checkbox to be created in the map UI to toggle this } + { layer on and off; false if the layer should simply always be enabled } + showUiToggle : Integer; + { Short label to use for this layer in the user interface } + layerName : XPLMString; + { A reference to arbitrary data that will be passed to your callbacks } + refcon : pointer; + END; + PXPLMCreateMapLayer_t = ^XPLMCreateMapLayer_t; + + { + XPLMCreateMapLayer + + This routine creates a new map layer. You pass in an XPLMCreateMapLayer_t + structure with all of the fields set in. You must set the structSize of + the structure to the size of the actual structure you used. + + Returns NULL if the layer creation failed. This happens most frequently + because the map you specified in your + XPLMCreateMapLayer_t::mapToCreateLayerIn field doesn't exist (that is, if + XPLMMapExists() returns 0 for the specified map). You can use + XPLMRegisterMapCreationHook() to get a notification each time a new map is + opened in X-Plane, at which time you can create layers in it. + } + FUNCTION XPLMCreateMapLayer( + inParams : PXPLMCreateMapLayer_t) : XPLMMapLayerID; + cdecl; external XPLM_DLL; + + { + XPLMDestroyMapLayer + + Destroys a map layer you created (calling your + XPLMMapWillBeDeletedCallback_f if applicable). Returns true if a deletion + took place. + } + FUNCTION XPLMDestroyMapLayer( + inLayer : XPLMMapLayerID) : Integer; + cdecl; external XPLM_DLL; + + { + XPLMMapCreatedCallback_f + + A callback to notify your plugin that a new map has been created in + X-Plane. This is the best time to add a custom map layer using + XPLMCreateMapLayer(). + + No OpenGL drawing is permitted within this callback. + } +TYPE + XPLMMapCreatedCallback_f = PROCEDURE( + mapIdentifier : XPLMString; + refcon : pointer); cdecl; + + { + XPLMRegisterMapCreationHook + + Registers your callback to receive a notification each time a new map is + constructed in X-Plane. This callback is the best time to add your custom + map layer using XPLMCreateMapLayer(). + + Note that you will not be notified about any maps that already exist---you + can use XPLMMapExists() to check for maps that were created previously. + } + PROCEDURE XPLMRegisterMapCreationHook( + callback : XPLMMapCreatedCallback_f; + refcon : pointer); + cdecl; external XPLM_DLL; + + { + XPLMMapExists + + Returns 1 if the map with the specified identifier already exists in + X-Plane. In that case, you can safely call XPLMCreateMapLayer() specifying + that your layer should be added to that map. + } + FUNCTION XPLMMapExists( + mapIdentifier : XPLMString) : Integer; + cdecl; external XPLM_DLL; + +{$ENDIF XPLM300} +{$IFDEF XPLM300} +{___________________________________________________________________________ + * MAP DRAWING + ___________________________________________________________________________} +{ + These APIs are only valid from within a map drawing callback (one of + XPLMIconDrawingCallback_t or XPLMMapLabelDrawingCallback_f). Your drawing + callbacks are registered when you create a new map layer as part of your + XPLMCreateMapLayer_t. The functions here hook into X-Plane's built-in map + drawing functionality for icons and labels, so that you get a consistent + style with the rest of the X-Plane map. + + Note that the X-Plane 11 map introduces a strict ordering: layers of type + xplm_MapLayer_Fill get drawn beneath all xplm_MapLayer_Markings layers. + Likewise, all OpenGL drawing (performed in your layer's + XPLMMapDrawingCallback_f) will appear beneath any icons and labels you + draw. +} + + + { + XPLMMapOrientation + + Indicates whether a map element should be match its rotation to the map + itself, or to the user interface. For instance, the map itself may be + rotated such that "up" matches the user's aircraft, but you may want to + draw a text label such that it is always rotated zero degrees relative to + the user's perspective. In that case, you would have it draw with UI + orientation. + } +TYPE + XPLMMapOrientation = ( + { Orient such that a 0 degree rotation matches the map's north } + xplm_MapOrientation_Map = 0 + + { Orient such that a 0 degree rotation is "up" relative to the user interface} + ,xplm_MapOrientation_UI = 1 + + ); + PXPLMMapOrientation = ^XPLMMapOrientation; + + { + XPLMDrawMapIconFromSheet + + Enables plugin-created map layers to draw PNG icons using X-Plane's + built-in icon drawing functionality. Only valid from within an + XPLMIconDrawingCallback_t (but you can request an arbitrary number of icons + to be drawn from within your callback). + + X-Plane will automatically manage the memory for your texture so that it + only has to be loaded from disk once as long as you continue drawing it + per-frame. (When you stop drawing it, the memory may purged in a "garbage + collection" pass, require a load from disk in the future.) + + Instead of having X-Plane draw a full PNG, this method allows you to use UV + coordinates to request a portion of the image to be drawn. This allows you + to use a single texture load (of an icon sheet, for example) to draw many + icons. Doing so is much more efficient than drawing a dozen different small + PNGs. + + The UV coordinates used here treat the texture you load as being comprised + of a number of identically sized "cells." You specify the width and height + in cells (ds and dt, respectively), as well as the coordinates within the + cell grid for the sub-image you'd like to draw. + + Note that you can use different ds and dt values in subsequent calls with + the same texture sheet. This enables you to use icons of different sizes in + the same sheet if you arrange them properly in the PNG. + + This function is only valid from within an XPLMIconDrawingCallback_t (but + you can request an arbitrary number of icons to be drawn from within your + callback). + } + PROCEDURE XPLMDrawMapIconFromSheet( + layer : XPLMMapLayerID; + inPngPath : XPLMString; + s : Integer; + t : Integer; + ds : Integer; + dt : Integer; + mapX : Single; + mapY : Single; + orientation : XPLMMapOrientation; + rotationDegrees : Single; + mapWidth : Single); + cdecl; external XPLM_DLL; + + { + XPLMDrawMapLabel + + Enables plugin-created map layers to draw text labels using X-Plane's + built-in labeling functionality. Only valid from within an + XPLMMapLabelDrawingCallback_f (but you can request an arbitrary number of + text labels to be drawn from within your callback). + } + PROCEDURE XPLMDrawMapLabel( + layer : XPLMMapLayerID; + inText : XPLMString; + mapX : Single; + mapY : Single; + orientation : XPLMMapOrientation; + rotationDegrees : Single); + cdecl; external XPLM_DLL; + +{$ENDIF XPLM300} +{$IFDEF XPLM300} +{___________________________________________________________________________ + * MAP PROJECTIONS + ___________________________________________________________________________} +{ + As of X-Plane 11, the map draws using true cartographic projections, and + different maps may use different projections. Thus, to draw at a particular + latitude and longitude, you must first transform your real-world + coordinates into map coordinates. + + The map projection is also responsible for giving you the current scale of + the map. That is, the projection can tell you how many map units correspond + to 1 meter at a given point. + + Finally, the map projection can give you the current rotation of the map. + Since X-Plane 11 maps can rotate to match the heading of the aircraft, the + map's rotation can potentially change every frame. +} + + + { + XPLMMapProject + + Projects a latitude/longitude into map coordinates. This is the inverse of + XPLMMapUnproject(). + + Only valid from within a map layer callback (one of + XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, + XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.) + } + PROCEDURE XPLMMapProject( + projection : XPLMMapProjectionID; + latitude : Real; + longitude : Real; + outX : PSingle; + outY : PSingle); + cdecl; external XPLM_DLL; + + { + XPLMMapUnproject + + Transforms map coordinates back into a latitude and longitude. This is the + inverse of XPLMMapProject(). + + Only valid from within a map layer callback (one of + XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, + XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.) + } + PROCEDURE XPLMMapUnproject( + projection : XPLMMapProjectionID; + mapX : Single; + mapY : Single; + outLatitude : PReal; + outLongitude : PReal); + cdecl; external XPLM_DLL; + + { + XPLMMapScaleMeter + + Returns the number of map units that correspond to a distance of one meter + at a given set of map coordinates. + + Only valid from within a map layer callback (one of + XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, + XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.) + } + FUNCTION XPLMMapScaleMeter( + projection : XPLMMapProjectionID; + mapX : Single; + mapY : Single) : Single; + cdecl; external XPLM_DLL; + + { + XPLMMapGetNorthHeading + + Returns the heading (in degrees clockwise) from the positive Y axis in the + cartesian mapping coordinate system to true north at the point passed in. + You can use it as a clockwise rotational offset to align icons and other + 2-d drawing with true north on the map, compensating for rotations in the + map due to projection. + + Only valid from within a map layer callback (one of + XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f, + XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.) + } + FUNCTION XPLMMapGetNorthHeading( + projection : XPLMMapProjectionID; + mapX : Single; + mapY : Single) : Single; + cdecl; external XPLM_DLL; + +{$ENDIF XPLM300} + +IMPLEMENTATION + +END. diff --git a/XPSDK/Delphi/XPLM/XPLMMenus.pas b/XPSDK/Delphi/XPLM/XPLMMenus.pas index d113952..754a434 100644 --- a/XPSDK/Delphi/XPLM/XPLMMenus.pas +++ b/XPSDK/Delphi/XPLM/XPLMMenus.pas @@ -1,54 +1,62 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMMenus; INTERFACE { - XPLMMenus - Theory of Operation + Plug-ins can create menus in the menu bar of X-Plane. This is done by + creating a menu and then creating items. Menus are referred to by an + opaque ID. Items are referred to by (zero-based) index number. - Plug-ins can create menus in the menu bar of X-Plane. This is done by - creating a menu and then creating items. Menus are referred to by an - opaque ID. Items are referred to by index number. For each menu and item - you specify a void *. Per menu you specify a handler function that is - called with each void * when the menu item is picked. Menu item indices - are zero based. + Menus are "sandboxed" between plugins---no plugin can access the menus of + any other plugin. Furthermore, all menu indices are relative to your + plugin's menus only; if your plugin creates two sub-menus in the Plugins + menu at different times, it doesn't matter how many other plugins also + create sub-menus of Plugins in the intervening time: your sub-menus will be + given menu indices 0 and 1. (The SDK does some work in the back-end to + filter out menus that are irrelevant to your plugin in order to deliver + this consistency for each plugin.) + + When you create a menu item, you specify how we should handle clicks on + that menu item. You can either have the XPLM trigger a callback (the + XPLMMenuHandler_f associated with the menu that contains the item), or you + can simply have a command be triggered (with no associated call to your + menu handler). The advantage of the latter method is that X-Plane will + display any keyboard shortcuts associated with the command. (In contrast, + there are no keyboard shortcuts associated with menu handler callbacks with + specific parameters.) + + Menu text in X-Plane is UTF8; X-Plane's character set covers latin, greek + and cyrillic characters, Katakana, as well as some Japanese symbols. Some + APIs have a inDeprecatedAndIgnored parameter that used to select a + character set; since X-Plane 9 all localization is done via UTF-8 only. } -USES XPLMDefs; +USES + XPLMDefs, XPLMUtilities; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * XPLM MENUS ___________________________________________________________________________} -{ - -} - - { XPLMMenuCheck - These enumerations define the various 'check' states for an X-Plane menu. - 'checking' in x-plane actually appears as a light which may or may not be - lit. So there are three possible states. + These enumerations define the various 'check' states for an X-Plane menu. + 'checking' in X-Plane actually appears as a light which may or may not be + lit. So there are three possible states. } TYPE XPLMMenuCheck = ( - { there is no symbol to the left of the menu item. } + { there is no symbol to the left of the menu item. } xplm_Menu_NoCheck = 0 - { the menu has a mark next to it that is unmarked (not lit). } + { the menu has a mark next to it that is unmarked (not lit). } ,xplm_Menu_Unchecked = 1 - { the menu has a mark next to it that is checked (lit). } + { the menu has a mark next to it that is checked (lit). } ,xplm_Menu_Checked = 2 ); @@ -57,7 +65,7 @@ TYPE { XPLMMenuID - This is a unique ID for each menu you create. + This is a unique ID for each menu you create. } XPLMMenuID = pointer; PXPLMMenuID = ^XPLMMenuID; @@ -65,9 +73,9 @@ TYPE { XPLMMenuHandler_f - A menu handler function takes two reference pointers, one for the menu - (specified when the menu was created) and one for the item (specified when - the item was created). + A menu handler function takes two reference pointers, one for the menu + (specified when the menu was created) and one for the item (specified when + the item was created). } XPLMMenuHandler_f = PROCEDURE( inMenuRef : pointer; @@ -76,184 +84,194 @@ TYPE { XPLMFindPluginsMenu - This function returns the ID of the plug-ins menu, which is created for you - at startup. + This function returns the ID of the plug-ins menu, which is created for you + at startup. } FUNCTION XPLMFindPluginsMenu: XPLMMenuID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; + +{$IFDEF XPLM300} + { + XPLMFindAircraftMenu + + This function returns the ID of the menu for the currently-loaded aircraft, + used for showing aircraft-specific commands. + + The aircraft menu is created by X-Plane at startup, but it remains hidden + until it is populated via XPLMAppendMenuItem() or + XPLMAppendMenuItemWithCommand(). + + Only plugins loaded with the user's current aircraft are allowed to access + the aircraft menu. For all other plugins, this will return NULL, and any + attempts to add menu items to it will fail. + } + FUNCTION XPLMFindAircraftMenu: XPLMMenuID; + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} { XPLMCreateMenu - This function creates a new menu and returns its ID. It returns NULL if - the menu cannot be created. Pass in a parent menu ID and an item index to - create a submenu, or NULL for the parent menu to put the menu in the menu - bar. The menu's name is only used if the menu is in the menubar. You also - pass a handler function and a menu reference value. Pass NULL for the - handler if you do not need callbacks from the menu (for example, if it only - contains submenus). + This function creates a new menu and returns its ID. It returns NULL if + the menu cannot be created. Pass in a parent menu ID and an item index to + create a submenu, or NULL for the parent menu to put the menu in the menu + bar. The menu's name is only used if the menu is in the menubar. You also + pass a handler function and a menu reference value. Pass NULL for the + handler if you do not need callbacks from the menu (for example, if it only + contains submenus). - Important: you must pass a valid, non-empty menu title even if the menu is - a submenu where the title is not visible. + Important: you must pass a valid, non-empty menu title even if the menu is + a submenu where the title is not visible. } FUNCTION XPLMCreateMenu( - inName : Pchar; + inName : XPLMString; inParentMenu : XPLMMenuID; - inParentItem : integer; + inParentItem : Integer; inHandler : XPLMMenuHandler_f; inMenuRef : pointer) : XPLMMenuID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMDestroyMenu - This function destroys a menu that you have created. Use this to remove a - submenu if necessary. (Normally this function will not be necessary.) + This function destroys a menu that you have created. Use this to remove a + submenu if necessary. (Normally this function will not be necessary.) } PROCEDURE XPLMDestroyMenu( inMenuID : XPLMMenuID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMClearAllMenuItems - This function removes all menu items from a menu, allowing you to rebuild - it. Use this function if you need to change the number of items on a menu. + This function removes all menu items from a menu, allowing you to rebuild + it. Use this function if you need to change the number of items on a menu. } PROCEDURE XPLMClearAllMenuItems( inMenuID : XPLMMenuID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMAppendMenuItem - This routine appends a new menu item to the bottom of a menu and returns - its index. Pass in the menu to add the item to, the items name, and a void - * ref for this item. If you pass in inForceEnglish, this menu item will be - drawn using the english character set no matter what language x-plane is - running in. Otherwise the menu item will be drawn localized. (An example - of why you'd want to do this is for a proper name.) See XPLMUtilities for - determining the current langauge. + This routine appends a new menu item to the bottom of a menu and returns + its index. Pass in the menu to add the item to, the items name, and a void + * ref for this item. + + Returns a negative index if the append failed (due to an invalid parent + menu argument). + + Note that all menu indices returned are relative to your plugin's menus + only; if your plugin creates two sub-menus in the Plugins menu at different + times, it doesn't matter how many other plugins also create sub-menus of + Plugins in the intervening time: your sub-menus will be given menu indices + 0 and 1. (The SDK does some work in the back-end to filter out menus that + are irrelevant to your plugin in order to deliver this consistency for each + plugin.) } FUNCTION XPLMAppendMenuItem( inMenu : XPLMMenuID; - inItemName : Pchar; + inItemName : XPLMString; inItemRef : pointer; - inForceEnglish : integer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inDeprecatedAndIgnored: Integer) : Integer; + cdecl; external XPLM_DLL; + +{$IFDEF XPLM300} + { + XPLMAppendMenuItemWithCommand + + Like XPLMAppendMenuItem(), but instead of the new menu item triggering the + XPLMMenuHandler_f of the containiner menu, it will simply execute the + command you pass in. Using a command for your menu item allows the user to + bind a keyboard shortcut to the command and see that shortcut represented + in the menu. + + Returns a negative index if the append failed (due to an invalid parent + menu argument). + + Like XPLMAppendMenuItem(), all menu indices are relative to your plugin's + menus only. + } + FUNCTION XPLMAppendMenuItemWithCommand( + inMenu : XPLMMenuID; + inItemName : XPLMString; + inCommandToExecute : XPLMCommandRef) : Integer; + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} { XPLMAppendMenuSeparator - This routine adds a seperator to the end of a menu. + This routine adds a separator to the end of a menu. + + Returns a negative index if the append failed (due to an invalid parent + menu argument). } PROCEDURE XPLMAppendMenuSeparator( inMenu : XPLMMenuID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMSetMenuItemName - This routine changes the name of an existing menu item. Pass in the menu - ID and the index of the menu item. + This routine changes the name of an existing menu item. Pass in the menu + ID and the index of the menu item. } PROCEDURE XPLMSetMenuItemName( inMenu : XPLMMenuID; - inIndex : integer; - inItemName : Pchar; - inForceEnglish : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inIndex : Integer; + inItemName : XPLMString; + inDeprecatedAndIgnored: Integer); + cdecl; external XPLM_DLL; { XPLMCheckMenuItem - Set whether a menu item is checked. Pass in the menu ID and item index. + Set whether a menu item is checked. Pass in the menu ID and item index. } PROCEDURE XPLMCheckMenuItem( inMenu : XPLMMenuID; - index : integer; + index : Integer; inCheck : XPLMMenuCheck); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMCheckMenuItemState - This routine returns whether a menu item is checked or not. A menu item's - check mark may be on or off, or a menu may not have an icon at all. + This routine returns whether a menu item is checked or not. A menu item's + check mark may be on or off, or a menu may not have an icon at all. } PROCEDURE XPLMCheckMenuItemState( inMenu : XPLMMenuID; - index : integer; + index : Integer; outCheck : PXPLMMenuCheck); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMEnableMenuItem - Sets whether this menu item is enabled. Items start out enabled. + Sets whether this menu item is enabled. Items start out enabled. } PROCEDURE XPLMEnableMenuItem( inMenu : XPLMMenuID; - index : integer; - enabled : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + index : Integer; + enabled : Integer); + cdecl; external XPLM_DLL; {$IFDEF XPLM210} { XPLMRemoveMenuItem - Removes one item from a menu. Note that all menu items below are moved up - one; your plugin must track the change in index numbers. + Removes one item from a menu. Note that all menu items below are moved up + one; your plugin must track the change in index numbers. } PROCEDURE XPLMRemoveMenuItem( inMenu : XPLMMenuID; - inIndex : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} + inIndex : Integer); + cdecl; external XPLM_DLL; +{$ENDIF XPLM210} + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMNavigation.pas b/XPSDK/Delphi/XPLM/XPLMNavigation.pas index 993ef58..044b99b 100644 --- a/XPSDK/Delphi/XPLM/XPLMNavigation.pas +++ b/XPSDK/Delphi/XPLM/XPLMNavigation.pas @@ -1,51 +1,39 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMNavigation; INTERFACE { - XPLMNavigation - THEORY OF OPERATION + The XPLM Navigation APIs give you some access to the navigation databases + inside X-Plane. X-Plane stores all navigation information in RAM, so by + using these APIs you can gain access to most information without having to + go to disk or parse the files yourself. - The XPLM Navigation APIs give you some access to the navigation databases - inside X-Plane. X-Plane stores all navigation information in RAM, so by - using these APIs you can gain access to most information without having to - go to disk or parse the files yourself. - - You can also use this API to program the FMS. You must use the navigation - APIs to find the nav-aids you want to program into the FMS, since the FMS - is powered internally by x-plane's navigation database. + You can also use this API to program the FMS. You must use the navigation + APIs to find the nav-aids you want to program into the FMS, since the FMS + is powered internally by X-Plane's navigation database. } -USES XPLMDefs; +USES + XPLMDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * NAVIGATION DATABASE ACCESS ___________________________________________________________________________} -{ - -} - - { XPLMNavType - These enumerations define the different types of navaids. They are each - defined with a separate bit so that they may be bit-wise added together to - form sets of nav-aid types. + These enumerations define the different types of navaids. They are each + defined with a separate bit so that they may be bit-wise added together to + form sets of nav-aid types. - NOTE: xplm_Nav_LatLon is a specific lat-lon coordinate entered into the - FMS. It will not exist in the database, and cannot be programmed into the - FMS. Querying the FMS for navaids will return it. Use - XPLMSetFMSEntryLatLon to set a lat/lon waypoint. + NOTE: xplm_Nav_LatLon is a specific lat-lon coordinate entered into the + FMS. It will not exist in the database, and cannot be programmed into the + FMS. Querying the FMS for navaids will return it. Use + XPLMSetFMSEntryLatLon to set a lat/lon waypoint. } TYPE XPLMNavType = ( @@ -81,17 +69,17 @@ TYPE { XPLMNavRef - XPLMNavRef is an iterator into the navigation database. The navigation - database is essentially an array, but it is not necessarily densely - populated. The only assumption you can safely make is that like-typed - nav-aids are grouped together. + XPLMNavRef is an iterator into the navigation database. The navigation + database is essentially an array, but it is not necessarily densely + populated. The only assumption you can safely make is that like-typed + nav-aids are grouped together. - Use XPLMNavRef to refer to a nav-aid. + Use XPLMNavRef to refer to a nav-aid. - XPLM_NAV_NOT_FOUND is returned by functions that return an XPLMNavRef when - the iterator must be invalid. + XPLM_NAV_NOT_FOUND is returned by functions that return an XPLMNavRef when + the iterator must be invalid. } - XPLMNavRef = integer; + XPLMNavRef = Integer; PXPLMNavRef = ^XPLMNavRef; CONST @@ -100,335 +88,263 @@ CONST { XPLMGetFirstNavAid - This returns the very first navaid in the database. Use this to traverse - the entire database. Returns XPLM_NAV_NOT_FOUND if the nav database is - empty. + This returns the very first navaid in the database. Use this to traverse + the entire database. Returns XPLM_NAV_NOT_FOUND if the nav database is + empty. } FUNCTION XPLMGetFirstNavAid: XPLMNavRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMGetNextNavAid - Given a nav aid ref, this routine returns the next navaid. It returns - XPLM_NAV_NOT_FOUND if the nav aid passed in was invalid or if the navaid - passed in was the last one in the database. Use this routine to iterate - across all like-typed navaids or the entire database. - - WARNING: due to a bug in the SDK, when fix loading is disabled in the - rendering settings screen, calling this routine with the last airport - returns a bogus nav aid. Using this nav aid can crash x-plane. + Given a valid nav aid ref, this routine returns the next navaid. It + returns XPLM_NAV_NOT_FOUND if the nav aid passed in was invalid or if the + navaid passed in was the last one in the database. Use this routine to + iterate across all like-typed navaids or the entire database. } FUNCTION XPLMGetNextNavAid( inNavAidRef : XPLMNavRef) : XPLMNavRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMFindFirstNavAidOfType - This routine returns the ref of the first navaid of the given type in the - database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the - database. You must pass exactly one nav aid type to this routine. - - WARNING: due to a bug in the SDK, when fix loading is disabled in the - rendering settings screen, calling this routine with fixes returns a bogus - nav aid. Using this nav aid can crash x-plane. + This routine returns the ref of the first navaid of the given type in the + database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the + database. You must pass exactly one nav aid type to this routine. } FUNCTION XPLMFindFirstNavAidOfType( inType : XPLMNavType) : XPLMNavRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMFindLastNavAidOfType - This routine returns the ref of the last navaid of the given type in the - database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the - database. You must pass exactly one nav aid type to this routine. - - WARNING: due to a bug in the SDK, when fix loading is disabled in the - rendering settings screen, calling this routine with fixes returns a bogus - nav aid. Using this nav aid can crash x-plane. + This routine returns the ref of the last navaid of the given type in the + database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the + database. You must pass exactly one nav aid type to this routine. } FUNCTION XPLMFindLastNavAidOfType( inType : XPLMNavType) : XPLMNavRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMFindNavAid - This routine provides a number of searching capabilities for the nav - database. XPLMFindNavAid will search through every nav aid whose type is - within inType (multiple types may be added together) and return any - nav-aids found based on the following rules: + This routine provides a number of searching capabilities for the nav + database. XPLMFindNavAid will search through every nav aid whose type is + within inType (multiple types may be added together) and return any + nav-aids found based on the following rules: - If inLat and inLon are not NULL, the navaid nearest to that lat/lon will be - returned, otherwise the last navaid found will be returned. + * If inLat and inLon are not NULL, the navaid nearest to that lat/lon will + be returned, otherwise the last navaid found will be returned. - If inFrequency is not NULL, then any navaids considered must match this - frequency. Note that this will screen out radio beacons that do not have - frequency data published (like inner markers) but not fixes and airports. + * If inFrequency is not NULL, then any navaids considered must match this + frequency. Note that this will screen out radio beacons that do not have + frequency data published (like inner markers) but not fixes and airports. - If inNameFragment is not NULL, only navaids that contain the fragment in - their name will be returned. + * If inNameFragment is not NULL, only navaids that contain the fragment in + their name will be returned. - If inIDFragment is not NULL, only navaids that contain the fragment in - their IDs will be returned. + * If inIDFragment is not NULL, only navaids that contain the fragment in + their IDs will be returned. - This routine provides a simple way to do a number of useful searches: - - Find the nearest navaid on this frequency. Find the nearest airport. Find - the VOR whose ID is "KBOS". Find the nearest airport whose name contains - "Chicago". + This routine provides a simple way to do a number of useful searches: + * Find the nearest navaid on this frequency. + * Find the nearest airport. + * Find the VOR whose ID is "KBOS". + * Find the nearest airport whose name contains "Chicago". } FUNCTION XPLMFindNavAid( - inNameFragment : Pchar; { Can be nil } - inIDFragment : Pchar; { Can be nil } - inLat : Psingle; { Can be nil } - inLon : Psingle; { Can be nil } - inFrequency : Pinteger; { Can be nil } + inNameFragment : XPLMString; { Can be nil } + inIDFragment : XPLMString; { Can be nil } + inLat : PSingle; { Can be nil } + inLon : PSingle; { Can be nil } + inFrequency : PInteger; { Can be nil } inType : XPLMNavType) : XPLMNavRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMGetNavAidInfo - This routine returns information about a navaid. Any non-null field is - filled out with information if it is available. + This routine returns information about a navaid. Any non-null field is + filled out with information if it is available. - Frequencies are in the nav.dat convention as described in the X-Plane nav - database FAQ: NDB frequencies are exact, all others are multiplied by 100. + Frequencies are in the nav.dat convention as described in the X-Plane nav + database FAQ: NDB frequencies are exact, all others are multiplied by 100. - The buffer for IDs should be at least 6 chars and the buffer for names - should be at least 41 chars, but since these values are likely to go up, I - recommend passing at least 32 chars for IDs and 256 chars for names when - possible. + The buffer for IDs should be at least 6 chars and the buffer for names + should be at least 41 chars, but since these values are likely to go up, I + recommend passing at least 32 chars for IDs and 256 chars for names when + possible. - The outReg parameter tells if the navaid is within the local "region" of - loaded DSFs. (This information may not be particularly useful to plugins.) - The parameter is a single byte value 1 for true or 0 for false, not a C - string. + The outReg parameter tells if the navaid is within the local "region" of + loaded DSFs. (This information may not be particularly useful to plugins.) + The parameter is a single byte value 1 for true or 0 for false, not a C + string. } PROCEDURE XPLMGetNavAidInfo( inRef : XPLMNavRef; outType : PXPLMNavType; { Can be nil } - outLatitude : Psingle; { Can be nil } - outLongitude : Psingle; { Can be nil } - outHeight : Psingle; { Can be nil } - outFrequency : Pinteger; { Can be nil } - outHeading : Psingle; { Can be nil } - outID : Pchar; { Can be nil } - outName : Pchar; { Can be nil } - outReg : Pchar); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outLatitude : PSingle; { Can be nil } + outLongitude : PSingle; { Can be nil } + outHeight : PSingle; { Can be nil } + outFrequency : PInteger; { Can be nil } + outHeading : PSingle; { Can be nil } + outID : XPLMString; { Can be nil } + outName : XPLMString; { Can be nil } + outReg : XPLMString); { Can be nil } + cdecl; external XPLM_DLL; {___________________________________________________________________________ * FLIGHT MANAGEMENT COMPUTER ___________________________________________________________________________} { - Note: the FMS works based on an array of entries. Indices into the array - are zero-based. Each entry is a nav-aid plus an altitude. The FMS tracks - the currently displayed entry and the entry that it is flying to. + Note: the FMS works based on an array of entries. Indices into the array + are zero-based. Each entry is a nav-aid plus an altitude. The FMS tracks + the currently displayed entry and the entry that it is flying to. - The FMS must be programmed with contiguous entries, so clearing an entry at - the end shortens the effective flight plan. There is a max of 100 - waypoints in the flight plan. + The FMS must be programmed with contiguous entries, so clearing an entry at + the end shortens the effective flight plan. There is a max of 100 + waypoints in the flight plan. } - { XPLMCountFMSEntries - This routine returns the number of entries in the FMS. + This routine returns the number of entries in the FMS. } - FUNCTION XPLMCountFMSEntries: integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + FUNCTION XPLMCountFMSEntries: Integer; + cdecl; external XPLM_DLL; { XPLMGetDisplayedFMSEntry - This routine returns the index of the entry the pilot is viewing. + This routine returns the index of the entry the pilot is viewing. } - FUNCTION XPLMGetDisplayedFMSEntry: integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + FUNCTION XPLMGetDisplayedFMSEntry: Integer; + cdecl; external XPLM_DLL; { XPLMGetDestinationFMSEntry - This routine returns the index of the entry the FMS is flying to. + This routine returns the index of the entry the FMS is flying to. } - FUNCTION XPLMGetDestinationFMSEntry: integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + FUNCTION XPLMGetDestinationFMSEntry: Integer; + cdecl; external XPLM_DLL; { XPLMSetDisplayedFMSEntry - This routine changes which entry the FMS is showing to the index specified. - } + This routine changes which entry the FMS is showing to the index specified. + } PROCEDURE XPLMSetDisplayedFMSEntry( - inIndex : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inIndex : Integer); + cdecl; external XPLM_DLL; { XPLMSetDestinationFMSEntry - This routine changes which entry the FMS is flying the aircraft toward. + This routine changes which entry the FMS is flying the aircraft toward. } PROCEDURE XPLMSetDestinationFMSEntry( - inIndex : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inIndex : Integer); + cdecl; external XPLM_DLL; { XPLMGetFMSEntryInfo - This routine returns information about a given FMS entry. A reference to a - navaid can be returned allowing you to find additional information (such as - a frequency, ILS heading, name, etc.). Some information is available - immediately. For a lat/lon entry, the lat/lon is returned by this routine - but the navaid cannot be looked up (and the reference will be - XPLM_NAV_NOT_FOUND. FMS name entry buffers should be at least 256 chars in - length. + This routine returns information about a given FMS entry. If the entry is + an airport or navaid, a reference to a nav entry can be returned allowing + you to find additional information (such as a frequency, ILS heading, name, + etc.). Note that this reference can be XPLM_NAV_NOT_FOUND until the + information has been looked up asynchronously, so after flightplan changes, + it might take up to a second for this field to become populated. The other + information is available immediately. For a lat/lon entry, the lat/lon is + returned by this routine but the navaid cannot be looked up (and the + reference will be XPLM_NAV_NOT_FOUND). FMS name entry buffers should be at + least 256 chars in length. + + WARNING: Due to a bug in X-Plane prior to 11.31, the navaid reference will + not be set to XPLM_NAV_NOT_FOUND while no data is available, and instead + just remain the value of the variable that you passed the pointer to. + Therefore, always initialize the variable to XPLM_NAV_NOT_FOUND before + passing the pointer to this function. } PROCEDURE XPLMGetFMSEntryInfo( - inIndex : integer; + inIndex : Integer; outType : PXPLMNavType; { Can be nil } - outID : Pchar; { Can be nil } + outID : XPLMString; { Can be nil } outRef : PXPLMNavRef; { Can be nil } - outAltitude : Pinteger; { Can be nil } - outLat : Psingle; { Can be nil } - outLon : Psingle); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outAltitude : PInteger; { Can be nil } + outLat : PSingle; { Can be nil } + outLon : PSingle); { Can be nil } + cdecl; external XPLM_DLL; { XPLMSetFMSEntryInfo - This routine changes an entry in the FMS to have the destination navaid - passed in and the altitude specified. Use this only for airports, fixes, - and radio-beacon navaids. Currently of radio beacons, the FMS can only - support VORs and NDBs. Use the routines below to clear or fly to a lat/lon. + This routine changes an entry in the FMS to have the destination navaid + passed in and the altitude specified. Use this only for airports, fixes, + and radio-beacon navaids. Currently of radio beacons, the FMS can only + support VORs and NDBs. Use the routines below to clear or fly to a lat/lon. } PROCEDURE XPLMSetFMSEntryInfo( - inIndex : integer; + inIndex : Integer; inRef : XPLMNavRef; - inAltitude : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inAltitude : Integer); + cdecl; external XPLM_DLL; { XPLMSetFMSEntryLatLon - This routine changes the entry in the FMS to a lat/lon entry with the given - coordinates. + This routine changes the entry in the FMS to a lat/lon entry with the given + coordinates. } PROCEDURE XPLMSetFMSEntryLatLon( - inIndex : integer; - inLat : single; - inLon : single; - inAltitude : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inIndex : Integer; + inLat : Single; + inLon : Single; + inAltitude : Integer); + cdecl; external XPLM_DLL; { XPLMClearFMSEntry - This routine clears the given entry, potentially shortening the flight - plan. + This routine clears the given entry, potentially shortening the flight + plan. } PROCEDURE XPLMClearFMSEntry( - inIndex : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inIndex : Integer); + cdecl; external XPLM_DLL; {___________________________________________________________________________ * GPS RECEIVER ___________________________________________________________________________} { - These APIs let you read data from the GPS unit. + These APIs let you read data from the GPS unit. } - - { XPLMGetGPSDestinationType - This routine returns the type of the currently selected GPS destination, - one of fix, airport, VOR or NDB. + This routine returns the type of the currently selected GPS destination, + one of fix, airport, VOR or NDB. } FUNCTION XPLMGetGPSDestinationType: XPLMNavType; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMGetGPSDestination - This routine returns the current GPS destination. + This routine returns the current GPS destination. } FUNCTION XPLMGetGPSDestination: XPLMNavRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMPlanes.pas b/XPSDK/Delphi/XPLM/XPLMPlanes.pas index b5d19a2..3801f0a 100644 --- a/XPSDK/Delphi/XPLM/XPLMPlanes.pas +++ b/XPSDK/Delphi/XPLM/XPLMPlanes.pas @@ -1,162 +1,158 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMPlanes; INTERFACE { - The XPLMPlanes APIs allow you to control the various aircraft in x-plane, - both the user's and the sim's. + The XPLMPlanes APIs allow you to control the various aircraft in X-Plane, + both the user's and the sim's. + + *Note*: unlike almost all other APIs in the SDK, aircraft paths are _full_ + file system paths for historical reasons. You'll need to prefix all + relative paths with the X-Plane path as accessed via XPLMGetSystemPath. } -USES XPLMDefs; +USES + XPLMDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * USER AIRCRAFT ACCESS ___________________________________________________________________________} -{ - -} - { XPLMSetUsersAircraft - This routine changes the user's aircraft. Note that this will reinitialize - the user to be on the nearest airport's first runway. Pass in a full path - (hard drive and everything including the .acf extension) to the .acf file. + This routine changes the user's aircraft. Note that this will reinitialize + the user to be on the nearest airport's first runway. Pass in a full path + (hard drive and everything including the .acf extension) to the .acf file. } PROCEDURE XPLMSetUsersAircraft( - inAircraftPath : Pchar); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inAircraftPath : XPLMString); + cdecl; external XPLM_DLL; { XPLMPlaceUserAtAirport - This routine places the user at a given airport. Specify the airport by - its ICAO code (e.g. 'KBOS'). + This routine places the user at a given airport. Specify the airport by + its X-Plane airport ID (e.g. 'KBOS'). } PROCEDURE XPLMPlaceUserAtAirport( - inAirportCode : Pchar); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inAirportCode : XPLMString); + cdecl; external XPLM_DLL; +{$IFDEF XPLM300} + { + XPLMPlaceUserAtLocation + + Places the user at a specific location after performing any necessary + scenery loads. + + As with in-air starts initiated from the X-Plane user interface, the + aircraft will always start with its engines running, regardless of the + user's preferences (i.e., regardless of what the dataref + `sim/operation/prefs/startup_running` says). + } + PROCEDURE XPLMPlaceUserAtLocation( + latitudeDegrees : Real; + longitudeDegrees : Real; + elevationMetersMSL : Single; + headingDegreesTrue : Single; + speedMetersPerSecond: Single); + cdecl; external XPLM_DLL; +{$ENDIF XPLM300} {___________________________________________________________________________ * GLOBAL AIRCRAFT ACCESS ___________________________________________________________________________} -{ - -} - CONST - { The user's aircraft is always index 0. } + { The user's aircraft is always index 0. } XPLM_USER_AIRCRAFT = 0; +{$IFDEF XPLM_DEPRECATED} { XPLMPlaneDrawState_t - This structure contains additional plane parameter info to be passed to - draw plane. Make sure to fill in the size of the structure field with - sizeof(XPLMDrawPlaneState_t) so that the XPLM can tell how many fields you - knew about when compiling your plugin (since more fields may be added - later). + This structure contains additional plane parameter info to be passed to + draw plane. Make sure to fill in the size of the structure field with + sizeof(XPLMDrawPlaneState_t) so that the XPLM can tell how many fields you + knew about when compiling your plugin (since more fields may be added + later). - Most of these fields are ratios from 0 to 1 for control input. X-Plane - calculates what the actual controls look like based on the .acf file for - that airplane. Note for the yoke inputs, this is what the pilot of the - plane has commanded (post artificial stability system if there were one) - and affects aelerons, rudder, etc. It is not necessarily related to the - actual position of the plane! + Most of these fields are ratios from 0 to 1 for control input. X-Plane + calculates what the actual controls look like based on the .acf file for + that airplane. Note for the yoke inputs, this is what the pilot of the + plane has commanded (post artificial stability system if there were one) + and affects aelerons, rudder, etc. It is not necessarily related to the + actual position of the plane! } TYPE XPLMPlaneDrawState_t = RECORD - { The size of the draw state struct. } - structSize : integer; - { A ratio from [0..1] describing how far the landing gear is extended. } - gearPosition : single; - { Ratio of flap deployment, 0 = up, 1 = full deploy. } - flapRatio : single; - { Ratio of spoiler deployment, 0 = none, 1 = full deploy. } - spoilerRatio : single; - { Ratio of speed brake deployment, 0 = none, 1 = full deploy. } - speedBrakeRatio : single; - { Ratio of slat deployment, 0 = none, 1 = full deploy. } - slatRatio : single; - { Wing sweep ratio, 0 = forward, 1 = swept. } - wingSweep : single; - { Thrust power, 0 = none, 1 = full fwd, -1 = full reverse. } - thrust : single; - { Total pitch input for this plane. } - yokePitch : single; - { Total Heading input for this plane. } - yokeHeading : single; - { Total Roll input for this plane. } - yokeRoll : single; + { The size of the draw state struct. } + structSize : Integer; + { A ratio from [0..1] describing how far the landing gear is extended. } + gearPosition : Single; + { Ratio of flap deployment, 0 = up, 1 = full deploy. } + flapRatio : Single; + { Ratio of spoiler deployment, 0 = none, 1 = full deploy. } + spoilerRatio : Single; + { Ratio of speed brake deployment, 0 = none, 1 = full deploy. } + speedBrakeRatio : Single; + { Ratio of slat deployment, 0 = none, 1 = full deploy. } + slatRatio : Single; + { Wing sweep ratio, 0 = forward, 1 = swept. } + wingSweep : Single; + { Thrust power, 0 = none, 1 = full fwd, -1 = full reverse. } + thrust : Single; + { Total pitch input for this plane. } + yokePitch : Single; + { Total Heading input for this plane. } + yokeHeading : Single; + { Total Roll input for this plane. } + yokeRoll : Single; END; PXPLMPlaneDrawState_t = ^XPLMPlaneDrawState_t; +{$ENDIF XPLM_DEPRECATED} { XPLMCountAircraft - This function returns the number of aircraft X-Plane is capable of having, - as well as the number of aircraft that are currently active. These numbers - count the user's aircraft. It can also return the plugin that is currently - controlling aircraft. In X-Plane 7, this routine reflects the number of - aircraft the user has enabled in the rendering options window. + This function returns the number of aircraft X-Plane is capable of having, + as well as the number of aircraft that are currently active. These numbers + count the user's aircraft. It can also return the plugin that is currently + controlling aircraft. In X-Plane 7, this routine reflects the number of + aircraft the user has enabled in the rendering options window. } PROCEDURE XPLMCountAircraft( - outTotalAircraft : Pinteger; - outActiveAircraft : Pinteger; + outTotalAircraft : PInteger; + outActiveAircraft : PInteger; outController : PXPLMPluginID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMGetNthAircraftModel - This function returns the aircraft model for the Nth aircraft. Indices are - zero based, with zero being the user's aircraft. The file name should be - at least 256 chars in length; the path should be at least 512 chars in - length. + This function returns the aircraft model for the Nth aircraft. Indices are + zero based, with zero being the user's aircraft. The file name should be + at least 256 chars in length; the path should be at least 512 chars in + length. } PROCEDURE XPLMGetNthAircraftModel( - inIndex : integer; - outFileName : Pchar; - outPath : Pchar); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inIndex : Integer; + outFileName : XPLMString; + outPath : XPLMString); + cdecl; external XPLM_DLL; {___________________________________________________________________________ * EXCLUSIVE AIRCRAFT ACCESS ___________________________________________________________________________} { - The following routines require exclusive access to the airplane APIs. Only - one plugin may have this access at a time. + The following routines require exclusive access to the airplane APIs. Only + one plugin may have this access at a time. } - { XPLMPlanesAvailable_f - Your airplanes available callback is called when another plugin gives up - access to the multiplayer planes. Use this to wait for access to - multiplayer. + Your airplanes available callback is called when another plugin gives up + access to the multiplayer planes. Use this to wait for access to + multiplayer. } TYPE XPLMPlanesAvailable_f = PROCEDURE( @@ -165,130 +161,118 @@ TYPE { XPLMAcquirePlanes - XPLMAcquirePlanes grants your plugin exclusive access to the aircraft. It - returns 1 if you gain access, 0 if you do not. inAircraft - pass in an - array of pointers to strings specifying the planes you want loaded. For - any plane index you do not want loaded, pass a 0-length string. Other - strings should be full paths with the .acf extension. NULL terminates this - array, or pass NULL if there are no planes you want loaded. If you pass in - a callback and do not receive access to the planes your callback will be - called when the airplanes are available. If you do receive airplane access, - your callback will not be called. + XPLMAcquirePlanes grants your plugin exclusive access to the aircraft. It + returns 1 if you gain access, 0 if you do not. + + inAircraft - pass in an array of pointers to strings specifying the planes + you want loaded. For any plane index you do not want loaded, pass a + 0-length string. Other strings should be full paths with the .acf + extension. NULL terminates this array, or pass NULL if there are no planes + you want loaded. + + If you pass in a callback and do not receive access to the planes your + callback will be called when the airplanes are available. If you do receive + airplane access, your callback will not be called. } FUNCTION XPLMAcquirePlanes( - inAircraft : PPchar; { Can be nil } + inAircraft : PXPLMString; { Can be nil } inCallback : XPLMPlanesAvailable_f; - inRefcon : pointer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inRefcon : pointer) : Integer; + cdecl; external XPLM_DLL; { XPLMReleasePlanes - Call this function to release access to the planes. Note that if you are - disabled, access to planes is released for you and you must reacquire it. + Call this function to release access to the planes. Note that if you are + disabled, access to planes is released for you and you must reacquire it. } PROCEDURE XPLMReleasePlanes; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMSetActiveAircraftCount - This routine sets the number of active planes. If you pass in a number - higher than the total number of planes availables, only the total number of - planes available is actually used. + This routine sets the number of active planes. If you pass in a number + higher than the total number of planes availables, only the total number of + planes available is actually used. } PROCEDURE XPLMSetActiveAircraftCount( - inCount : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inCount : Integer); + cdecl; external XPLM_DLL; { XPLMSetAircraftModel - This routine loads an aircraft model. It may only be called if you have - exclusive access to the airplane APIs. Pass in the path of the model with - the .acf extension. The index is zero based, but you may not pass in 0 - (use XPLMSetUsersAircraft to load the user's aircracft). + This routine loads an aircraft model. It may only be called if you have + exclusive access to the airplane APIs. Pass in the path of the model with + the .acf extension. The index is zero based, but you may not pass in 0 + (use XPLMSetUsersAircraft to load the user's aircracft). } PROCEDURE XPLMSetAircraftModel( - inIndex : integer; - inAircraftPath : Pchar); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inIndex : Integer; + inAircraftPath : XPLMString); + cdecl; external XPLM_DLL; { XPLMDisableAIForPlane - This routine turns off X-Plane's AI for a given plane. The plane will - continue to draw and be a real plane in X-Plane, but will not move itself. + This routine turns off X-Plane's AI for a given plane. The plane will + continue to draw and be a real plane in X-Plane, but will not move itself. } PROCEDURE XPLMDisableAIForPlane( - inPlaneIndex : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inPlaneIndex : Integer); + cdecl; external XPLM_DLL; +{$IFDEF XPLM_DEPRECATED} { XPLMDrawAircraft - This routine draws an aircraft. It can only be called from a 3-d drawing - callback. Pass in the position of the plane in OpenGL local coordinates - and the orientation of the plane. A 1 for full drawing indicates that the - whole plane must be drawn; a 0 indicates you only need the nav lights - drawn. (This saves rendering time when planes are far away.) + WARNING: Aircraft drawing via this API is deprecated and will not work in + future versions of X-Plane. Use XPLMInstance for 3-d drawing of custom + aircraft models. + + This routine draws an aircraft. It can only be called from a 3-d drawing + callback. Pass in the position of the plane in OpenGL local coordinates + and the orientation of the plane. A 1 for full drawing indicates that the + whole plane must be drawn; a 0 indicates you only need the nav lights + drawn. (This saves rendering time when planes are far away.) } PROCEDURE XPLMDrawAircraft( - inPlaneIndex : integer; - inX : single; - inY : single; - inZ : single; - inPitch : single; - inRoll : single; - inYaw : single; - inFullDraw : integer; + inPlaneIndex : Integer; + inX : Single; + inY : Single; + inZ : Single; + inPitch : Single; + inRoll : Single; + inYaw : Single; + inFullDraw : Integer; inDrawStateInfo : PXPLMPlaneDrawState_t); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; +{$ENDIF XPLM_DEPRECATED} +{$IFDEF XPLM_DEPRECATED} { XPLMReinitUsersPlane - This function recomputes the derived flight model data from the aircraft - structure in memory. If you have used the data access layer to modify the - aircraft structure, use this routine to resynchronize x-plane; since - X-plane works at least partly from derived values, the sim will not behave - properly until this is called. + WARNING: DO NOT USE. Use XPLMPlaceUserAtAirport or + XPLMPlaceUserAtLocation. - WARNING: this routine does not necessarily place the airplane at the - airport; use XPLMSetUsersAircraft to be compatible. This routine is - provided to do special experimentation with flight models without resetting - flight. + This function recomputes the derived flight model data from the aircraft + structure in memory. If you have used the data access layer to modify the + aircraft structure, use this routine to resynchronize X-Plane; since + X-Plane works at least partly from derived values, the sim will not behave + properly until this is called. + + WARNING: this routine does not necessarily place the airplane at the + airport; use XPLMSetUsersAircraft to be compatible. This routine is + provided to do special experimentation with flight models without resetting + flight. } PROCEDURE XPLMReinitUsersPlane; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; +{$ENDIF XPLM_DEPRECATED} + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMPlugin.pas b/XPSDK/Delphi/XPLM/XPLMPlugin.pas index f053f80..83fbb73 100644 --- a/XPSDK/Delphi/XPLM/XPLMPlugin.pas +++ b/XPSDK/Delphi/XPLM/XPLMPlugin.pas @@ -1,381 +1,413 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMPlugin; INTERFACE { - These APIs provide facilities to find and work with other plugins and - manage other plugins. + These APIs provide facilities to find and work with other plugins and + manage other plugins. } -USES XPLMDefs; +USES + XPLMDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * FINDING PLUGINS ___________________________________________________________________________} { - These APIs allow you to find another plugin or yourself, or iterate across - all plugins. For example, if you wrote an FMS plugin that needed to talk - to an autopilot plugin, you could use these APIs to locate the autopilot - plugin. + These APIs allow you to find another plugin or yourself, or iterate across + all plugins. For example, if you wrote an FMS plugin that needed to talk + to an autopilot plugin, you could use these APIs to locate the autopilot + plugin. } - { XPLMGetMyID - This routine returns the plugin ID of the calling plug-in. Call this to - get your own ID. + This routine returns the plugin ID of the calling plug-in. Call this to + get your own ID. } FUNCTION XPLMGetMyID: XPLMPluginID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMCountPlugins - This routine returns the total number of plug-ins that are loaded, both - disabled and enabled. + This routine returns the total number of plug-ins that are loaded, both + disabled and enabled. } - FUNCTION XPLMCountPlugins: integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + FUNCTION XPLMCountPlugins: Integer; + cdecl; external XPLM_DLL; { XPLMGetNthPlugin - This routine returns the ID of a plug-in by index. Index is 0 based from 0 - to XPLMCountPlugins-1, inclusive. Plugins may be returned in any arbitrary - order. + This routine returns the ID of a plug-in by index. Index is 0 based from 0 + to XPLMCountPlugins-1, inclusive. Plugins may be returned in any arbitrary + order. } FUNCTION XPLMGetNthPlugin( - inIndex : integer) : XPLMPluginID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inIndex : Integer) : XPLMPluginID; + cdecl; external XPLM_DLL; { XPLMFindPluginByPath - This routine returns the plug-in ID of the plug-in whose file exists at the - passed in absolute file system path. XPLM_NO_PLUGIN_ID is returned if the - path does not point to a currently loaded plug-in. + This routine returns the plug-in ID of the plug-in whose file exists at the + passed in absolute file system path. XPLM_NO_PLUGIN_ID is returned if the + path does not point to a currently loaded plug-in. } FUNCTION XPLMFindPluginByPath( - inPath : Pchar) : XPLMPluginID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inPath : XPLMString) : XPLMPluginID; + cdecl; external XPLM_DLL; { XPLMFindPluginBySignature - This routine returns the plug-in ID of the plug-in whose signature matches - what is passed in or XPLM_NO_PLUGIN_ID if no running plug-in has this - signature. Signatures are the best way to identify another plug-in as they - are independent of the file system path of a plug-in or the human-readable - plug-in name, and should be unique for all plug-ins. Use this routine to - locate another plugin that your plugin interoperates with + This routine returns the plug-in ID of the plug-in whose signature matches + what is passed in or XPLM_NO_PLUGIN_ID if no running plug-in has this + signature. Signatures are the best way to identify another plug-in as they + are independent of the file system path of a plug-in or the human-readable + plug-in name, and should be unique for all plug-ins. Use this routine to + locate another plugin that your plugin interoperates with } FUNCTION XPLMFindPluginBySignature( - inSignature : Pchar) : XPLMPluginID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inSignature : XPLMString) : XPLMPluginID; + cdecl; external XPLM_DLL; { XPLMGetPluginInfo - This routine returns information about a plug-in. Each parameter should be - a pointer to a buffer of at least 256 characters, or NULL to not receive - the information. + This routine returns information about a plug-in. Each parameter should be + a pointer to a buffer of at least + 256 characters, or NULL to not receive the information. - outName - the human-readable name of the plug-in. outFilePath - the - absolute file path to the file that contains this plug-in. outSignature - a - unique string that identifies this plug-in. outDescription - a - human-readable description of this plug-in. + outName - the human-readable name of the plug-in. outFilePath - the + absolute file path to the file that contains this plug-in. outSignature - a + unique string that identifies this plug-in. outDescription - a + human-readable description of this plug-in. } PROCEDURE XPLMGetPluginInfo( inPlugin : XPLMPluginID; - outName : Pchar; { Can be nil } - outFilePath : Pchar; { Can be nil } - outSignature : Pchar; { Can be nil } - outDescription : Pchar); { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + outName : XPLMString; { Can be nil } + outFilePath : XPLMString; { Can be nil } + outSignature : XPLMString; { Can be nil } + outDescription : XPLMString); { Can be nil } + cdecl; external XPLM_DLL; {___________________________________________________________________________ * ENABLING/DISABLING PLUG-INS ___________________________________________________________________________} { - These routines are used to work with plug-ins and manage them. Most - plugins will not need to use these APIs. + These routines are used to work with plug-ins and manage them. Most + plugins will not need to use these APIs. } - { XPLMIsPluginEnabled - Returns whether the specified plug-in is enabled for running. + Returns whether the specified plug-in is enabled for running. } FUNCTION XPLMIsPluginEnabled( - inPluginID : XPLMPluginID) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inPluginID : XPLMPluginID) : Integer; + cdecl; external XPLM_DLL; { XPLMEnablePlugin - This routine enables a plug-in if it is not already enabled. It returns 1 - if the plugin was enabled or successfully enables itself, 0 if it does not. - Plugins may fail to enable (for example, if resources cannot be acquired) - by returning 0 from their XPluginEnable callback. + This routine enables a plug-in if it is not already enabled. It returns 1 + if the plugin was enabled or successfully enables itself, 0 if it does not. + Plugins may fail to enable (for example, if resources cannot be acquired) + by returning 0 from their XPluginEnable callback. } FUNCTION XPLMEnablePlugin( - inPluginID : XPLMPluginID) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inPluginID : XPLMPluginID) : Integer; + cdecl; external XPLM_DLL; { XPLMDisablePlugin - This routine disableds an enabled plug-in. + This routine disableds an enabled plug-in. } PROCEDURE XPLMDisablePlugin( inPluginID : XPLMPluginID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMReloadPlugins - This routine reloads all plug-ins. Once this routine is called and you - return from the callback you were within (e.g. a menu select callback) you - will receive your XPluginDisable and XPluginStop callbacks and your DLL - will be unloaded, then the start process happens as if the sim was starting - up. + This routine reloads all plug-ins. Once this routine is called and you + return from the callback you were within (e.g. a menu select callback) you + will receive your XPluginDisable and XPluginStop callbacks and your DLL + will be unloaded, then the start process happens as if the sim was starting + up. } PROCEDURE XPLMReloadPlugins; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; {___________________________________________________________________________ * INTERPLUGIN MESSAGING ___________________________________________________________________________} { - Plugin messages are defined as 32-bit integers. Messages below 0x00FFFFFF - are reserved for X-Plane and the plugin SDK. + Plugin messages are defined as 32-bit integers. Messages below 0x00FFFFFF + are reserved for X-Plane and the plugin SDK. - Messages have two conceptual uses: notifications and commands. Commands - are sent from one plugin to another to induce behavior; notifications are - sent from one plugin to all others for informational purposes. It is - important that commands and notifications not have the same values because - this could cause a notification sent by one plugin to accidentally induce a - command in another. + Messages come with a pointer parameter; the meaning of this pointer depends + on the message itself. In some messages, the pointer parameter contains an + actual typed pointer to data that can be inspected in the plugin; in these + cases the documentation will state that the parameter "points to" + information. - By convention, plugin-defined notifications should have the high bit set - (e.g. be greater or equal to unsigned 0x8000000) while commands should have - this bit be cleared. + in other cases, the value of the pointer is actually an integral number + stuffed into the pointer's storage. In these second cases, the pointer + parameter needs to be cast, not dereferenced. In these caess, the + documentation will state that the parameter "contains" a value, which will + always be an integral type. - The following messages are sent to your plugin by x-plane. + Some messages don't use the pointer parameter - in this case your plugin + should ignore it. + + Messages have two conceptual uses: notifications and commands. Commands + are sent from one plugin to another to induce behavior; notifications are + sent from one plugin to all others for informational purposes. It is + important that commands and notifications not have the same values because + this could cause a notification sent by one plugin to accidentally induce a + command in another. + + By convention, plugin-defined notifications should have the high bit set + (e.g. be greater or equal to unsigned 0x8000000) while commands should have + this bit be cleared. + + The following messages are sent to your plugin by X-Plane. } - CONST - { This message is sent to your plugin whenever the user's plane crashes. } + { This message is sent to your plugin whenever the user's plane crashes. The } + { parameter is ignored. } XPLM_MSG_PLANE_CRASHED = 101; - { This message is sent to your plugin whenever a new plane is loaded. The } - { parameter is the number of the plane being loaded; 0 indicates the user's } - { plane. } + { This message is sent to your plugin whenever a new plane is loaded. The } + { parameter contains the index number of the plane being loaded; 0 indicates } + { the user's plane. } XPLM_MSG_PLANE_LOADED = 102; - { This messages is called whenever the user's plane is positioned at a new } - { airport. } + { This messages is sent whenever the user's plane is positioned at a new } + { airport. The parameter is ignored. } XPLM_MSG_AIRPORT_LOADED = 103; - { This message is sent whenever new scenery is loaded. Use datarefs to } - { determine the new scenery files that were loaded. } + { This message is sent whenever new scenery is loaded. Use datarefs to } + { determine the new scenery files that were loaded. The parameter is ignored.} XPLM_MSG_SCENERY_LOADED = 104; - { This message is sent whenever the user adjusts the number of X-Plane } - { aircraft models. You must use XPLMCountPlanes to find out how many planes } - { are now available. This message will only be sent in XP7 and higher } - { because in XP6 the number of aircraft is not user-adjustable. } + { This message is sent whenever the user adjusts the number of X-Plane } + { aircraft models. You must use XPLMCountPlanes to find out how many planes } + { are now available. This message will only be sent in XP7 and higher } + { because in XP6 the number of aircraft is not user-adjustable. The parameter} + { is ignored. } XPLM_MSG_AIRPLANE_COUNT_CHANGED = 105; {$IFDEF XPLM200} - { This message is sent to your plugin whenever a plane is unloaded. The } - { parameter is the number of the plane being unloaded; 0 indicates the user's } - { plane. The parameter is of type int, passed as the value of the pointer. } - { (That is: the parameter is an int, not a pointer to an int.) } +CONST + { This message is sent to your plugin whenever a plane is unloaded. The } + { parameter contains the index number of the plane being unloaded; 0 } + { indicates the user's plane. The parameter is of type int, passed as the } + { value of the pointer. (That is: the parameter is an int, not a pointer to } + { an int.) } XPLM_MSG_PLANE_UNLOADED = 106; -{$ENDIF} +{$ENDIF XPLM200} {$IFDEF XPLM210} - { This message is sent to your plugin right before X-Plane writes its } - { preferences file. You can use this for two purposes: to write your own } - { preferences, and to modify any datarefs to influence preferences output. } - { For example, if your plugin temporarily modifies saved preferences, you can } - { put them back to their default values here to avoid having the tweaks be } - { persisted if your plugin is not loaded on the next invocation of X-Plane. } +CONST + { This message is sent to your plugin right before X-Plane writes its } + { preferences file. You can use this for two purposes: to write your own } + { preferences, and to modify any datarefs to influence preferences output. } + { For example, if your plugin temporarily modifies saved preferences, you can} + { put them back to their default values here to avoid having the tweaks be } + { persisted if your plugin is not loaded on the next invocation of X-Plane. } + { The parameter is ignored. } XPLM_MSG_WILL_WRITE_PREFS = 107; -{$ENDIF} +{$ENDIF XPLM210} {$IFDEF XPLM210} - { This message is sent to your plugin right after a livery is loaded for an } - { airplane. You can use this to check the new livery (via datarefs) and } - { react accordingly. The parameter is of type int, passed as the value of a } - { pointer and represents the aicraft plane number - 0 is the user's plane. } + { This message is sent to your plugin right after a livery is loaded for an } + { airplane. You can use this to check the new livery (via datarefs) and } + { react accordingly. The parameter contains the index number of the aircraft} + { whose livery is changing. } XPLM_MSG_LIVERY_LOADED = 108; -{$ENDIF} +{$ENDIF XPLM210} + +{$IFDEF XPLM301} +CONST + { Sent to your plugin right before X-Plane enters virtual reality mode (at } + { which time any windows that are not positioned in VR mode will no longer be} + { visible to the user). The parameter is unused and should be ignored. } + XPLM_MSG_ENTERED_VR = 109; +{$ENDIF XPLM301} + +{$IFDEF XPLM301} + { Sent to your plugin right before X-Plane leaves virtual reality mode (at } + { which time you may want to clean up windows that are positioned in VR } + { mode). The parameter is unused and should be ignored. } + XPLM_MSG_EXITING_VR = 110; +{$ENDIF XPLM301} + +{$IFDEF XPLM303} +CONST + { Sent to your plugin if another plugin wants to take over AI planes. If you } + { are a synthetic traffic provider, that probably means a plugin for an } + { online network has connected and wants to supply aircraft flown by real } + { humans and you should cease to provide synthetic traffic. If however you } + { are providing online traffic from real humans, you probably don't want to } + { disconnect, in which case you just ignore this message. The sender is the } + { plugin ID of the plugin asking for control of the planes now. You can use } + { it to find out who is requesting and whether you should yield to them. } + { Synthetic traffic providers should always yield to online networks. The } + { parameter is unused and should be ignored. } + XPLM_MSG_RELEASE_PLANES = 111; +{$ENDIF XPLM303} { XPLMSendMessageToPlugin - This function sends a message to another plug-in or X-Plane. Pass - XPLM_NO_PLUGIN_ID to broadcast to all plug-ins. Only enabled plug-ins with - a message receive function receive the message. + This function sends a message to another plug-in or X-Plane. Pass + XPLM_NO_PLUGIN_ID to broadcast to all plug-ins. Only enabled plug-ins with + a message receive function receive the message. } PROCEDURE XPLMSendMessageToPlugin( inPlugin : XPLMPluginID; - inMessage : integer; + inMessage : Integer; inParam : pointer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; {$IFDEF XPLM200} {___________________________________________________________________________ * Plugin Features API ___________________________________________________________________________} { - The plugin features API allows your plugin to "sign up" for additional - capabilities and plugin system features that are normally disabled for - backward compatibility. This allows advanced plugins to "opt-in" to new - behavior. + The plugin features API allows your plugin to "sign up" for additional + capabilities and plugin system features that are normally disabled for + backward compatibility. This allows advanced plugins to "opt-in" to new + behavior. - Each feature is defined by a permanent string name. The feature string - names will vary with the particular installation of X-Plane, so plugins - should not expect a feature to be guaranteed present. + Each feature is defined by a permanent string name. The feature string + names will vary with the particular installation of X-Plane, so plugins + should not expect a feature to be guaranteed present. + + XPLM_WANTS_REFLECTIONS + ---------------------- + + Available in the SDK 2.0 and later for X-Plane 9, enabling this capability + causes your plugin to receive drawing hook callbacks when X-Plane builds + its off-screen reflection and shadow rendering passes. Plugins should + enable this and examine the dataref sim/graphics/view/plane_render_type to + determine whether the drawing callback is for a reflection, shadow + calculation, or the main screen. Rendering can be simlified or omitted for + reflections, and non-solid drawing should be skipped for shadow + calculations. + + **Note**: direct drawing via draw callbacks is not recommended; use the + XPLMInstance API to create object models instead. + + XPLM_USE_NATIVE_PATHS + --------------------- + + available in the SDK 2.1 and later for X-Plane 10, this modifies the plugin + system to use Unix-style paths on all operating systems. With this enabled: + + * OS X paths will match the native OS X Unix. + * Windows will use forward slashes but preserve C:\ or another drive letter + when using complete file paths. + * Linux uses its native file system path scheme. + + Without this enabled: + + * OS X will use CFM file paths separated by a colon. + * Windows will use back-slashes and conventional DOS paths. + * Linux uses its native file system path scheme. + + All plugins should enable this feature on OS X to access the native file + system. + + XPLM_USE_NATIVE_WIDGET_WINDOWS + ------------------------------ + + Available in the SDK 3.0.2 SDK, this capability tells the widgets library + to use new, modern X-Plane backed XPLMDisplay windows to anchor all widget + trees. Without it, widgets will always use legacy windows. + + Plugins should enable this to allow their widget hierarchies to respond to + the user's UI size settings and to map widget-based windwos to a VR HMD. + + Before enabling this, make sure any custom widget code in your plugin is + prepared to cope with the UI coordinate system not being th same as the + OpenGL window coordinate system. } - - { XPLMFeatureEnumerator_f - You pass an XPLMFeatureEnumerator_f to get a list of all features supported - by a given version running version of X-Plane. This routine is called once - for each feature. + You pass an XPLMFeatureEnumerator_f to get a list of all features supported + by a given version running version of X-Plane. This routine is called once + for each feature. } TYPE XPLMFeatureEnumerator_f = PROCEDURE( - inFeature : Pchar; + inFeature : XPLMString; inRef : pointer); cdecl; { XPLMHasFeature - This returns 1 if the given installation of X-Plane supports a feature, or - 0 if it does not. + This returns 1 if the given installation of X-Plane supports a feature, or + 0 if it does not. } FUNCTION XPLMHasFeature( - inFeature : Pchar) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inFeature : XPLMString) : Integer; + cdecl; external XPLM_DLL; { XPLMIsFeatureEnabled - This returns 1 if a feature is currently enabled for your plugin, or 0 if - it is not enabled. It is an error to call this routine with an unsupported - feature. + This returns 1 if a feature is currently enabled for your plugin, or 0 if + it is not enabled. It is an error to call this routine with an unsupported + feature. } FUNCTION XPLMIsFeatureEnabled( - inFeature : Pchar) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inFeature : XPLMString) : Integer; + cdecl; external XPLM_DLL; { XPLMEnableFeature - This routine enables or disables a feature for your plugin. This will - change the running behavior of X-Plane and your plugin in some way, - depending on the feature. + This routine enables or disables a feature for your plugin. This will + change the running behavior of X-Plane and your plugin in some way, + depending on the feature. } PROCEDURE XPLMEnableFeature( - inFeature : Pchar; - inEnable : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inFeature : XPLMString; + inEnable : Integer); + cdecl; external XPLM_DLL; { XPLMEnumerateFeatures - This routine calls your enumerator callback once for each feature that this - running version of X-Plane supports. Use this routine to determine all of - the features that X-Plane can support. + This routine calls your enumerator callback once for each feature that this + running version of X-Plane supports. Use this routine to determine all of + the features that X-Plane can support. } PROCEDURE XPLMEnumerateFeatures( inEnumerator : XPLMFeatureEnumerator_f; inRef : pointer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; + +{$ENDIF XPLM200} -{$ENDIF} IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMProcessing.pas b/XPSDK/Delphi/XPLM/XPLMProcessing.pas index 79c7b2e..e09b6e5 100644 --- a/XPSDK/Delphi/XPLM/XPLMProcessing.pas +++ b/XPSDK/Delphi/XPLM/XPLMProcessing.pas @@ -1,276 +1,254 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMProcessing; INTERFACE { - This API allows you to get regular callbacks during the flight loop, the - part of X-Plane where the plane's position calculates the physics of - flight, etc. Use these APIs to accomplish periodic tasks like logging data - and performing I/O. + This API allows you to get regular callbacks during the flight loop, the + part of X-Plane where the plane's position calculates the physics of + flight, etc. Use these APIs to accomplish periodic tasks like logging data + and performing I/O. - WARNING: Do NOT use these callbacks to draw! You cannot draw during flight - loop callbacks. Use the drawing callbacks (see XPLMDisplay for more info) - for graphics. + You can receive a callback either just before or just after the per-frame + physics calculations happen - you can use post-FM callbacks to "patch" the + flight model after it has run. + + If the user has set the number of flight model iterations per frame greater + than one your plugin will _not_ see this; these integrations run on the + sub-section of the flight model where iterations improve responsiveness + (e.g. physical integration, not simple systems tracking) and are thus + opaque to plugins. + + Flight loop scheduling, when scheduled by time, is scheduled by a "first + callback after the deadline" schedule, e.g. your callbacks will always be + slightly late to ensure that we don't run faster than your deadline. + + WARNING: Do NOT use these callbacks to draw! You cannot draw during flight + loop callbacks. Use the drawing callbacks (see XPLMDisplay for more info) + for graphics. (One exception: you can use a post-flight loop callback to + update your own off-screen FBOs.) } -USES XPLMDefs; +USES + XPLMDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {___________________________________________________________________________ * FLIGHT LOOP CALLBACKS ___________________________________________________________________________} -{ - -} - - {$IFDEF XPLM210} { XPLMFlightLoopPhaseType - You can register a flight loop callback to run either before or after the - flight model is integrated by X-Plane. + You can register a flight loop callback to run either before or after the + flight model is integrated by X-Plane. } TYPE XPLMFlightLoopPhaseType = ( - { Your callback runs before X-Plane integrates the flight model. } + { Your callback runs before X-Plane integrates the flight model. } xplm_FlightLoop_Phase_BeforeFlightModel = 0 - { Your callback runs after X-Plane integrates the flight model. } + { Your callback runs after X-Plane integrates the flight model. } ,xplm_FlightLoop_Phase_AfterFlightModel = 1 ); PXPLMFlightLoopPhaseType = ^XPLMFlightLoopPhaseType; -{$ENDIF} +{$ENDIF XPLM210} {$IFDEF XPLM210} { XPLMFlightLoopID - This is an opaque identifier for a flight loop callback. You can use this - identifier to easily track and remove your callbacks, or to use the new - flight loop APIs. + This is an opaque identifier for a flight loop callback. You can use this + identifier to easily track and remove your callbacks, or to use the new + flight loop APIs. } XPLMFlightLoopID = pointer; PXPLMFlightLoopID = ^XPLMFlightLoopID; -{$ENDIF} +{$ENDIF XPLM210} { XPLMFlightLoop_f - This is your flight loop callback. Each time the flight loop is iterated - through, you receive this call at the end. You receive a time since you - were last called and a time since the last loop, as well as a loop counter. - The 'phase' parameter is deprecated and should be ignored. + This is your flight loop callback. Each time the flight loop is iterated + through, you receive this call at the end. - Your return value controls when you will next be called. Return 0 to stop - receiving callbacks. Pass a positive number to specify how many seconds - until the next callback. (You will be called at or after this time, not - before.) Pass a negative number to specify how many loops must go by until - you are called. For example, -1.0 means call me the very next loop. Try - to run your flight loop as infrequently as is practical, and suspend it - (using return value 0) when you do not need it; lots of flight loop - callbacks that do nothing lowers x-plane's frame rate. + Flight loop callbacks receive a number of input timing parameters. These + input timing parameters are not particularly useful; you may need to track + your own timing data (e.g. by reading datarefs). The input parameters are: - Your callback will NOT be unregistered if you return 0; it will merely be - inactive. + - inElapsedSinceLastCall: the wall time since your last callback. + - inElapsedTimeSinceLastFlightLoop: the wall time since any flight loop was + dispatched. + - inCounter: a monotonically increasing counter, bumped once per flight + loop dispatch from the sim. + - inRefcon: your own ptr constant from when you regitered yor callback. - The reference constant you passed to your loop is passed back to you. + Your return value controls when you will next be called. + + - Return 0 to stop receiving callbacks. + - Pass a positive number to specify how many seconds until the next + callback. (You will be called at or after this time, not before.) + - Pass a negative number to specify how many loops must go by until you + are called. For example, -1.0 means call me the very next loop. + + Try to run your flight loop as infrequently as is practical, and suspend it + (using return value 0) when you do not need it; lots of flight loop + callbacks that do nothing lowers X-Plane's frame rate. + + Your callback will NOT be unregistered if you return 0; it will merely be + inactive. } +TYPE XPLMFlightLoop_f = FUNCTION( - inElapsedSinceLastCall: single; - inElapsedTimeSinceLastFlightLoop: single; - inCounter : integer; - inRefcon : pointer) : single; cdecl; + inElapsedSinceLastCall: Single; + inElapsedTimeSinceLastFlightLoop: Single; + inCounter : Integer; + inRefcon : pointer) : Single; cdecl; {$IFDEF XPLM210} { XPLMCreateFlightLoop_t - XPLMCreateFlightLoop_t contains the parameters to create a new flight loop - callback. The strsucture can be expanded in future SDKs - always set - structSize to the size of your structure in bytes. + XPLMCreateFlightLoop_t contains the parameters to create a new flight loop + callback. The strsucture can be expanded in future SDKs - always set + structSize to the size of your structure in bytes. } +TYPE XPLMCreateFlightLoop_t = RECORD - structSize : integer; + structSize : Integer; phase : XPLMFlightLoopPhaseType; callbackFunc : XPLMFlightLoop_f; refcon : pointer; END; PXPLMCreateFlightLoop_t = ^XPLMCreateFlightLoop_t; -{$ENDIF} +{$ENDIF XPLM210} { XPLMGetElapsedTime - This routine returns the elapsed time since the sim started up in decimal - seconds. + This routine returns the elapsed time since the sim started up in decimal + seconds. This is a wall timer; it keeps counting upward even if the sim is + pasued. + + __WARNING__: XPLMGetElapsedTime is not a very good timer! It lacks + precision in both its data type and its source. Do not attempt to use it + for timing critical applications like network multiplayer. } - FUNCTION XPLMGetElapsedTime: single; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + FUNCTION XPLMGetElapsedTime: Single; + cdecl; external XPLM_DLL; { XPLMGetCycleNumber - This routine returns a counter starting at zero for each sim cycle - computed/video frame rendered. + This routine returns a counter starting at zero for each sim cycle + computed/video frame rendered. } - FUNCTION XPLMGetCycleNumber: integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + FUNCTION XPLMGetCycleNumber: Integer; + cdecl; external XPLM_DLL; { XPLMRegisterFlightLoopCallback - This routine registers your flight loop callback. Pass in a pointer to a - flight loop function and a refcon. inInterval defines when you will be - called. Pass in a positive number to specify seconds from registration - time to the next callback. Pass in a negative number to indicate when you - will be called (e.g. pass -1 to be called at the next cylcle). Pass 0 to - not be called; your callback will be inactive. + This routine registers your flight loop callback. Pass in a pointer to a + flight loop function and a refcon. inInterval defines when you will be + called. Pass in a positive number to specify seconds from registration time + to the next callback. Pass in a negative number to indicate when you will + be called (e.g. pass -1 to be called at the next cylcle). Pass 0 to not be + called; your callback will be inactive. + + (This legacy function only installs pre-flight-loop callbacks; use + XPLMCreateFlightLoop for more control.) } PROCEDURE XPLMRegisterFlightLoopCallback( inFlightLoop : XPLMFlightLoop_f; - inInterval : single; + inInterval : Single; inRefcon : pointer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMUnregisterFlightLoopCallback - This routine unregisters your flight loop callback. Do NOT call it from - your flight loop callback. Once your flight loop callback is - unregistered, it will not be called again. + This routine unregisters your flight loop callback. Do NOT call it from + your flight loop callback. Once your flight loop callback is unregistered, + it will not be called again. + + Only use this on flight loops registered via + XPLMRegisterFlightLoopCallback. } PROCEDURE XPLMUnregisterFlightLoopCallback( inFlightLoop : XPLMFlightLoop_f; inRefcon : pointer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMSetFlightLoopCallbackInterval - This routine sets when a callback will be called. Do NOT call it from your - callback; use the return value of the callback to change your callback - interval from inside your callback. + This routine sets when a callback will be called. Do NOT call it from your + callback; use the return value of the callback to change your callback + interval from inside your callback. - inInterval is formatted the same way as in XPLMRegisterFlightLoopCallback; - positive for seconds, negative for cycles, and 0 for deactivating the - callback. If inRelativeToNow is 1, times are from the time of this call; - otherwise they are from the time the callback was last called (or the time - it was registered if it has never been called. + inInterval is formatted the same way as in XPLMRegisterFlightLoopCallback; + positive for seconds, negative for cycles, and 0 for deactivating the + callback. If inRelativeToNow is 1, times are from the time of this call; + otherwise they are from the time the callback was last called (or the time + it was registered if it has never been called. } PROCEDURE XPLMSetFlightLoopCallbackInterval( inFlightLoop : XPLMFlightLoop_f; - inInterval : single; - inRelativeToNow : integer; + inInterval : Single; + inRelativeToNow : Integer; inRefcon : pointer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; {$IFDEF XPLM210} { XPLMCreateFlightLoop - This routine creates a flight loop callback and returns its ID. The flight - loop callback is created using the input param struct, and is inited to be - unscheduled. + This routine creates a flight loop callback and returns its ID. The flight + loop callback is created using the input param struct, and is inited to be + unscheduled. } FUNCTION XPLMCreateFlightLoop( inParams : PXPLMCreateFlightLoop_t) : XPLMFlightLoopID; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} + cdecl; external XPLM_DLL; +{$ENDIF XPLM210} {$IFDEF XPLM210} { XPLMDestroyFlightLoop - This routine destroys a flight loop callback by ID. + This routine destroys a flight loop callback by ID. Only call it on flight + loops created with the newer XPLMCreateFlightLoop API. } PROCEDURE XPLMDestroyFlightLoop( inFlightLoopID : XPLMFlightLoopID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} + cdecl; external XPLM_DLL; +{$ENDIF XPLM210} {$IFDEF XPLM210} { XPLMScheduleFlightLoop - This routine schedules a flight loop callback for future execution. If - inInterval is negative, it is run in a certain number of frames based on - the absolute value of the input. If the interval is positive, it is a - duration in seconds. + This routine schedules a flight loop callback for future execution. If + inInterval is negative, it is run in a certain number of frames based on + the absolute value of the input. If the interval is positive, it is a + duration in seconds. - If inRelativeToNow is true, ties are interpretted relative to the time this - routine is called; otherwise they are relative to the last call time or the - time the flight loop was registered (if never called). - - THREAD SAFETY: it is legal to call this routine from any thread under the - following conditions: - - 1. The call must be between the beginning of an XPLMEnable and the end of - an XPLMDisable sequence. (That is, you must not call this routine from - thread activity when your plugin was supposed to be disabled. Since - plugins are only enabled while loaded, this also implies you cannot run - this routine outside an XPLMStart/XPLMStop sequence.) - - 2. You may not call this routine re-entrantly for a single flight loop ID. - (That is, you can't enable from multiple threads at the same time.) - - 3. You must call this routine between the time after XPLMCreateFlightLoop - returns a value and the time you call XPLMDestroyFlightLoop. (That is, you - must ensure that your threaded activity is within the life of the object. - The SDK does not check this for you, nor does it synchronize destruction of - the object.) - - 4. The object must be unscheduled if this routine is to be called from a - thread other than the main thread. + If inRelativeToNow is true, ties are interpretted relative to the time this + routine is called; otherwise they are relative to the last call time or the + time the flight loop was registered (if never called). } PROCEDURE XPLMScheduleFlightLoop( inFlightLoopID : XPLMFlightLoopID; - inInterval : single; - inRelativeToNow : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} + inInterval : Single; + inRelativeToNow : Integer); + cdecl; external XPLM_DLL; +{$ENDIF XPLM210} + IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMScenery.pas b/XPSDK/Delphi/XPLM/XPLMScenery.pas index e0c51ac..a585830 100644 --- a/XPSDK/Delphi/XPLM/XPLMScenery.pas +++ b/XPSDK/Delphi/XPLM/XPLMScenery.pas @@ -1,67 +1,63 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMScenery; INTERFACE { - This package contains APIs to interact with X-Plane's scenery system. + This package contains APIs to interact with X-Plane's scenery system. } -USES XPLMDefs; +USES + XPLMDefs; {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} {$IFDEF XPLM200} {___________________________________________________________________________ * Terrain Y-Testing ___________________________________________________________________________} { - The Y-testing API allows you to locate the physical scenery mesh. This - would be used to place dynamic graphics on top of the ground in a - plausible way or do physics interactions. + The Y-testing API allows you to locate the physical scenery mesh. This + would be used to place dynamic graphics on top of the ground in a plausible + way or do physics interactions. - The Y-test API works via probe objects, which are allocated by your plugin - and used to query terrain. Probe objects exist both to capture which - algorithm you have requested (see probe types) and also to cache query - information. + The Y-test API works via probe objects, which are allocated by your plugin + and used to query terrain. Probe objects exist both to capture which + algorithm you have requested (see probe types) and also to cache query + information. - Performance guidelines: It is generally faster to use the same probe for - nearby points and different probes for different points. Try not to - allocate more than "hundreds" of probes at most. Share probes if you need - more. Generally, probing operations are expensive, and should be avoided - via caching when possible. + Performance Guidelines + ---------------------- - Y testing returns a location on the terrain, a normal vectory, and a - velocity vector. The normal vector tells you the slope of the terrain at - that point. The velocity vector tells you if that terrain is moving (and - is in meters/second). For example, if your Y test hits the aircraft carrier - deck, this tells you the velocity of that point on the deck. + It is generally faster to use the same probe for nearby points and + different probes for different points. Try not to allocate more than + "hundreds" of probes at most. Share probes if you need more. Generally, + probing operations are expensive, and should be avoided via caching when + possible. - Note: the Y-testing API is limited to probing the loaded scenery area, - which is approximately 300x300 km in X-Plane 9. Probes outside this area - will return the height of a 0 MSL sphere. + Y testing returns a location on the terrain, a normal vectory, and a + velocity vector. The normal vector tells you the slope of the terrain at + that point. The velocity vector tells you if that terrain is moving (and is + in meters/second). For example, if your Y test hits the aircraft carrier + deck, this tells you the velocity of that point on the deck. + + Note: the Y-testing API is limited to probing the loaded scenery area, + which is approximately 300x300 km in X-Plane 9. Probes outside this area + will return the height of a 0 MSL sphere. } - - { XPLMProbeType - XPLMProbeType defines the type of terrain probe - each probe has a - different algorithm. (Only one type of probe is provided right now, but - future APIs will expose more flexible or poewrful or useful probes. + XPLMProbeType defines the type of terrain probe - each probe has a + different algorithm. (Only one type of probe is provided right now, but + future APIs will expose more flexible or poewrful or useful probes. } TYPE XPLMProbeType = ( - { The Y probe gives you the location of the tallest physical scenery along } - { the Y axis going through the queried point. } + { The Y probe gives you the location of the tallest physical scenery along } + { the Y axis going through the queried point. } xplm_ProbeY = 0 ); @@ -70,18 +66,18 @@ TYPE { XPLMProbeResult - Probe results - possible results from a probe query. + Probe results - possible results from a probe query. } XPLMProbeResult = ( - { The probe hit terrain and returned valid values. } + { The probe hit terrain and returned valid values. } xplm_ProbeHitTerrain = 0 - { An error in the API call. Either the probe struct size is bad, or the } - { probe is invalid or the type is mismatched for the specific query call. } + { An error in the API call. Either the probe struct size is bad, or the } + { probe is invalid or the type is mismatched for the specific query call. } ,xplm_ProbeError = 1 - { The probe call succeeded but there is no terrain under this point (perhaps } - { it is off the side of the planet?) } + { The probe call succeeded but there is no terrain under this point (perhaps } + { it is off the side of the planet?) } ,xplm_ProbeMissed = 2 ); @@ -90,8 +86,8 @@ TYPE { XPLMProbeRef - An XPLMProbeRef is an opaque handle to a probe, used for querying the - terrain. + An XPLMProbeRef is an opaque handle to a probe, used for querying the + terrain. } XPLMProbeRef = pointer; PXPLMProbeRef = ^XPLMProbeRef; @@ -99,321 +95,340 @@ TYPE { XPLMProbeInfo_t - XPLMProbeInfo_t contains the results of a probe call. Make sure to set - structSize to the size of the struct before using it. + XPLMProbeInfo_t contains the results of a probe call. Make sure to set + structSize to the size of the struct before using it. } XPLMProbeInfo_t = RECORD - { Size of structure in bytes - always set this before calling the XPLM. } - structSize : integer; - { Resulting X location of the terrain point we hit, in local OpenGL } - { coordinates. } - locationX : single; - { Resulting Y location of the terrain point we hit, in local OpenGL } - { coordinates. } - locationY : single; - { Resulting Z location of the terrain point we hit, in local OpenGL } - { coordinates. } - locationZ : single; - { X component of the normal vector to the terrain we found. } - normalX : single; - { Y component of the normal vector to the terrain we found. } - normalY : single; - { Z component of the normal vector to the terrain we found. } - normalZ : single; - { X component of the velocity vector of the terrain we found. } - velocityX : single; - { Y component of the velocity vector of the terrain we found. } - velocityY : single; - { Z component of the velocity vector of the terrain we found. } - velocityZ : single; - { Tells if the surface we hit is water (otherwise it is land). } - is_wet : integer; + { Size of structure in bytes - always set this before calling the XPLM. } + structSize : Integer; + { Resulting X location of the terrain point we hit, in local OpenGL } + { coordinates. } + locationX : Single; + { Resulting Y location of the terrain point we hit, in local OpenGL } + { coordinates. } + locationY : Single; + { Resulting Z location of the terrain point we hit, in local OpenGL } + { coordinates. } + locationZ : Single; + { X component of the normal vector to the terrain we found. } + normalX : Single; + { Y component of the normal vector to the terrain we found. } + normalY : Single; + { Z component of the normal vector to the terrain we found. } + normalZ : Single; + { X component of the velocity vector of the terrain we found. } + velocityX : Single; + { Y component of the velocity vector of the terrain we found. } + velocityY : Single; + { Z component of the velocity vector of the terrain we found. } + velocityZ : Single; + { Tells if the surface we hit is water (otherwise it is land). } + is_wet : Integer; END; PXPLMProbeInfo_t = ^XPLMProbeInfo_t; { XPLMCreateProbe - Creates a new probe object of a given type and returns. + Creates a new probe object of a given type and returns. } FUNCTION XPLMCreateProbe( inProbeType : XPLMProbeType) : XPLMProbeRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMDestroyProbe - Deallocates an existing probe object. + Deallocates an existing probe object. } PROCEDURE XPLMDestroyProbe( inProbe : XPLMProbeRef); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMProbeTerrainXYZ - Probes the terrain. Pass in the XYZ coordinate of the probe point, a probe - object, and an XPLMProbeInfo_t struct that has its structSize member set - properly. Other fields are filled in if we hit terrain, and a probe result - is returned. + Probes the terrain. Pass in the XYZ coordinate of the probe point, a probe + object, and an XPLMProbeInfo_t struct that has its structSize member set + properly. Other fields are filled in if we hit terrain, and a probe result + is returned. } FUNCTION XPLMProbeTerrainXYZ( inProbe : XPLMProbeRef; - inX : single; - inY : single; - inZ : single; + inX : Single; + inY : Single; + inZ : Single; outInfo : PXPLMProbeInfo_t) : XPLMProbeResult; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; -{$ENDIF} +{$ENDIF XPLM200} +{$IFDEF XPLM300} +{___________________________________________________________________________ + * Magnetic Variation + ___________________________________________________________________________} +{ + Use the magnetic variation (more properly, the "magnetic declination") API + to find the offset of magnetic north from true north at a given latitude + and longitude within the simulator. + + In the real world, the Earth's magnetic field is irregular, such that true + north (the direction along a meridian toward the north pole) does not + necessarily match what a magnetic compass shows as north. + + Using this API ensures that you present the same offsets to users as + X-Plane's built-in instruments. +} + + + { + XPLMGetMagneticVariation + + Returns X-Plane's simulated magnetic variation (declination) at the + indication latitude and longitude. + } + FUNCTION XPLMGetMagneticVariation( + latitude : Real; + longitude : Real) : Single; + cdecl; external XPLM_DLL; + + { + XPLMDegTrueToDegMagnetic + + Converts a heading in degrees relative to true north into a value relative + to magnetic north at the user's current location. + } + FUNCTION XPLMDegTrueToDegMagnetic( + headingDegreesTrue : Single) : Single; + cdecl; external XPLM_DLL; + + { + XPLMDegMagneticToDegTrue + + Converts a heading in degrees relative to magnetic north at the user's + current location into a value relative to true north. + } + FUNCTION XPLMDegMagneticToDegTrue( + headingDegreesMagnetic: Single) : Single; + cdecl; external XPLM_DLL; + +{$ENDIF XPLM300} {___________________________________________________________________________ * Object Drawing ___________________________________________________________________________} { - The object drawing routines let you load and draw X-Plane OBJ files. - Objects are loaded by file path and managed via an opaque handle. X-Plane - naturally reference counts objects, so it is important that you balance - every successful call to XPLMLoadObject with a call to XPLMUnloadObject! + The object drawing routines let you load and draw X-Plane OBJ files. + Objects are loaded by file path and managed via an opaque handle. X-Plane + naturally reference counts objects, so it is important that you balance + every successful call to XPLMLoadObject with a call to XPLMUnloadObject! } - {$IFDEF XPLM200} TYPE { XPLMObjectRef - An XPLMObjectRef is a opaque handle to an .obj file that has been loaded - into memory. + An XPLMObjectRef is a opaque handle to an .obj file that has been loaded + into memory. } XPLMObjectRef = pointer; PXPLMObjectRef = ^XPLMObjectRef; -{$ENDIF} +{$ENDIF XPLM200} {$IFDEF XPLM200} { XPLMDrawInfo_t - The XPLMDrawInfo_t structure contains positioning info for one object that - is to be drawn. Be sure to set structSize to the size of the structure for - future expansion. + The XPLMDrawInfo_t structure contains positioning info for one object that + is to be drawn. Be sure to set structSize to the size of the structure for + future expansion. } XPLMDrawInfo_t = RECORD - { Set this to the size of this structure! } - structSize : integer; - { X location of the object in local coordinates. } - x : single; - { Y location of the object in local coordinates. } - y : single; - { Z location of the object in local coordinates. } - z : single; - { Pitch in degres to rotate the object, positive is up. } - pitch : single; - { Heading in local coordinates to rotate the object, clockwise. } - heading : single; - { Roll to rotate the object. } - roll : single; + { Set this to the size of this structure! } + structSize : Integer; + { X location of the object in local coordinates. } + x : Single; + { Y location of the object in local coordinates. } + y : Single; + { Z location of the object in local coordinates. } + z : Single; + { Pitch in degres to rotate the object, positive is up. } + pitch : Single; + { Heading in local coordinates to rotate the object, clockwise. } + heading : Single; + { Roll to rotate the object. } + roll : Single; END; PXPLMDrawInfo_t = ^XPLMDrawInfo_t; -{$ENDIF} +{$ENDIF XPLM200} {$IFDEF XPLM210} { XPLMObjectLoaded_f - You provide this callback when loading an object asynchronously; it will be - called once the object is loaded. Your refcon is passed back. The object - ref passed in is the newly loaded object (ready for use) or NULL if an - error occured. + You provide this callback when loading an object asynchronously; it will be + called once the object is loaded. Your refcon is passed back. The object + ref passed in is the newly loaded object (ready for use) or NULL if an + error occured. - If your plugin is disabled, this callback will be delivered as soon as the - plugin is re-enabled. If your plugin is unloaded before this callback is - ever called, the SDK will release the object handle for you. + If your plugin is disabled, this callback will be delivered as soon as the + plugin is re-enabled. If your plugin is unloaded before this callback is + ever called, the SDK will release the object handle for you. } +TYPE XPLMObjectLoaded_f = PROCEDURE( inObject : XPLMObjectRef; inRefcon : pointer); cdecl; -{$ENDIF} +{$ENDIF XPLM210} {$IFDEF XPLM200} { XPLMLoadObject - This routine loads an OBJ file and returns a handle to it. If X-plane has - already loaded the object, the handle to the existing object is returned. - Do not assume you will get the same handle back twice, but do make sure to - call unload once for every load to avoid "leaking" objects. The object - will be purged from memory when no plugins and no scenery are using it. + This routine loads an OBJ file and returns a handle to it. If X-Plane has + already loaded the object, the handle to the existing object is returned. + Do not assume you will get the same handle back twice, but do make sure to + call unload once for every load to avoid "leaking" objects. The object will + be purged from memory when no plugins and no scenery are using it. - The path for the object must be relative to the X-System base folder. If - the path is in the root of the X-System folder you may need to prepend ./ - to it; loading objects in the root of the X-System folder is STRONGLY - discouraged - your plugin should not dump art resources in the root folder! + The path for the object must be relative to the X-System base folder. If + the path is in the root of the X-System folder you may need to prepend ./ + to it; loading objects in the root of the X-System folder is STRONGLY + discouraged - your plugin should not dump art resources in the root folder! + XPLMLoadObject will return NULL if the object cannot be loaded (either + because it is not found or the file is misformatted). This routine will + load any object that can be used in the X-Plane scenery system. - XPLMLoadObject will return NULL if the object cannot be loaded (either - because it is not found or the file is misformatted). This routine will - load any object that can be used in the X-Plane scenery system. - - It is important that the datarefs an object uses for animation already be - loaded before you load the object. For this reason it may be necessary to - defer object loading until the sim has fully started. + It is important that the datarefs an object uses for animation already be + loaded before you load the object. For this reason it may be necessary to + defer object loading until the sim has fully started. } FUNCTION XPLMLoadObject( - inPath : Pchar) : XPLMObjectRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} + inPath : XPLMString) : XPLMObjectRef; + cdecl; external XPLM_DLL; +{$ENDIF XPLM200} {$IFDEF XPLM210} { XPLMLoadObjectAsync - This routine loads an object asynchronously; control is returned to you - immediately while X-Plane loads the object. The sim will not stop flying - while the object loads. For large objects, it may be several seconds - before the load finishes. + This routine loads an object asynchronously; control is returned to you + immediately while X-Plane loads the object. The sim will not stop flying + while the object loads. For large objects, it may be several seconds before + the load finishes. - You provide a callback function that is called once the load has completed. - Note that if the object cannot be loaded, you will not find out until the - callback function is called with a NULL object handle. + You provide a callback function that is called once the load has completed. + Note that if the object cannot be loaded, you will not find out until the + callback function is called with a NULL object handle. - There is no way to cancel an asynchronous object load; you must wait for - the load to complete and then release the object if it is no longer - desired. + There is no way to cancel an asynchronous object load; you must wait for + the load to complete and then release the object if it is no longer + desired. } PROCEDURE XPLMLoadObjectAsync( - inPath : Pchar; + inPath : XPLMString; inCallback : XPLMObjectLoaded_f; inRefcon : pointer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} + cdecl; external XPLM_DLL; +{$ENDIF XPLM210} -{$IFDEF XPLM200} +{$IFDEF XPLM_DEPRECATED} { XPLMDrawObjects - XPLMDrawObjects draws an object from an OBJ file one or more times. You - pass in the object and an array of XPLMDrawInfo_t structs, one for each - place you would like the object to be drawn. + __Deprecation Warning__: use XPLMInstancing to draw 3-d objects by creating + instances, rather than these APIs from draw callbacks. - X-Plane will attempt to cull the objects based on LOD and visibility, and - will pick the appropriate LOD. + XPLMDrawObjects draws an object from an OBJ file one or more times. You + pass in the object and an array of XPLMDrawInfo_t structs, one for each + place you would like the object to be drawn. - Lighting is a boolean; pass 1 to show the night version of object with - night-only lights lit up. Pass 0 to show the daytime version of the - object. + X-Plane will attempt to cull the objects based on LOD and visibility, and + will pick the appropriate LOD. - earth_relative controls the coordinate system. If this is 1, the rotations - you specify are applied to the object after its coordinate system is - transformed from local to earth-relative coordinates -- that is, an object - with no rotations will point toward true north and the Y axis will be up - against gravity. If this is 0, the object is drawn with your rotations - from local coordanates -- that is, an object with no rotations is drawn - pointing down the -Z axis and the Y axis of the object matches the local - coordinate Y axis. + Lighting is a boolean; pass 1 to show the night version of object with + night-only lights lit up. Pass 0 to show the daytime version of the object. + + earth_relative controls the coordinate system. If this is 1, the rotations + you specify are applied to the object after its coordinate system is + transformed from local to earth-relative coordinates -- that is, an object + with no rotations will point toward true north and the Y axis will be up + against gravity. If this is 0, the object is drawn with your rotations from + local coordanates -- that is, an object with no rotations is drawn pointing + down the -Z axis and the Y axis of the object matches the local coordinate + Y axis. } PROCEDURE XPLMDrawObjects( inObject : XPLMObjectRef; - inCount : integer; + inCount : Integer; inLocations : PXPLMDrawInfo_t; - lighting : integer; - earth_relative : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} + lighting : Integer; + earth_relative : Integer); + cdecl; external XPLM_DLL; +{$ENDIF XPLM_DEPRECATED} {$IFDEF XPLM200} { XPLMUnloadObject - This routine marks an object as no longer being used by your plugin. - Objects are reference counted: once no plugins are using an object, it is - purged from memory. Make sure to call XPLMUnloadObject once for each - successful call to XPLMLoadObject. + This routine marks an object as no longer being used by your plugin. + Objects are reference counted: once no plugins are using an object, it is + purged from memory. Make sure to call XPLMUnloadObject once for each + successful call to XPLMLoadObject. } PROCEDURE XPLMUnloadObject( inObject : XPLMObjectRef); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} + cdecl; external XPLM_DLL; +{$ENDIF XPLM200} {$IFDEF XPLM200} {___________________________________________________________________________ * Library Access ___________________________________________________________________________} { - The library access routines allow you to locate scenery objects via the - X-Plane library system. Right now library access is only provided for - objects, allowing plugin-drawn objects to be extended using the library - system. + The library access routines allow you to locate scenery objects via the + X-Plane library system. Right now library access is only provided for + objects, allowing plugin-drawn objects to be extended using the library + system. } - - { XPLMLibraryEnumerator_f - An XPLMLibraryEnumerator_f is a callback you provide that is called once - for each library element that is located. The returned paths will be - relative to the X-System folder. + An XPLMLibraryEnumerator_f is a callback you provide that is called once + for each library element that is located. The returned paths will be + relative to the X-System folder. } TYPE XPLMLibraryEnumerator_f = PROCEDURE( - inFilePath : Pchar; + inFilePath : XPLMString; inRef : pointer); cdecl; { XPLMLookupObjects - This routine looks up a virtual path in the library system and returns all - matching elements. You provide a callback - one virtual path may match - many objects in the library. XPLMLookupObjects returns the number of - objects found. + This routine looks up a virtual path in the library system and returns all + matching elements. You provide a callback - one virtual path may match many + objects in the library. XPLMLookupObjects returns the number of objects + found. - The latitude and longitude parameters specify the location the object will - be used. The library system allows for scenery packages to only provide - objects to certain local locations. Only objects that are allowed at the - latitude/longitude you provide will be returned. + The latitude and longitude parameters specify the location the object will + be used. The library system allows for scenery packages to only provide + objects to certain local locations. Only objects that are allowed at the + latitude/longitude you provide will be returned. } FUNCTION XPLMLookupObjects( - inPath : Pchar; - inLatitude : single; - inLongitude : single; + inPath : XPLMString; + inLatitude : Single; + inLongitude : Single; enumerator : XPLMLibraryEnumerator_f; - ref : pointer) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + ref : pointer) : Integer; + cdecl; external XPLM_DLL; + +{$ENDIF XPLM200} -{$ENDIF} IMPLEMENTATION + END. diff --git a/XPSDK/Delphi/XPLM/XPLMUtilities.pas b/XPSDK/Delphi/XPLM/XPLMUtilities.pas index 0595d1c..121e28b 100644 --- a/XPSDK/Delphi/XPLM/XPLMUtilities.pas +++ b/XPSDK/Delphi/XPLM/XPLMUtilities.pas @@ -1,40 +1,685 @@ { - Copyright 2005-2012 Sandy Barbour and Ben Supnik - - All rights reserved. See license.txt for usage. - - X-Plane SDK Version: 2.1.1 + Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved. See + license.txt for usage. X-Plane SDK Version: 2.1.1 } UNIT XPLMUtilities; INTERFACE + +USES + XPLMDefs; + {$A4} +{___________________________________________________________________________ + * FILE UTILITIES + ___________________________________________________________________________} { - + The XPLMUtilities file APIs provide some basic file and path functions for + use with X-Plane. + + Directory Separators + -------------------- + + The XPLM has two modes it can work in: + + * X-Plane native paths: all paths are UTF8 strings, using the unix forward + slash (/) as the directory separating character. In native path mode, + you use the same path format for all three operating systems. + + * Legacy OS paths: the directroy separator is \ for Windows, : for OS X, + and / for Linux; OS paths are encoded in MacRoman for OS X using legacy + HFS conventions, use the application code page for multi-byte encoding + on Unix using DOS path conventions, and use UTF-8 for Linux. + + While legacy OS paths are the default, we strongly encourage you to opt in + to native paths using the XPLMEnableFeature API. + + * All OS X plugins should enable native paths all of the time; if you do + not do this, you will have to convert all paths back from HFS to Unix + (and deal with MacRoman) - code written using native paths and the C + file APIs "just works" on OS X. + + * For Linux plugins, there is no difference between the two encodings. + + * Windows plugins will need to convert the UTF8 file paths to UTF16 for + use with the "wide" APIs. While it might seem tempting to stick with + legacy OS paths (and just use the "ANSI" Windows APIs), X-Plane is fully + unicode-capable, and will often be installed in paths where the user's + directories have no ACP encoding. + + Full and Relative Paths + ----------------------- + + Some of these APIs use full paths, but others use paths relative to the + user's X-Plane installation. This is documented on a per-API basis. } -USES XPLMDefs; - {$A4} -{$IFDEF MSWINDOWS} - {$DEFINE DELPHI} -{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMDataFileType + + These enums define types of data files you can load or unload using the + SDK. + } +TYPE + XPLMDataFileType = ( + { A situation (.sit) file, which starts off a flight in a given } + { configuration. } + xplm_DataFile_Situation = 1 + + { A situation movie (.smo) file, which replays a past flight. } + ,xplm_DataFile_ReplayMovie = 2 + + ); + PXPLMDataFileType = ^XPLMDataFileType; +{$ENDIF XPLM200} + + { + XPLMGetSystemPath + + This function returns the full path to the X-System folder. Note that this + is a directory path, so it ends in a trailing : or /. + + The buffer you pass should be at least 512 characters long. The path is + returned using the current native or OS path conventions. + } + PROCEDURE XPLMGetSystemPath( + outSystemPath : XPLMString); + cdecl; external XPLM_DLL; + + { + XPLMGetPrefsPath + + This routine returns a full path to a file that is within X-Plane's + preferences directory. (You should remove the file name back to the last + directory separator to get the preferences directory using + XPLMExtractFileAndPath.) + + The buffer you pass should be at least 512 characters long. The path is + returned using the current native or OS path conventions. + } + PROCEDURE XPLMGetPrefsPath( + outPrefsPath : XPLMString); + cdecl; external XPLM_DLL; + + { + XPLMGetDirectorySeparator + + This routine returns a string with one char and a null terminator that is + the directory separator for the current platform. This allows you to write + code that concatinates directory paths without having to #ifdef for + platform. The character returned will reflect the current file path mode. + } + FUNCTION XPLMGetDirectorySeparator: XPLMString; + cdecl; external XPLM_DLL; + + { + XPLMExtractFileAndPath + + Given a full path to a file, this routine separates the path from the file. + If the path is a partial directory (e.g. ends in : or \) the trailing + directory separator is removed. This routine works in-place; a pointer to + the file part of the buffer is returned; the original buffer still starts + with the path and is null terminated with no trailing separator. + } + FUNCTION XPLMExtractFileAndPath( + inFullPath : XPLMString) : XPLMString; + cdecl; external XPLM_DLL; + + { + XPLMGetDirectoryContents + + This routine returns a list of files in a directory (specified by a full + path, no trailing : or \). The output is returned as a list of NULL + terminated strings. An index array (if specified) is filled with pointers + into the strings. The last file is indicated by a zero-length string (and + NULL in the indices). This routine will return 1 if you had capacity for + all files or 0 if you did not. You can also skip a given number of files. + + * inDirectoryPath - a null terminated C string containing the full path to + the directory with no trailing directory char. + + * inFirstReturn - the zero-based index of the first file in the directory + to return. (Usually zero to fetch all in one pass.) + + * outFileNames - a buffer to receive a series of sequential null + terminated C-string file names. A zero-length C string will be appended + to the very end. + + * inFileNameBufSize - the size of the file name buffer in bytes. + + * outIndices - a pointer to an array of character pointers that will + become an index into the directory. The last file will be followed by a + NULL value. Pass NULL if you do not want indexing information. + + * inIndexCount - the max size of the index in entries. + + * outTotalFiles - if not NULL, this is filled in with the number of files + in the directory. + + * outReturnedFiles - if not NULL, the number of files returned by this + iteration. + + Return value: 1 if all info could be returned, 0 if there was a buffer + overrun. + + WARNING: Before X-Plane 7 this routine did not properly iterate through + directories. If X-Plane + 6 compatibility is needed, use your own code to iterate directories. + } + FUNCTION XPLMGetDirectoryContents( + inDirectoryPath : XPLMString; + inFirstReturn : Integer; + outFileNames : XPLMString; + inFileNameBufSize : Integer; + outIndices : PXPLMString; { Can be nil } + inIndexCount : Integer; + outTotalFiles : PInteger; { Can be nil } + outReturnedFiles : PInteger) : Integer; { Can be nil } + cdecl; external XPLM_DLL; + +{$IFDEF XPLM200} + { + XPLMLoadDataFile + + Loads a data file of a given type. Paths must be relative to the X-System + folder. To clear the replay, pass a NULL file name (this is only valid with + replay movies, not sit files). + } + FUNCTION XPLMLoadDataFile( + inFileType : XPLMDataFileType; + inFilePath : XPLMString) : Integer; { Can be nil } + cdecl; external XPLM_DLL; +{$ENDIF XPLM200} + +{$IFDEF XPLM200} + { + XPLMSaveDataFile + + Saves the current situation or replay; paths are relative to the X-System + folder. + } + FUNCTION XPLMSaveDataFile( + inFileType : XPLMDataFileType; + inFilePath : XPLMString) : Integer; + cdecl; external XPLM_DLL; +{$ENDIF XPLM200} + +{___________________________________________________________________________ + * X-PLANE MISC + ___________________________________________________________________________} + + { + XPLMHostApplicationID + + While the plug-in SDK is only accessible to plugins running inside X-Plane, + the original authors considered extending the API to other applications + that shared basic infrastructure with X-Plane. These enumerations are + hold-overs from that original roadmap; all values other than X-Plane are + deprecated. Your plugin should never need this enumeration. + } +TYPE + XPLMHostApplicationID = ( + xplm_Host_Unknown = 0 + + ,xplm_Host_XPlane = 1 + +{$IFDEF XPLM_DEPRECATED} + ,xplm_Host_PlaneMaker = 2 +{$ENDIF XPLM_DEPRECATED} + +{$IFDEF XPLM_DEPRECATED} + ,xplm_Host_WorldMaker = 3 +{$ENDIF XPLM_DEPRECATED} + +{$IFDEF XPLM_DEPRECATED} + ,xplm_Host_Briefer = 4 +{$ENDIF XPLM_DEPRECATED} + +{$IFDEF XPLM_DEPRECATED} + ,xplm_Host_PartMaker = 5 +{$ENDIF XPLM_DEPRECATED} + +{$IFDEF XPLM_DEPRECATED} + ,xplm_Host_YoungsMod = 6 +{$ENDIF XPLM_DEPRECATED} + +{$IFDEF XPLM_DEPRECATED} + ,xplm_Host_XAuto = 7 +{$ENDIF XPLM_DEPRECATED} + + ); + PXPLMHostApplicationID = ^XPLMHostApplicationID; + + { + XPLMLanguageCode + + These enums define what language the sim is running in. These enumerations + do not imply that the sim can or does run in all of these languages; they + simply provide a known encoding in the event that a given sim version is + localized to a certain language. + } + XPLMLanguageCode = ( + xplm_Language_Unknown = 0 + + ,xplm_Language_English = 1 + + ,xplm_Language_French = 2 + + ,xplm_Language_German = 3 + + ,xplm_Language_Italian = 4 + + ,xplm_Language_Spanish = 5 + + ,xplm_Language_Korean = 6 + +{$IFDEF XPLM200} + ,xplm_Language_Russian = 7 +{$ENDIF XPLM200} + +{$IFDEF XPLM200} + ,xplm_Language_Greek = 8 +{$ENDIF XPLM200} + +{$IFDEF XPLM200} + ,xplm_Language_Japanese = 9 +{$ENDIF XPLM200} + +{$IFDEF XPLM300} + ,xplm_Language_Chinese = 10 +{$ENDIF XPLM300} + + ); + PXPLMLanguageCode = ^XPLMLanguageCode; + +{$IFDEF XPLM200} + { + XPLMError_f + + An XPLM error callback is a function that you provide to receive debugging + information from the plugin SDK. See XPLMSetErrorCallback for more + information. NOTE: for the sake of debugging, your error callback will be + called even if your plugin is not enabled, allowing you to receive debug + info in your XPluginStart and XPluginStop callbacks. To avoid causing logic + errors in the management code, do not call any other plugin routines from + your error callback - it is only meant for catching errors in the + debugging. + } +TYPE + XPLMError_f = PROCEDURE( + inMessage : XPLMString); cdecl; +{$ENDIF XPLM200} + +{$IFDEF XPLM_DEPRECATED} + { + XPLMInitialized + + Deprecated: This function returns 1 if X-Plane has properly initialized the + plug-in system. If this routine returns 0, many XPLM functions will not + work. + + NOTE: because plugins are always called from within the XPLM, there is no + need to check for initialization; it will always return 1. This routine is + deprecated - you do not need to check it before continuing within your + plugin. + } + FUNCTION XPLMInitialized: Integer; + cdecl; external XPLM_DLL; +{$ENDIF XPLM_DEPRECATED} + + { + XPLMGetVersions + + This routine returns the revision of both X-Plane and the XPLM DLL. All + versions are three-digit decimal numbers (e.g. 606 for version 6.06 of + X-Plane); the current revision of the XPLM is 200 (2.00). This routine also + returns the host ID of the app running us. + + The most common use of this routine is to special-case around X-Plane + version-specific behavior. + } + PROCEDURE XPLMGetVersions( + outXPlaneVersion : PInteger; + outXPLMVersion : PInteger; + outHostID : PXPLMHostApplicationID); + cdecl; external XPLM_DLL; + + { + XPLMGetLanguage + + This routine returns the langauge the sim is running in. + } + FUNCTION XPLMGetLanguage: XPLMLanguageCode; + cdecl; external XPLM_DLL; + +{$IFDEF XPLM200} + { + XPLMFindSymbol + + This routine will attempt to find the symbol passed in the inString + parameter. If the symbol is found a pointer the function is returned, + othewise the function will return NULL. + + You can use XPLMFindSymbol to utilize newer SDK API features without + requiring newer versions of the SDK (and X-Plane) as your minimum X-Plane + version as follows: + + * Define the XPLMnnn macro to the minimum required XPLM version you will + ship with (e.g. XPLM210 for X-Plane 10 compatibility). + + * Use XPLMGetVersions and XPLMFindSymbol to detect that the host sim is + new enough to use new functions and resolve function pointers. + + * Conditionally use the new functions if and only if XPLMFindSymbol only + returns a non- NULL pointer. + + Warning: you should always check the XPLM API version as well as the + results of XPLMFindSymbol to determine if funtionality is safe to use. + + To use functionality via XPLMFindSymbol you will need to copy your own + definitions of the X-Plane API prototypes and cast the returned pointer to + the correct type. + } + FUNCTION XPLMFindSymbol( + inString : XPLMString) : pointer; + cdecl; external XPLM_DLL; +{$ENDIF XPLM200} + +{$IFDEF XPLM200} + { + XPLMSetErrorCallback + + XPLMSetErrorCallback installs an error-reporting callback for your plugin. + Normally the plugin system performs minimum diagnostics to maximize + performance. When you install an error callback, you will receive calls due + to certain plugin errors, such as passing bad parameters or incorrect data. + + Important: the error callback determines *programming* errors, e.g. bad API + parameters. Every error that is returned by the error callback represents a + mistake in your plugin that you should fix. Error callbacks are not used to + report expected run-time problems (e.g. disk I/O errors). + + The intention is for you to install the error callback during debug + sections and put a break-point inside your callback. This will cause you to + break into the debugger from within the SDK at the point in your plugin + where you made an illegal call. + + Installing an error callback may activate error checking code that would + not normally run, and this may adversely affect performance, so do not + leave error callbacks installed in shipping plugins. Since the only useful + response to an error is to change code, error callbacks are not useful "in + the field". + } + PROCEDURE XPLMSetErrorCallback( + inCallback : XPLMError_f); + cdecl; external XPLM_DLL; +{$ENDIF XPLM200} + + { + XPLMDebugString + + This routine outputs a C-style string to the Log.txt file. The file is + immediately flushed so you will not lose data. (This does cause a + performance penalty.) + + Please do *not* leave routine diagnostic logging enabled in your shipping + plugin. The X-Plane Log file is shared by X-Plane and every plugin in the + system, and plugins that (when functioning normally) print verbose log + output make it difficult for developers to find error conditions from other + parts of the system. + } + PROCEDURE XPLMDebugString( + inString : XPLMString); + cdecl; external XPLM_DLL; + + { + XPLMSpeakString + + This function displays the string in a translucent overlay over the current + display and also speaks the string if text-to-speech is enabled. The string + is spoken asynchronously, this function returns immediately. This function + may not speak or print depending on user preferences. + } + PROCEDURE XPLMSpeakString( + inString : XPLMString); + cdecl; external XPLM_DLL; + + { + XPLMGetVirtualKeyDescription + + Given a virtual key code (as defined in XPLMDefs.h) this routine returns a + human-readable string describing the character. This routine is provided + for showing users what keyboard mappings they have set up. The string may + read 'unknown' or be a blank or NULL string if the virtual key is unknown. + } + FUNCTION XPLMGetVirtualKeyDescription( + inVirtualKey : XPLMChar) : XPLMString; + cdecl; external XPLM_DLL; + + { + XPLMReloadScenery + + XPLMReloadScenery reloads the current set of scenery. You can use this + function in two typical ways: simply call it to reload the scenery, picking + up any new installed scenery, .env files, etc. from disk. Or, change the + lat/ref and lon/ref data refs and then call this function to shift the + scenery environment. This routine is equivalent to picking "reload + scenery" from the developer menu. + } + PROCEDURE XPLMReloadScenery; + cdecl; external XPLM_DLL; + +{$IFDEF XPLM200} +{___________________________________________________________________________ + * X-PLANE COMMAND MANAGEMENT + ___________________________________________________________________________} +{ + The command management APIs let plugins interact with the command-system in + X-Plane, the abstraction behind keyboard presses and joystick buttons. This + API lets you create new commands and modify the behavior (or get + notification) of existing ones. + + X-Plane Command Phases + ---------------------- + + X-Plane commands are not instantaneous; they operate over a duration. + (Think of a joystick button press - you can press, hold down, and then + release the joystick button; X-Plane commands model this entire process.) + + An X-Plane command consists of three phases: a beginning, continuous + repetition, and an ending. The command may be repeated zero times in its + duration, followed by one command ending. Command begin and end messges are + balanced, but a command may be bound to more than one event source (e.g. a + keyboard key and a joystick button), in which case you may receive a second + begin during before any end). + + When you issue commands in the plugin system, you *must* balance every call + to XPLMCommandBegin with a call to XPLMCommandEnd with the same command + reference. + + Command Behavior Modification + ----------------------------- + + You can register a callback to handle a command either before or after + X-Plane does; if you receive the command before X-Plane you have the option + to either let X-Plane handle the command or hide the command from X-Plane. + This lets plugins both augment commands and replace them. + + If you register for an existing command, be sure that you are *consistent* + in letting X-Plane handle or not handle the command; you are responsible + for passing a *balanced* number of begin and end messages to X-Plane. (E.g. + it is not legal to pass all the begin messages to X-Plane but hide all the + end messages). +} + + + { + XPLMCommandPhase + + The phases of a command. + } +TYPE + XPLMCommandPhase = ( + { The command is being started. } + xplm_CommandBegin = 0 + + { The command is continuing to execute. } + ,xplm_CommandContinue = 1 + + { The command has ended. } + ,xplm_CommandEnd = 2 + + ); + PXPLMCommandPhase = ^XPLMCommandPhase; + + { + XPLMCommandRef + + A command ref is an opaque identifier for an X-Plane command. Command + references stay the same for the life of your plugin but not between + executions of X-Plane. Command refs are used to execute commands, create + commands, and create callbacks for particular commands. + + Note that a command is not "owned" by a particular plugin. Since many + plugins may participate in a command's execution, the command does not go + away if the plugin that created it is unloaded. + } + XPLMCommandRef = pointer; + PXPLMCommandRef = ^XPLMCommandRef; + + { + XPLMCommandCallback_f + + A command callback is a function in your plugin that is called when a + command is pressed. Your callback receives the command reference for the + particular command, the phase of the command that is executing, and a + reference pointer that you specify when registering the callback. + + Your command handler should return 1 to let processing of the command + continue to other plugins and X-Plane, or 0 to halt processing, potentially + bypassing X-Plane code. + } + XPLMCommandCallback_f = FUNCTION( + inCommand : XPLMCommandRef; + inPhase : XPLMCommandPhase; + inRefcon : pointer) : Integer; cdecl; + + { + XPLMFindCommand + + XPLMFindCommand looks up a command by name, and returns its command + reference or NULL if the command does not exist. + } + FUNCTION XPLMFindCommand( + inName : XPLMString) : XPLMCommandRef; + cdecl; external XPLM_DLL; + + { + XPLMCommandBegin + + XPLMCommandBegin starts the execution of a command, specified by its + command reference. The command is "held down" until XPLMCommandEnd is + called. You must balance each XPLMCommandBegin call with an XPLMCommandEnd + call. + } + PROCEDURE XPLMCommandBegin( + inCommand : XPLMCommandRef); + cdecl; external XPLM_DLL; + + { + XPLMCommandEnd + + XPLMCommandEnd ends the execution of a given command that was started with + XPLMCommandBegin. You must not issue XPLMCommandEnd for a command you did + not begin. + } + PROCEDURE XPLMCommandEnd( + inCommand : XPLMCommandRef); + cdecl; external XPLM_DLL; + + { + XPLMCommandOnce + + This executes a given command momentarily, that is, the command begins and + ends immediately. This is the equivalent of calling XPLMCommandBegin() and + XPLMCommandEnd() back ot back. + } + PROCEDURE XPLMCommandOnce( + inCommand : XPLMCommandRef); + cdecl; external XPLM_DLL; + + { + XPLMCreateCommand + + XPLMCreateCommand creates a new command for a given string. If the command + already exists, the existing command reference is returned. The description + may appear in user interface contexts, such as the joystick configuration + screen. + } + FUNCTION XPLMCreateCommand( + inName : XPLMString; + inDescription : XPLMString) : XPLMCommandRef; + cdecl; external XPLM_DLL; + + { + XPLMRegisterCommandHandler + + XPLMRegisterCommandHandler registers a callback to be called when a command + is executed. You provide a callback with a reference pointer. + + If inBefore is true, your command handler callback will be executed before + X-Plane executes the command, and returning 0 from your callback will + disable X-Plane's processing of the command. If inBefore is false, your + callback will run after X-Plane. (You can register a single callback both + before and after a command.) + } + PROCEDURE XPLMRegisterCommandHandler( + inComand : XPLMCommandRef; + inHandler : XPLMCommandCallback_f; + inBefore : Integer; + inRefcon : pointer); + cdecl; external XPLM_DLL; + + { + XPLMUnregisterCommandHandler + + XPLMUnregisterCommandHandler removes a command callback registered with + XPLMRegisterCommandHandler. + } + PROCEDURE XPLMUnregisterCommandHandler( + inComand : XPLMCommandRef; + inHandler : XPLMCommandCallback_f; + inBefore : Integer; + inRefcon : pointer); + cdecl; external XPLM_DLL; + +{$ENDIF XPLM200} +{$IFDEF XPLM_DEPRECATED} {___________________________________________________________________________ * X-PLANE USER INTERACTION ___________________________________________________________________________} { - The user interaction APIs let you simulate commands the user can do with a - joystick, keyboard etc. Note that it is generally safer for future - compatibility to use one of these commands than to manipulate the - underlying sim data. + WARNING: The legacy user interaction API is deprecated; while it was the + only way to run commands in X-Plane 6,7 and 8, it is obsolete, and was + replaced by the command system API in X-Plane 9. You should not use this + API; replace any of the calls below with XPLMCommand invocations based on + persistent command strings. The documentation that follows is for historic + reference only. + + The legacy user interaction APIs let you simulate commands the user can do + with a joystick, keyboard etc. Note that it is generally safer for future + compatibility to use one of these commands than to manipulate the + underlying sim data. } - { XPLMCommandKeyID - These enums represent all the keystrokes available within x-plane. They - can be sent to x-plane directly. For example, you can reverse thrust using - these enumerations. + These enums represent all the keystrokes available within X-Plane. They can + be sent to X-Plane directly. For example, you can reverse thrust using + these enumerations. } TYPE XPLMCommandKeyID = ( @@ -139,10 +784,10 @@ TYPE { XPLMCommandButtonID - These are enumerations for all of the things you can do with a joystick - button in X-Plane. They currently match the buttons menu in the equipment - setup dialog, but these enums will be stable even if they change in - X-Plane. + These are enumerations for all of the things you can do with a joystick + button in X-Plane. They currently match the buttons menu in the equipment + setup dialog, but these enums will be stable even if they change in + X-Plane. } XPLMCommandButtonID = ( xplm_joy_nothing=0, @@ -243,685 +888,64 @@ TYPE ); PXPLMCommandButtonID = ^XPLMCommandButtonID; - { - XPLMHostApplicationID - - The plug-in system is based on Austin's cross-platform OpenGL framework and - could theoretically be adapted to run in other apps like WorldMaker. The - plug-in system also runs against a test harness for internal development - and could be adapted to another flight sim (in theory at least). So an ID - is providing allowing plug-ins to indentify what app they are running - under. - } - XPLMHostApplicationID = ( - xplm_Host_Unknown = 0 - - ,xplm_Host_XPlane = 1 - - ,xplm_Host_PlaneMaker = 2 - - ,xplm_Host_WorldMaker = 3 - - ,xplm_Host_Briefer = 4 - - ,xplm_Host_PartMaker = 5 - - ,xplm_Host_YoungsMod = 6 - - ,xplm_Host_XAuto = 7 - - ); - PXPLMHostApplicationID = ^XPLMHostApplicationID; - - { - XPLMLanguageCode - - These enums define what language the sim is running in. These enumerations - do not imply that the sim can or does run in all of these languages; they - simply provide a known encoding in the event that a given sim version is - localized to a certain language. - } - XPLMLanguageCode = ( - xplm_Language_Unknown = 0 - - ,xplm_Language_English = 1 - - ,xplm_Language_French = 2 - - ,xplm_Language_German = 3 - - ,xplm_Language_Italian = 4 - - ,xplm_Language_Spanish = 5 - - ,xplm_Language_Korean = 6 - -{$IFDEF XPLM200} - ,xplm_Language_Russian = 7 -{$ENDIF} - -{$IFDEF XPLM200} - ,xplm_Language_Greek = 8 -{$ENDIF} - -{$IFDEF XPLM200} - ,xplm_Language_Japanese = 9 -{$ENDIF} - -{$IFDEF XPLM200} - ,xplm_Language_Chinese = 10 -{$ENDIF} - - ); - PXPLMLanguageCode = ^XPLMLanguageCode; - -{$IFDEF XPLM200} - { - XPLMDataFileType - - These enums define types of data files you can load or unload using the - SDK. - } - XPLMDataFileType = ( - { A situation (.sit) file, which starts off a flight in a given } - { configuration. } - xplm_DataFile_Situation = 1 - - { A situation movie (.smo) file, which replays a past flight. } - ,xplm_DataFile_ReplayMovie = 2 - - ); - PXPLMDataFileType = ^XPLMDataFileType; -{$ENDIF} - -{$IFDEF XPLM200} - { - XPLMError_f - - An XPLM error callback is a function that you provide to receive debugging - information from the plugin SDK. See XPLMSetErrorCallback for more - information. NOTE: for the sake of debugging, your error callback will be - called even if your plugin is not enabled, allowing you to receive debug - info in your XPluginStart and XPluginStop callbacks. To avoid causing - logic errors in the management code, do not call any other plugin routines - from your error callback - it is only meant for logging! - } - XPLMError_f = PROCEDURE( - inMessage : Pchar); cdecl; -{$ENDIF} - { XPLMSimulateKeyPress - This function simulates a key being pressed for x-plane. The keystroke - goes directly to x-plane; it is never sent to any plug-ins. However, since - this is a raw key stroke it may be mapped by the keys file or enter text - into a field. + This function simulates a key being pressed for X-Plane. The keystroke goes + directly to X-Plane; it is never sent to any plug-ins. However, since this + is a raw key stroke it may be mapped by the keys file or enter text into a + field. - WARNING: This function will be deprecated; do not use it. Instead use - XPLMCommandKeyStroke. + Deprecated: use XPLMCommandOnce } PROCEDURE XPLMSimulateKeyPress( - inKeyType : integer; - inKey : integer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMSpeakString - - This function displays the string in a translucent overlay over the current - display and also speaks the string if text-to-speech is enabled. The - string is spoken asynchronously, this function returns immediately. - } - PROCEDURE XPLMSpeakString( - inString : Pchar); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + inKeyType : Integer; + inKey : Integer); + cdecl; external XPLM_DLL; { XPLMCommandKeyStroke - This routine simulates a command-key stroke. However, the keys are done by - function, not by actual letter, so this function works even if the user has - remapped their keyboard. Examples of things you might do with this include - pausing the simulator. + This routine simulates a command-key stroke. However, the keys are done by + function, not by actual letter, so this function works even if the user has + remapped their keyboard. Examples of things you might do with this include + pausing the simulator. + + Deprecated: use XPLMCommandOnce } PROCEDURE XPLMCommandKeyStroke( inKey : XPLMCommandKeyID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMCommandButtonPress - This function simulates any of the actions that might be taken by pressing - a joystick button. However, this lets you call the command directly rather - than have to know which button is mapped where. Important: you must - release each button you press. The APIs are separate so that you can 'hold - down' a button for a fixed amount of time. + This function simulates any of the actions that might be taken by pressing + a joystick button. However, this lets you call the command directly rather + than have to know which button is mapped where. Important: you must release + each button you press. The APIs are separate so that you can 'hold down' a + button for a fixed amount of time. + + Deprecated: use XPLMCommandBegin. } PROCEDURE XPLMCommandButtonPress( inButton : XPLMCommandButtonID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; { XPLMCommandButtonRelease - This function simulates any of the actions that might be taken by pressing - a joystick button. See XPLMCommandButtonPress + This function simulates any of the actions that might be taken by pressing + a joystick button. See XPLMCommandButtonPress. + + Deprecated: use XPLMCommandEnd. } PROCEDURE XPLMCommandButtonRelease( inButton : XPLMCommandButtonID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} + cdecl; external XPLM_DLL; - { - XPLMGetVirtualKeyDescription - - Given a virtual key code (as defined in XPLMDefs.h) this routine returns a - human-readable string describing the character. This routine is provided - for showing users what keyboard mappings they have set up. The string may - read 'unknown' or be a blank or NULL string if the virtual key is unknown. - } - FUNCTION XPLMGetVirtualKeyDescription( - inVirtualKey : char) : Pchar; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} +{$ENDIF XPLM_DEPRECATED} -{___________________________________________________________________________ - * X-PLANE MISC - ___________________________________________________________________________} -{ - -} - - - - { - XPLMReloadScenery - - XPLMReloadScenery reloads the current set of scenery. You can use this - function in two typical ways: simply call it to reload the scenery, picking - up any new installed scenery, .env files, etc. from disk. Or, change the - lat/ref and lon/ref data refs and then call this function to shift the - scenery environment. - } - PROCEDURE XPLMReloadScenery; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMGetSystemPath - - This function returns the full path to the X-System folder. Note that this - is a directory path, so it ends in a trailing : or /. The buffer you pass - should be at least 512 characters long. - } - PROCEDURE XPLMGetSystemPath( - outSystemPath : Pchar); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMGetPrefsPath - - This routine returns a full path to the proper directory to store - preferences in. It ends in a : or /. The buffer you pass should be at - least 512 characters long. - } - PROCEDURE XPLMGetPrefsPath( - outPrefsPath : Pchar); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMGetDirectorySeparator - - This routine returns a string with one char and a null terminator that is - the directory separator for the current platform. This allows you to write - code that concatinates directory paths without having to #ifdef for - platform. - } - FUNCTION XPLMGetDirectorySeparator: Pchar; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMExtractFileAndPath - - Given a full path to a file, this routine separates the path from the file. - If the path is a partial directory (e.g. ends in : or \) the trailing - directory separator is removed. This routine works in-place; a pointer to - the file part of the buffer is returned; the original buffer still starts - with the path. - } - FUNCTION XPLMExtractFileAndPath( - inFullPath : Pchar) : Pchar; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMGetDirectoryContents - - This routine returns a list of files in a directory (specified by a full - path, no trailing : or \). The output is returned as a list of NULL - terminated strings. An index array (if specified) is filled with pointers - into the strings. This routine The last file is indicated by a zero-length - string (and NULL in the indices). This routine will return 1 if you had - capacity for all files or 0 if you did not. You can also skip a given - number of files. - - inDirectoryPath - a null terminated C string containing the full path to - the directory with no trailing directory char. - - inFirstReturn - the zero-based index of the first file in the directory to - return. (Usually zero to fetch all in one pass.) - - outFileNames - a buffer to receive a series of sequential null terminated - C-string file names. A zero-length C string will be appended to the very - end. - - inFileNameBufSize - the size of the file name buffer in bytes. - - outIndices - a pointer to an array of character pointers that will become - an index into the directory. The last file will be followed by a NULL - value. Pass NULL if you do not want indexing information. - - inIndexCount - the max size of the index in entries. - - outTotalFiles - if not NULL, this is filled in with the number of files in - the directory. - - outReturnedFiles - if not NULL, the number of files returned by this - iteration. - - Return value - 1 if all info could be returned, 0 if there was a buffer - overrun. - - WARNING: Before X-Plane 7 this routine did not properly iterate through - directories. If X-Plane 6 compatibility is needed, use your own code to - iterate directories. - } - FUNCTION XPLMGetDirectoryContents( - inDirectoryPath : Pchar; - inFirstReturn : integer; - outFileNames : Pchar; - inFileNameBufSize : integer; - outIndices : PPchar; { Can be nil } - inIndexCount : integer; - outTotalFiles : Pinteger; { Can be nil } - outReturnedFiles : Pinteger) : integer; { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMInitialized - - This function returns 1 if X-Plane has properly initialized the plug-in - system. If this routine returns 0, many XPLM functions will not work. - - NOTE: Under normal circumstances a plug-in should never be running while - the plug-in manager is not initialized. - - WARNING: This function is generally not needed and may be deprecated in the - future. - } - FUNCTION XPLMInitialized: integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMGetVersions - - This routine returns the revision of both X-Plane and the XPLM DLL. All - versions are three-digit decimal numbers (e.g. 606 for version 6.06 of - X-Plane); the current revision of the XPLM is 200 (2.00). This routine - also returns the host ID of the app running us. - - The most common use of this routine is to special-case around x-plane - version-specific behavior. - } - PROCEDURE XPLMGetVersions( - outXPlaneVersion : Pinteger; - outXPLMVersion : Pinteger; - outHostID : PXPLMHostApplicationID); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMGetLanguage - - This routine returns the langauge the sim is running in. - } - FUNCTION XPLMGetLanguage: XPLMLanguageCode; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMDebugString - - This routine outputs a C-style string to the Log.txt file. The file is - immediately flushed so you will not lose data. (This does cause a - performance penalty.) - } - PROCEDURE XPLMDebugString( - inString : Pchar); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - -{$IFDEF XPLM200} - { - XPLMSetErrorCallback - - XPLMSetErrorCallback installs an error-reporting callback for your plugin. - Normally the plugin system performs minimum diagnostics to maximize - performance. When you install an error callback, you will receive calls - due to certain plugin errors, such as passing bad parameters or incorrect - data. - - The intention is for you to install the error callback during debug - sections and put a break-point inside your callback. This will cause you - to break into the debugger from within the SDK at the point in your plugin - where you made an illegal call. - - Installing an error callback may activate error checking code that would - not normally run, and this may adversely affect performance, so do not - leave error callbacks installed in shipping plugins. - } - PROCEDURE XPLMSetErrorCallback( - inCallback : XPLMError_f); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} - -{$IFDEF XPLM200} - { - XPLMFindSymbol - - This routine will attempt to find the symbol passed in the inString - parameter. If the symbol is found a pointer the function is returned, - othewise the function will return NULL. - } - FUNCTION XPLMFindSymbol( - inString : Pchar) : pointer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} - -{$IFDEF XPLM200} - { - XPLMLoadDataFile - - Loads a data file of a given type. Paths must be relative to the X-System - folder. To clear the replay, pass a NULL file name (this is only valid with - replay movies, not sit files). - } - FUNCTION XPLMLoadDataFile( - inFileType : XPLMDataFileType; - inFilePath : Pchar) : integer; { Can be nil } -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} - -{$IFDEF XPLM200} - { - XPLMSaveDataFile - - Saves the current situation or replay; paths are relative to the X-System - folder. - } - FUNCTION XPLMSaveDataFile( - inFileType : XPLMDataFileType; - inFilePath : Pchar) : integer; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} -{$ENDIF} - -{$IFDEF XPLM200} -{___________________________________________________________________________ - * X-PLANE COMMAND MANAGEMENT - ___________________________________________________________________________} -{ - The command management APIs let plugins interact with the command-system in - X-Plane, the abstraction behind keyboard presses and joystick buttons. - This API lets you create new commands and modify the behavior (or get - notification) of existing ones. - - An X-Plane command consists of three phases: a beginning, continuous - repetition, and an ending. The command may be repeated zero times in the - event that the user presses a button only momentarily. -} - - - - - { - XPLMCommandPhase - - The phases of a command. - } -TYPE - XPLMCommandPhase = ( - { The command is being started. } - xplm_CommandBegin = 0 - - { The command is continuing to execute. } - ,xplm_CommandContinue = 1 - - { The command has ended. } - ,xplm_CommandEnd = 2 - - ); - PXPLMCommandPhase = ^XPLMCommandPhase; - - { - XPLMCommandRef - - A command ref is an opaque identifier for an X-Plane command. Command - references stay the same for the life of your plugin but not between - executions of X-Plane. Command refs are used to execute commands, create - commands, and create callbacks for particular commands. - - Note that a command is not "owned" by a particular plugin. Since many - plugins may participate in a command's execution, the command does not go - away if the plugin that created it is unloaded. - } - XPLMCommandRef = pointer; - PXPLMCommandRef = ^XPLMCommandRef; - - { - XPLMCommandCallback_f - - A command callback is a function in your plugin that is called when a - command is pressed. Your callback receives the commadn reference for the - particular command, the phase of the command that is executing, and a - reference pointer that you specify when registering the callback. - - Your command handler should return 1 to let processing of the command - continue to other plugins and X-Plane, or 0 to halt processing, - potentially bypassing X-Plane code. - } - XPLMCommandCallback_f = FUNCTION( - inCommand : XPLMCommandRef; - inPhase : XPLMCommandPhase; - inRefcon : pointer) : integer; cdecl; - - { - XPLMFindCommand - - XPLMFindCommand looks up a command by name, and returns its command - reference or NULL if the command does not exist. - } - FUNCTION XPLMFindCommand( - inName : Pchar) : XPLMCommandRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMCommandBegin - - XPLMCommandBegin starts the execution of a command, specified by its - command reference. The command is "held down" until XPLMCommandEnd is - called. - } - PROCEDURE XPLMCommandBegin( - inCommand : XPLMCommandRef); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMCommandEnd - - XPLMCommandEnd ends the execution of a given command that was started with - XPLMCommandBegin. - } - PROCEDURE XPLMCommandEnd( - inCommand : XPLMCommandRef); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMCommandOnce - - This executes a given command momentarily, that is, the command begins and - ends immediately. - } - PROCEDURE XPLMCommandOnce( - inCommand : XPLMCommandRef); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMCreateCommand - - XPLMCreateCommand creates a new command for a given string. If the command - already exists, the existing command reference is returned. The - description may appear in user interface contexts, such as the joystick - configuration screen. - } - FUNCTION XPLMCreateCommand( - inName : Pchar; - inDescription : Pchar) : XPLMCommandRef; -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMRegisterCommandHandler - - XPLMRegisterCommandHandler registers a callback to be called when a command - is executed. You provide a callback with a reference pointer. - - If inBefore is true, your command handler callback will be executed before - X-Plane executes the command, and returning 0 from your callback will - disable X-Plane's processing of the command. If inBefore is false, your - callback will run after X-Plane. (You can register a single callback both - before and after a command.) - } - PROCEDURE XPLMRegisterCommandHandler( - inComand : XPLMCommandRef; - inHandler : XPLMCommandCallback_f; - inBefore : integer; - inRefcon : pointer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - - { - XPLMUnregisterCommandHandler - - XPLMUnregisterCommandHandler removes a command callback registered with - XPLMRegisterCommandHandler. - } - PROCEDURE XPLMUnregisterCommandHandler( - inComand : XPLMCommandRef; - inHandler : XPLMCommandCallback_f; - inBefore : integer; - inRefcon : pointer); -{$IFDEF DELPHI} - cdecl; external 'XPLM.DLL'; -{$ELSE} - cdecl; external ''; -{$ENDIF} - -{$ENDIF} IMPLEMENTATION + END. diff --git a/XPSDK/Libraries/Mac/XPLM.framework/XPLM b/XPSDK/Libraries/Mac/XPLM.framework/XPLM index c03cf48cfdd294b169567f086fbd4ca180a0f1c8..99a7a721c0b977b5969e82367b7ef6299fccbdc7 100644 GIT binary patch literal 566176 zcmeEvdwf*I`S%905P`7a5)DcqO4LLU5+#}#7P2G@XJsP@qO_U@MG%xrgk6cnNH9b> z9=D=ZpAwq9c7vJqs1QVbU%fDSh~XPY_a6w_b|Mco`~x~k0mw_&$KG|dgAH$ z>!3gf1v)6uL4ghmbWos!0v#0Spg;!&Iw;UVfes3EP@sbX9Te!GKnDdnD9}NH4hnQo zpo0P(6zHHp2L(DP&_RI?3UpAQg905C=%7Fc1v)6uL4ghmbWos!0v#0Spg;!&Iw;UV zfes3EP@sbX9Te!GKnDdnD9}NH4hnQopo0P(6zHHp2L(DP&_RI?3UpB5|1kwV{Nbxp zIQSofga4K;czWY0jk8!PExlw({TS|Ku@o2I;GA-UjB5Q;j#~nv|IDxzaeR2G0RM`M zJ=04)%CEw$;Ux?*-wjpp7>;d8&Omu|u()`E$9vm?NK{+=60TQpR+{KB9F1w536FK= zpMqCBbNcL(>GNf{HGZoms@#7DE%?W<=~WS@;djThX~ok^r%f;M6nk#Htu21;$qHU+ zyvojSD|jk8@>^UyZQk4kEd*=}ul_a#ufoj1a4Y&nASn;vE%3~rHTMoPzAd~-(-geX zeN=*QI1HvOuEoXPxeI5_y}fwW+!^zbs4cve_b7O`oTDHx+!jU{HeK>v9TF557dUQk zM7;^~Tb>!$CQLr&0~VHl#l>@H7caPX&TaE%7ngYEpAlX-y#?@?Km14jC=!a9eoJR`6!udN%y>On50Ku^5hq$NuGR1#iwgHo`1V@eJ?WX{Xh9 z>I14B^2|I8N5eClCj#+wzH8kcRVKW0v!gS7cD}p)R?n>w@TcLI^030MznO&Lv+)V> zn=@zL+%Uwp{E}zFTcyCtWYPFVMay@^#kVbJkt(OR?-4`gSbkx+#MW}EEj;qEhNrmL z?YeH9v%nRWp?))Eo>{wac$f?F9Q z0KL36M&jK7HxHd7>HQdsz~Dgam@cj{#&RcahY_nfS^VEvEZq?|0T2I1A;9NT`1>Qx zbuza7pH+Y9WLe(Ms|ygvaytD`GOzR%`#*oTa8&Wc**%O@#3e9&w{9R%56flYFyrvY z3u|WLk$D+0D-WFclx5hYdlz`7&l%>Pb=&+~=ifVQOqdJ{hUL$jKYh$R?_4nEta)>z z2z2B0`3n%UV3?y#8h~XvQ}9H}k*yVTwsOXoOrJZ}-9CKv&V*ai3T`$+XNBu1DVaTM znnZrm^!fM9LX)>&NIMB-Ju;%p>%1D>1Lb)a%pW#;)@^*I4IVr+bLj2&!Yk7gqn3IP z#4z7Fy(0C{(PkE;wpcE~BirrM7)v9VDBTPRDRahh*@ z54Ue@g4;K~ujU(@r0KD#j?m)`fQ;f2R944LjvF159XCt@46VX`H;c9{{WsFM^ery^ zBTYZ%(oboIGvSymq3bbQFK0D8UFcZ@PbYf(@Wjxw(XBgIA9L6eEDY7T^}a zp}jiO<7bo;5EGmm>5WaLw@xz(S0f3EOmJ>NU{yF!j{xe>E9M;%H+@5Ji1Y-92CVm@ zB>n}gKVM4S1>P`$g&y zHflg%x!YnJxKsk3ARa-iD8dh0I5Sk##CXXjpnFn<{rlU2f~UAL$w)$+a_r-f!P|X3^A|NSS}{wG{fg)pBjk(a%a=2gW-N>=YC4q| zRV@vS<11<;&Qk$N^Vv6mrkcJ_^gEZt+R*H5jPabK8D&SrSmNNb{+$VOHh2;=V_bHo zzvAAMkY;n%20LZ?Tab^+mLO5zFJ8G!kyf(v4U=5@adNGGTzt+16(^1?xY?y|gy*~k zz4CqN2g|y+LYoRJ4|*>RUg_2kXcZe0w2A{qi0iw6<{6UOMA5f^zh;!+i-1>31 ze#)(XCPo5e{-)SVEaU>o19&G!B3HP*L6Yzv`|UZTk1@7?(S}UF?Be1)l7qcj(`!{N zZBP1HNwYsAQ?_QrzXWP)m76_7PH^nAv~XgS+7+vq@WTNH{( z5fn*C%7i3mW-}9HY5Ga6VsV>O=vaE;=1#IxcS6N7^%&5A1wSp4X4 zwR2GIJd5WFSxOWp*M%{$0TWhS795(CCrh5l651APH;dITRrH?Is@Rm)71vr#PY|gcAsML*d6*-hrZLL ze}~cmyiV+S48VQPx^i&Exh4a+^{)%`&kFQ!LX)OA^ngsa6X^=j^(61L86oP#n}h-) zbTYB|;`@KJWqY`^rp(OtDB}kQo`o_q!<4B(x-(PeSwaD2M5@AO z%ZdL9WlGLKnIV97M#_{($_!?K?NcVf#N`$fm%R3HX-%2Z_9*k0N6$)`(lBMJknYTs zd4NzrnXQ8qW&Uye43xP(%rlx+@lH9!g2gkkJ+`p{pdt<#8FjU^u+49oPtvD5i*27i zM}DI)8ew9T(hf!%G{4o*1*@S$I`oem`f;TS_*s?7AShIU>LS)?pXiCN!D+tu*BH#H z^Q5?ql59uC{V5^a(gPA5`!~a(J2j%%CJcub%}9QZX)E`7E;I6bl1# z4U8~QuVaA2N*9FPI!5{b%105} zO82ZI9B)H@J--LU+h|*_f-4iQ4HR6-6qb;+F9G<a+(s@5UkeBh+ncuL z+89q4moYvr*jd}w1a93-o#k@J#x0JIu}yKk24uut$cJjrupRavvn{qj71Q%EAz7TC0Z$$%<<^_U zxkyxC%-LC>-<1@|Pva)z_55*E{FJgVyPDnty{V>43}D&*^#1&dw2JRzJ-zXp;_WB( z^=c~Z!EWp0;8gQR&rcJJW!d@YT=vydQ2AW@Yj8BZsM^!Vr4Mvf1mfJf{Yk_%ZATVN zESA9UO5Y8YSF1hMS@T^Nqv=o~h22(}in?jlqzL{77V1B`YJcqH%Gu(!jsCaxwu%nf zw4AMOTYe*mfF`K(T&n5bWv-l!wuim}MXvRY_#EX}#Ek+5mA z?Mpr8!ju?13C=G_JyBR0y1yT2ghUwqesJj@inox}t$#1G>dD(~V(8-Sa5O!B2c638 zo;Xe4Ee;Jp0KGGFZ)UTwJuHbC1CjF-5W(c)1Gmrm2YB5!=LV3uliL^H4K+j%ZxYW{ z-W_-o>-HsAsNi0=&;F?Lp2QnWu`m8n1rJ~nb2XX?fC&wg@WjI^xI^=0U50J0cykPI zQo!7wso+Vs@ABR_BY+}HKQl+2Qv4#;oVuo<`;KC(P5RvXdTs+e4!ad-r4x`sIF=$_f6ryykecnv zy&*M^UGjX8+pp=P;|laUG5dKJ!UeCJKxd1~cOQ^h_jmQzO&ffkR{KL|t@=eX1`~{W z%{Lm8iX*m%`pOJ$)WbKTx0VyYG~3H(-yq%fM_)Pr?ix z#cL>jW`fJOKTbwh_<_b4gh36L;U-<)*V2z_>ClJnk3%Ehf3A2b8O$0NetQAq0;1tCnhfqtq@lRPv~Y1!jJJzsj7>431e~0d$ybo+A->fyFcfEK zxy9L@%R$u!V*yy?xVRVvl$SMFJOHsMF4Tu{SF+HG4M{E}_U=|Ae3TWVLG(7U`jv^* zXkbNbFzTVqPG0oLu_>5ww1ZG5?`RVtOj#g8+Ck~@2Tw<-3UOyeX)zOkP#>JH2=(gM z(I~|#lrR@)2c_5uN|;Qvk5Z`ebd=(M4y8lLM3k~kl=_<}O`4Fo7i3EC4l|0=YEO0| zkEEvW$oarl_^~$aU9GmUlh%1`iZ*SBR{L2eFps8h5{CgqT9v{Ez-W_P62aLjmw>Yz z`iIb^Tza!h|1sa!e^~8-PHc?a;U?YD#WFYVWQyD1`fwlf)R@PqmNjE7d+G zG2;F!VtfW5XC+45|Ckv60;sbQV_w= z1!s^g`bV*a$r6ek8j&L^E`4S3kJ)g<+L#OckM_i35v$*J|YHRJm1f}Hs&-mZbsQWw^YyD`2sd*U_ysAgORulKuP zGLpgK*A3R+idv}OnNZE(+=#du%#>|8;Qi) zO13L!zh|`DH#6JiTbSg`S(xBW*3yr8xK)Ol)efGt8+>ZD#du z2HaVM3k@y!Jm?x1J?a7D5vIN$UOc!;d;zskGZsK?IWG3V-<+Q!XBdkzL}4QNWxrJN z9q>yFsbm`3aY3o#ILxI$iM^g{fJmYKt>#+0j!1+X@b7M*j^+|IwPA~Z;V)MO$2Rkc3B0T-)-Cz7wm$$qifsO;dubd4R+D= z543GTSI$1r#bq14i(H#(GUVa}%o9QZ0?>?mWMGrH05t#`_Q~9gOt!~s-8sjks%*=z ztrY|1^u{cEeF9JucR*R9N&rUTDKyQrA~VO_?275)TG?<`xU?bN8^5ax)x!BV8H&s#5wWU(+j?e)ZFZV!%x zo!sr41I6+%LC7Eex>Dj|BQE8xUS+7J#47g+uum?dz5BrS>|B&HD| zfQcsuFt;%et-3L;u<|RwHl#3E>sTgCLF$Q#Os+8tR4MC%#@wLn)uMUK6mLFJ1R zEFN1_*XfOdP@u}w6w8pxj@5^7Z6|@^P?ej>DS@#`5|}I?JjZVV-|bJ%qneSBHZz^TD($Rg~&#H2cpzJ>(0`Fol^B}EKd zNEOSO=G3PTaq49mg}OHzr9Otj#S|n~W{aFDDc;@%Ia7ytdlcl9W_Y`}b4s#3SD{UV z`;dAXQo}GT?m`B0-OxUs5S~YbIjXlT9cJzg?r-4}arZBzsOoCuCsg|Hy#V0O<2r#a zD+Nx?YS2T>KoY#BAqql2+`(1-v4$YmYDLnOz&4Oi@dBPDpYazg7mJD}Y|4-0TgeDm z-9m?!lJ~$BIIc^ckupVmjw+)QDqI#5m)|K|o`40vhNGL*;v9J|p%dFu*r-iGdB|)opx)SCuRQ4E*F*U1zx_A-=pkSK@`t3r$cV>RY zT3n&E-w4)lBkUUsKv1kx0mQMEYy>Eq5h?m(Csq|<$T8g*7F(D&&QmhwCz7x{4 z+(`*u2#yKa@FjVWovERp`|N#?o#Kl8hhQwB{T2RTXDs8vj3>t*4j~Qkur+2j2lqs^ z`8PL4wYlWK6fqlqhm%M97^MA$PXtf+%wT8QD#Fs`(xziCL4uYuWV0_8_lqlrrt+ z`Q)>LR0y^EQil{ugObm_s{oZAhqSEpd9pWAm<^G_EJN~B@E{6#1?jLjAZ|y}urPa? zd7nXq-Vo8HAjUqA5LLW*Lt8GoUJ2k|QUFUSR)r)#%SGM(H&X1Q)?73&8W+h$I}|Qk zA!`&D^;Nk1EEiom9Q0}<#ag$?3ot^VO|FDf0|nY5KAI#u;T`!P*(Xwd9VEqvoJMge zxk&L5NJ{1z00KMKn3C&K=1-H7>oon<WR|HH`0OzX`Fmh|s=+Q5 zi%62lTPG4D$QL6IBR?(Flpvu-De}T>xm79{=4ksqOk4uuO+UuDqtE^YV6y+io>OxNLC*r{_2ocC#Ky7z z2MY9(6n#o6OsQ!F`qUv@nb5~(Xw^t!A<9r>hdTmeM=%VtZymyUwlrq~c2bSipo!6) z;tGtN$poVJTndu0B}kcql%+typGWC%O7zBi_i1b1;W1HZBu|q+|67e@y2+;IB*)%a z)p-ZZHZ>Kjvv-1pt0>TnyH+e3j-lG$rh`gTshsB6KLMpcu&0>WVCHOOE`$zT<}^ma zdRx(WxZ;H7ou_E%?}F6&28S`GubvO9^BC}KejZ%#Ouhyetd~Cl?gY3~;DQp z=Fb!dXLHr11mQe{OC1%VDc*j8{Nbd#!?@91@k8u_!TO}^U^+x+39Qod#>8?VD5a%& zkZ*V(U$#zglrbsWVcetX3r1ks!9NP^YjicnkpV-?s{m9%m|-jN&*qG7hHWucv9OMb z*Y$Xf#_EGioLf!jP$%`!@a7mPxV0sRmH{`VFK+~mK&rc7e5s-KB;v;t#v7#&L4Yal zVM@rcJ2-94wWfd%yj?Rx;yK3WCMPl69U6Rhc=(6nH3c$>AZ63lTt{VUIQK62tY42r zf#}i1ca_3-8l!+O^cM>Z>qO4n9f?&$)uMSwBGz`td!PYy;xW^PLEgB4Mu1}|bRZKn z$^;mzunQ;5lh`b&K$Iw^SOT+6&8MAE(?LKB+7XtC9+Q>bfcbPDNtd(1w)83114S);|1=r$asvW(2_ znVTJNlSUydogmLs%%dlN$h!Ni4R&V5e_kF-?VY(fGenZ**`C0HO2Nm$*vwGoUJwbn z+iv)AOGx|0%FciR%ffxTO;cQ0I*GWUD61VU_t|0XX}NnYH?`a-$&^;e$?_JM@~W{@ zh6FXN{jX3s>rT|j?xP{lmvs>a!M<%uK6bCgrqVFj#mFB5K&aH%OjUHQv)*e1siSQhVtc1H z#y!Yv2wdkHX`+S9{f?c=uy!(mD9Y#{2`CfCy2g<4{tk5v{13)U!W^31QcRnV&)!p| z+y~2#qDnbZVtWL-&Sl&;P@oSroNM$ku?1KRE6`_P|C#moxeDQM{}1-Tj)D}YJ|h*o z3(}ArbB-avX>P_@D)xO$I~6O`H)7@0Y;skxbQ6fG*e28n6&pr$lUcEC*M=)L3cKxC zu_k)@iG{!kT(pXqOrj$xH<7YwaxG)P5L0$vf}jb+Ip zE!?7W%#yFd>i1;;Ok1&Rz9Xth2gnGcJPp|pFL%!#ZBh8bzG!=|YzVXDcU4Uez|d23 zJxi{Plza@k)mUeiygK{LC1Ufoov#YT6ROnu1Z43r%Y0-}_%(7@6-aUm@yoS73=F)zomeu6 zm%C>vs&1^R*vl>HV81^N#WkVHQ{jDCNhUvzaCeE{&-q;^~7M?EA`Dp-x6IiRY+ zR9CnSC&*`r+paNT7A-JwGgqndvb^l}CI{VdfaMtNKqG9t!H&% zkuz9jzn$4@nY|0LXYN(%(fnq`ZLwGqDuqHB&8?9c+)rp=Fxf?f@F5{=EC_S!72*7D zy`)rTo-s7MdEPd##jvZ)*x?z#E(LHKY*#hBYgR0X0Q~oNA($b-_>ZA>wkK+_k)vg@ zKB<*{`+|aE5DGW?h|3A3MZbLtpxBcpq9=(@^Hr~9C-QP1-~B3gA#?X;?j1-WnU|{U zAn5qvj(-A-iwrBTL=;rnZq#(zsUnk%+i^>{~^In?Qt$QfM3fP&+59 zVk+vq!?D2j=8<3)>iGH#$*_MZzhI z^McWB?MD3+2VMk6*^Oo*$rT?nXYD=zCXriMsKsin zCg8sZQv>dp?tp72^@KyV_TMv6L1^D{Hh|gT2F%#51&J|GosYEG=w$&33UU^dc+;`o z1v`k6zkfq^#YIwF$8+%uQYy5ZVplV620!fe)`5a96rg&2SY2rP5y~{1R?%QEAVnp-q##KP9l>ICb7#uNOk_=M|mPeH*bpx0iS>^BY zh?;dEDnxGWku#-4P6VGg3f?iSHZwkh@q>AI3ENE$p;9zZUkDNzxenthBmTfJ00cZR zk6(C6y6|*H@+(vlE@5HO5I~b_Sbd-UIFJA?fpd^mj$gBg3#LiuN+KqJSyyHtiJU)W z2YVvCEE3L;gm2E=uIR|Ms}^w_*@$1Lzo!>MfyY8pvqS$8g|1Wtn8-p`#DW0dj-oCe zim_GxmT3FzFQF=oAcdgQ1~zwegs3B|EkE202|VB8sAUDp0|xvMZu6v5%8PD+mxF3B{A-HpZ4_?o~A^ z(7zAW2dxS|4@&F+5KyGEHxUMaZph5Pfc3}A)%mlqq>G zNkdK+2=D;_gpp(unvm)(VoDH$({=N4W$*fj;^^;Sd8*k<1XrL0w{LpAG?t3*Ku1VYN5zO# zi*4C%giykFu+)k*2b8292jt5a#aX=9VCKrX>J>(QMy_+GryJIWE~(%~z!Wm8x2Lfv z4HL~}cgh({4}`=UzoOqe&E%$P!2TU!9|G)(vid8$vt<5hh~Lck-1fa8}YUl^I_;q?QKB99Lnqlfi6~h z596nmmqT*X$1*m`Yh&yN85`y8%h;D?Y?QYjV^_%7h*zto`JRObom%z4us=t8dywhZ z^q#?A2fCy&Ns;MJ4RnE##S$zu-3eOt)sf^~f{s9!EBJb->1GDHOlNq2>0TJ-il`qp8N1D#q$WBC-6Lr=S4jK#PbfG4R}7lvjfjwJly>g7Up3An~lT85UrB= zx1p<{cb@1B=I=_$`t&tq{xZLuHHs6Es19S4+Q%$~4VGG$VM=VNDBFm0uqNXi6=M*k zZ!pUIrc9~`U16*I2(_-j&PLnP58%^_c5<`I<(*^?I++gU^Q-Ae#2AHMx0*c(r!&og z_nW3ABpr?n45IK9U|TO35-2-~vK)cF%uy1-`@ZZ88>NK*QvBg&O8C_{#^}_)#oVq$ ze0hZJ;;bsry{iJwm)Iy64k+o>A-*bc_Z#T!SRnx(+*WcwKs4PA5~A2^iEwwEqA-ef z5|uuznI|4q&TPgIBMM|?w?H*3IH^t*Ww*#5^WbllNI(JDyCh}kYB2!tDMRl>2cZnT z4$arLwO|+HB*mfs1SHDRfJDK5DR*p3pI`-GEMLQ#pi(=f6k1S_bJq~>oPwN18Qwb_ z6{jL{Cjoqkp=gq^AWh2i`>`8CZamEfb<)IUiG;HnfcydHMt}r$CS@1shcSx}O@ieP zdSqF(D103>x)2og?v!AD0WeB@*(w)-R>3Zj1+=Y~0^JLNZh_nq6m7p#B&Zglf3^^$ zPQ()y2=a@s=>~)y$3MaZ3C~4du&VZlQK{xrvh0`Wt~9MfPovea7aEE~?hq(FjbP=2 zm^g8{Bn@rnFh)9ztBv?3ENRz(5wRH4AQtgxj2tfHW*S+Z(!SIg>V2XNDJyajocK0|~bbl4-0*%iSoNBt)1-isDJi&BF2Do|o~g!4tr<9nYtD z1fFAfPT@HR9i=axfp{*%lZ7V_&p13c;-S2sjb|aA#dsdV^C+Gbc>aLruXtX?^A?`< zcmjAn#IqaEemq~|iF6#UW@7TBj*g!auR^FxS?;J9Wgbx}9a>TL3D~qiKQ2YO$Uqfw zP7-~2J(?L(91AGj@D}Pzq6{CzxvhfzVYRZQ<3z7hU?Z5Evw5pUE>&}%{i{LX^w>{L z`Bec(lwYz4?0l?~@@t0dN7de6Ik}V|JCnBu{N6&p2-k+i@E$XO!xUuDS6&(FE z4O`+VKmv8rux;9#i=wVp*mR9x^EV_QHeHB~G_-sdk_aC>32YuDHg_V49G1J&9B8VC za;!bf-Pk!;!SQ|$*n0sK)p(H^<;Yx!j1nvs#X(fqQul=OH*G>MSRE65HG;T#6-pX! zGEwKiBg5VY3Zsbxe3Te{3zLUrVJGhG=!emzAWnFDNp6g8H5gHCl?TCP1^OHc+8ZxK z1Al-9rr^dp&wCK?b+&cRja)Xet%Kvo30-RPj*7A&7SELq!^_PIV$vjYsO*QWxEV&- z8VrfXWWOUcIfZMHx1x_Q*>y-(Xw2dInDK(*Z_9pY3IXLvQiK;+bC9*+vJS>hP#^l+}0JnpnrvjWL0}d{3ltXtiYUpNN`Ds7efKyb`DdGZ7!q9_MEd9T6%&9HxjQaHT?5x&E-h11L*oSB7gB6R0SiF}*v0!0+%DNeesomiL~m9p%<7?4>@N)j=$8RnRm=W#+@GyJ;6|9Zu=lYY|rhV(+!9>akjE8 zpJLzOZm3+!KrveNs@G0{K?^Vrib=ze(`Qd4ijU(Y3Mq7(+30`_A!SU4I{dvT_)+e; z9tr)lQ2&|@{pAFc*9O8GIh7f4UVNNsk3gbucxSoL?R+o?KMBXOEUpUhQO zIgOa2dj4z2QUBSp{zH)+^=Da+<2VYd!G%>$Er7JXuR#BgTmQFko|M%efn65TEc2i7 zti0dixd?kWW-?d5LgP9v+siCQ;m!iXSs$uL{b@`RpCEmqaTWHHcvqo3?gSGvP@Yt8 zAj8|#y^`<85Fg+n{(#JouMOea`-KlNto_FaRPEPdd~MtC*|1M(xL?VoqxvvVu_r8m zWP;>-tr_*-C+m+X<$7p(7V)(NwLxyN&dbmOd3lJnh-4zLxI71|Ze_KOWn)9EZ$@y0Tc1-6F2He{1Xso9N60;k zQ5-fQAzQtx;$PS+KgaJjc&328o>oupsBK0f+@o_faK^f?QMOuSASUVr`ISW4;L*%{ z&8^=x0ad(>d#YefzY4gijV!I^H>BqqpYc`nN%WwM*)Mds;T@T#<^2{L692b5lP*Oj zwnum_(DMfX@nz+F2f807-S-Y=1drqF7yXGTI0*Z-5#h5}U4X{FnUPUu)@UOq=2uLz zN!BpDwdG{1tu41O0mgoa_+}4Q3%El>x!+f*a44&Irdt=6;}0nqKTzzk$B8@z<7aLB3)%Qlt-zI5 z?ykEXkWlMc#{jS!1~<_i01^LrKh$j~bXu?%S4PjJ#?s3X+6uwvsQ5Z&z7-MPqe%G< zQ))70L(AG&SSy`Sh?7S8hv>T4Iipr~JE5G1W>!2u*YPdQhIFlfQU@Hrz&0St0hh~P2F#3Qa?St+DNNtyz9y3!4kt0|D4O#&JE!TLk|F?K-PxOfDp3bSetlmK0$ z#QO^f9UPfZs@n6giAjAlpIxVj^IKG4pw#mELD~+1A%8u9hF78dXzt*70M5m?zeK$t zADF|@@6aB7_^P!nb`uVuv=XX7n~h(EeMsVttqSKs5@-7(h=aPD=2a);_KD4y<(S~V zM4s8qvz~ci&!qpW?XB|P-ZsB|XRG`L%;SW$4Ebl$|M@|c|9(||9Eb(dH5`$o8>66= zc&A{y-5*gix#}|DV`Rxq{vE^Ie)kAG{EN0)=U-})m*iRqFkw2bLR!deO4gl(qpSi? z1D%ht0ZBYfbin`g4~440<}^vO4RIh%N`y4!7)zr_^BUf_p?n4)gpcmX7PxVeItzF6 zr{wt!9PrWMfLzu;X|^{K|4auAF$D?Cvv6bKrQY$zC(-9tz`8dc2G_oYSm>blG2fZb z!eORVRxf_Im_o_6l$Hzel?-@r6@jzfZKR-&*_H-@i>m?`FIYSEDsKBfoDZtkd?(F)ZMu)6GaPextzKcqA7~deAG}IVn&_efAZEs_(1$ln@sq znYb;ImV4Ozp7Y%~Qxjy`KbdLwG3_KIbL+xwWEAFn;W@|U8ZY#N&A`4Z=vOd-V_u_!AFH1*h=&;YoetYpU zRwIxq<#-o4QwB6xw!W?rg!UfZxQ(*x6H4Kj8Eidw%g}1iJ z^vR)bK+7u>_;z?Jm#Mew0xJ!X)fwvwyBzeojYWx#;T>i<6)VT+{x&}M{f**hi2#D_5>j__8Q z44jp>ZifB^xpe^?#ap)`&slhDtxTUB{0|ysfCAqRZ(Yh%VcxPKnK*huSjM&Gtt-v6 zlD7^ZS-ZUT50(GtcF752b;(1_OVLiAe~Fn-u7Fcxy7TIZbX|$}-yHtxNFY zth~iJ_6{)E1yZ%^iNoSbCBi{}SQ*q@S<4wHcPdJ~=!`oRoAWc&4Ig>pu5F}sSY0bZ zD9R>4-a0eqt@)pF-l(>m7oK6zHF*~sl|%2#D?hyFYuki2ZI2e(gw2Ty`$I*fLfG^g zF-0`*Bg^>}dc&rBxNyrG3N*ZOY>FMAHbE1jew4Rb8rGp)7cjD$yF_0EQq=U*hvtsU zuu6ypu$kCThKt6kFzFXfc(3l-SjJ1=c>geOF$bZz=loslt-^*lSieOL62g+U(q(wT z5#CimNZfc1G8;JNRfxVZc{#6%OVD(8Do{2-;F^vW5DN(+$GOs0`HF?eI+tm=&gHhs zS{W)@1r}P(i~Q0*aaH^X)8G4uhwt2l@lMM@-0xajuxx55cwr%KRe_D~iz7tg8HE-M zd|P4Q;}w?E>)bgfJ+_CtFN@P)5eoS+1@L~e2?Z(xUzHe-JW&R|i3DMkt>U@tb08d6 zi#*0uY@8XrX#uxE3c|>`QabUY;M9x;hGGCx2QS0ysk=(hTP3)R3G$iXr>#hEjx@9W z9$p*vIx53pZxmZEw)1t@U?*jIZH35Nctv428E#uv;-1J-H2md15q-AJk&4hc@1RL6 zHurwt0$eVLTQN5i!ZaAh?t8Ba1Sl695rKJJ3W_dY2iqGqL^BDZaKn$B^{zsgS0DoR zwjUMjT;~xSK9|O{QW(?3tw=)VBMz92dK<)?7O)NLdJ`;TqQPDt25T-&siSbF^)f5& zOJs4IS;lhmox^~>e;w>U*et5vc!!Au84Uxyz2OVIuszRG_QEg;GIe6WXRqUn=0DP) zZ3+wGTGaI6zamCOG_^zDAsB9Nrg#G((g3zkLU z+~xaKA}Yo$8&45c!1xW)BMOZ8`RBl8u^GKkMi;FnM}^-_lkafW$(U2m+jcL*4MlTS z(lS07Z+JYP=581K1?i3V-J-2@#caYQM~S#Y)S2_6CnevuZp28jXba4!8{ogsZgGVI z;x2@7H~y!%4aZkhO;il;YB8!4&?4``crzZjG&`%+<*jw%=m+u@(aIvqTL7Ta52Ti( zrUMXz8zfiTD&GLvAXs3YKMsgh;wwO*-yx$XfJx4AzaTW@$Jz%)d$95DLZ*qCl$ zm#gm$?ko_~WD%t!ZEsZ`Lil0}W)XHv9xm3+2T109l=K3=+y?vyl-yid3fUdQi?_;_ ziBW(YOcEYA{E~&e;vjMP0$YPWHp`SB45$<5B1nQZ!lg}!J7dS9M8@5KIPA42J46c- z^nJ4|cK>B!2gF>Y`$v)O9mJEVe*ssG9pEw9;llfni{o(JVuD9;NVAyF47?~$$DL8X zZn-AYHF%&_d$M!XRg$(>cbL~?E-Z5S#-oO3z9AEh46fWSzK$iq7Qt}REaF%arD?^O zgd~`8#ALqYvPYhkIB>gww8-+^3!5crBvw7-N)FN`Asxl{eR#?4F!i}8J1B272!A=@ zMOmr;>dOhsWPunv&+z4hSb#kJ%L%c_B}Li<)c6Q$jO`sKh+X7@8zn^cndyp}zKHmC znZAgQ39*P~*vadyezLvUbrpstXT4sy#oK2@%t9)cmkdF$Z1VPK*4*Wkxia4P3Rd5Xb^w@VQHR>gSxFmbRKz@|sQ z5*C~7rvM6qa4(VzVf&#=U`WPr9*)0834QdqdU3!^+h5+?f!!fr8z3qWDz!(~i%U2i^EX0d>;TL~W zFGkze^+k4regkA4eBA6GQ?Me~^*)k&8OoIN9^P%@#E#`=Je3urpsRm*}cIX&Dpzt5=c-UzH z?(ri!%};|6jk(6tJBX`_u`|MxgaQ)Ev#;^m!r8zxb(@f}^ouDCRdV>M91LWH@ZHiBVX+;yFA#MSJT&!S|v zj*GnH5`*l2>~2P`sn{%v6L-iY$AuMcls*cmrC7bg?VZQPwRnYVfZ})pD5e2E?1IMb zJ9gH+@0q$}*i@c@w5HOKE|JNiVHT$Hd!=o7zqnii+e9|$4=;f{Yyt@n{6k<^5!eCruD}!c-oOya_Fl2O^PES|Ycq$fD5HsV2ZRkz_MllKnLjS<({u zcqFp4C9*6WSzZp_X^Ed6iC@+#zAzHMyj6TwBz|R7eB1lk=WO7YtR!tuySx4RmUogX z#he~;5`H0Aas@Tu!PaF`5sv?(48=cA2cHSxeznD)z>nekO2@u{Fm-j0 zp41hZnrcm%bXxnohBs|4kmOk`bddE)q|geym&03r_LO~cs@;DJpUF` zU?-6LgDl?Xsy&5^=W);c=xqus+fmi;|i{s&jpfh z{qhmSRkzydgm0U_AHdapIM|NSa?lC;)R0Q_##=GCb3~fUdoz*`{Qv-l^(#93_?0{7 zN_pQbE`MwA9u5AAk(li9GPqiPfvA@|=O{L%>U|{rDrym5hf@iL^+gi`*U49KTZ93z ze18J&RYAQu1~jfmWNvZ=(h)%Nui=S^Dyc->fDL=eHzOL~3b=(1ru3J|eY+PsCB)7J zIVEvkT+i7f6{0X9^cboHzTN<#zu((G;YPvE}yz~(?>LdL1A`TdH;DRunO~$Ds@4E*pD=rlUCt72;w^5 z@J4z0E%sj#NmRp6!yYgWiM~i^plbNYo#ca@k8PDn=o?VhR`W8PL<~ye3FtJcarSu+ z^9@xiY%!GcN3m@!%BpDnX%8P}rgtGeXcZ3tXIu9c`v@{CLrt|P9{9PrFMg)+#a&U? zibf8$t33i&%W|Xl2s|1jy%Njm0HNVXK;;YGLGY64A6sL}x3K1O1?)!Rw}?fTnZkUh zX+BEC-hf(QE5$G1@DFl%G-G`B4|(;4FEREmd>OCl?*!lKFG3I;Jm;w^XfcX1DDT97 z06`j!8b$Uoiel?e5KEBcU&BF{+z)3)z`7M0*)_1EROI%yRhFalC5vKLL2!5%ibFR@ zT&~zfCoxkx@mEP_Z6l;RCd<26IUEx~q?o-NrC=h0RdH;@zT7Kz(2KO8s6qkNhE z%I&r%{Jy@H(7Q!VBQ}QNWMc1)g7_hJ*(jg?BjuA^ibmmwRZ!R2O>{tXXQMjfQW3J* z9-7e!vHCISF~0bbptv?Ic8L~K7iz>k6O~)Ay+u5U;RI|d1DT;F9wrlmeiI5c4Q5u~ z+Il3ygyc^bWAezsYTb0u4&fwT`-1>|@l zlIBi{?H(}@iNaM~iMO($2Kr8TDq$KJX#O;>_;br<-!BkhkaL04EqjG3;S-lJ?z^BZc$JwA%5vY zGu(*|q*YWWbp{==TT1D?h@Z%KTpELTiqOuOEVa>xDdN$l>Vtt&owFu>&P<>HH&P`J z1PE~*K8gV?4#)BgYx6<%8i%xPl?`k-NK$}^QWw_~53wBQryP>4ST@!!0^+yHEDB#6 z%$ie=jK1e6YNQC~^#V@45wd^Jn|Q%8hP#1W!fS`Q#_z3K56Lzx> z+~0cxKd2NLsS7JAM@wZtGy& zhhcU(?L!lZAn(&ZCB}xmUx)$l!hClwmKtK3-;MEfbKxrjF5^aic3|6o&|b8s@notN z`T$ko9y^c$R~O(nY{=%vbC-#3fE4vnxs%Kz&C&a`TpTT`^Z+esB%TJ|msMiEYO!4= zY`xm1ZwTfDt?1P9SW1vb{970H95O`}_8Y>W0lI5z*!M6Vjnh}U0deBNmLXUk4-4Cw z^MU+-`GwvTz@&ZbOm^mH@&0r>^Rxd@{HK%vxfmO{=M0O1FXJ^BMI%%B%9e42{ELbj zrJ}0D2t`NmlXn@Ir%KGZ9DMoal zVuB1VQ^A$OAqy<4SBJT~#dH0q;zY<>L{Ma(o-#q!Kfuir`kvR6M`idJwhxs76F`;W zQ<)&k7tZjvRvA{w49(7Zg+Qb5)8BUP{LVwoYVOuUdw~y%}!K-ajS)| zB@Xq#EFWLWzL#;~F9Jq@PeUwOA_nf+?t7B+P&vz6a%d$xBsXRkp+)wK8jKi95L7`B ztj0^W+2#)v;4O%NAgH49+D(qYMS8R#Sc$Yl-e+GtD*U*B0=QP8)mEV`{h~iIw3RVD ze3I*|vMv1xeGWZ;ED93mR zLGg`gnc2Vqjc?h+Vz>lug>|&q@N5I7 zAYY0MBy6rE`C>3@HP*rq77`c8ND?!~q^*26h3`VIfHoEHVQnnv&YiQ$R#^!h0`1|a zB=jU=M!b)7sMrw82stJ8ho{6SdcRl)0O&kb;%cAS%#@WY#a|e|WFz@8YM@3+zp&#~ z&?>x_q3O88AXtn&2XMv*dj`S08-m06bH4PSR+;ONxw%qSrll4+ER3U+Ip3}mmokQE zRXx%QEgR#3_RBBR4T#543C?{9sb8Vf$YPW8&Lu0cAj;=ZI3i)VZo z)7vq3#j8K!)g}cYCUiqm31+juK@?VvpIq9H#Tm|nMxoHHb%@pDZzLj>J;70#%}w*+ zg!4A>YXLz^811K-Ix!8YN&K{zT1FUk&&iTQJX!&JX{KMd&Ou@gmYlEv)3F679i2e0 zOhE~@^vVP{ns043)!trXC*aA$lYu7%PlByiR~!Kih4e?OfUvFCL#yDx0^t0Va95Bu z^+)~cRUKdHE2^dQ5O~I-KlFrrHFhdsmEgHo)5l_toAq0)4~geqB&f9$*js#A%NX^r ziYix82BQ|rsLGW@kVa?=?%b1&oS04$7+6<-e5S1M1Z)`7Qa0tKVUNJt45SyiR+a#P zi}j*m5>D0xz?4kgM~3azWHGe9rlNF&I#^h4%WiFg0ba8?t5nbG1g6?H&Hp-*2Al^Ce`HQyV| z1}R&Mn5ex=Pcei397Pl4Z8_xaGTTzzf(mhe@pFIzZE&V6k4H^UiSbDOFr*NUPL>~# zLkGv_FGLY*&b%Bw7*-S)LQ%XaJSae2KP+}3 z5h^2x7+=<~S~EJDFNPiiNHhM5Q7wuN>g6H+(*z07Bwh4L|HsmPAKFWD4FNaR8d zU?(=#QnrScCtzBFveu!NoaEk#iRx*h>wds%u4L7f#HRcgvk-~eqvlKZ%KaPl;zmSa zY)X=ZtNchZ8NN^oQ8wWc)x4PT;Dg8L9cuK5Bz-vq zJDLKg!qEmGzVG6m8;LdzC87>prr_Z@I1cl9jQ2{m1{`1vZ{I|qXn>7z7&Dlr^5sRExs z8KNtK&;U%8(j5KqDP(Lb+lJH1$Hk$)0$a`pIQ9?5ob5Dn|9}+XS~{10Wm5bg^I=*b z=~Ed5#hWY1+p3-N*iN-b(ph}nC3*Hp$9-KrU z$JDF&Q^X&L8_ZM4{i^JSJG}TQBl($Xs;c#3D}rHFwJkaRA@jE($8!p3q>`nq z=u9*2g(~9nBczN}wFNB5M`?;-m7=;-6S2>-cd z1jLUqyJCoPeE0ou2FL#h-Bhb>vd-GfrqSa^AR6N=*rg6;9t_#pc+&7B;lZb*#-6|< zOr3xY4V{3x3|9rvVKDxeBcwkHiNaT_`AT0=1&8DIcu!#Leehd0jV(b{?`YJFCuI%w zn>4q+aDrQ(Hw7xfRHU4#8E;7X{pL?dUYQN_fp#UMnk}I6Nm6-A0`8BrEqxmhv2>la zjs*U+rYnLbcNViXv5JW;h_-^J@AN|``$?0IG>&!XyCKr#Ei04Rm-)dUe_sfH zq##c$zF?U^TlM3N_t{S|&4chaJ)km8Vube$nTk}V`_&LG21uFxp=%!Hs0gOTI z)u1-!T4LGrEM@Hp+Sp72_*B#?M2T6be#KgHAV96Hf@@ofd%1wH^%|;VgRO(<)Cz0C ztP^ZeN9aQs1aD+yZt_iVJm(k4MQ~`w$)gZ<8xl;@zb%B4n97vtJ1}rTPw&+75%!U` z$~EBr$fRr(SIf8kBv-yiH$|^j@*C`ei;<9&Z!8Cfnl9TI>z1~Mc&!eWCNXmWLALx+ zbw!g044GP91%~DER|znvO-DZw zu%-eU|J>L@owVexqWM^o>ZbN;md;=oToqc@y7X60(1XkIbA0mFZU-w}P z;+6y?wxK}N0}T4?GnjmtOdb|REfS(cfgHy)x6>ckkRnk{{yiXb_i_0Wm$yN_ouQN+)!SX}{vD+`cIG=7Z*TGQb^I6uD^WkqL6iXl! zkBc(K`|K8`xm)_zlK;hY_*FIV_HYf}PC`s`CFPppu{bv9#^)Hx5Taioq?>%?9dbPl|&5uL958=hY_kf z)VnK!U2sQIC!Fe_KBxE?yTR7VUT_f;_kmS~iXh}jKwLvmOxdO`C!TGmE(c^}o4Rb3 zk!|YoHX=#u)t~C(>0Gn7Ma!o)}Bk5Ht>7{UR z90p%sbf=%7#BkYO-N;i%^#st@wPX|dlI?dgi9nBg55X`8DcX$12$D_OVI>yIro($G zrUl%F^X_6LjBmjmb;D`ezkU`dGmKWYXhb+@Wkm zNAFhdrE8Q;Xv<#ZUR$ii&v@ec1^icag!}=NUv4O!b)XfBP6+c2)i;sO=Dyr z7VQH!Y=8>efS$rjJuww%kRwx{HdzLZWyIepp(Wl-2iw?kws|h+N1N)65i3PH2S47N z6JH=xS+iuS_qFtQwb~y#X*qiqHozL|@jz$z&rSl^qYX}MfX}rq!g94gke_yGq4%-D zT$?sh%lUy@$2P@k*p_-Ym<`8sB}OGF`@owk&LyDarwI@H38WLhF#`S9^kFmEUomdK z0>9MO$$Pr}RRq;4oo>H+d)SYCnvrmi{H6(_rS|AY>SrfjuIuT`+AjQMI$ zrD(G@5rm_;z!Hb;=!L%FFkEbkbA>hq-zhXamZae8q!17+koAnuf>SMfQu_P&E)THO zS{lsu>QQX^meUH&=G;YOb3DCx5HXDDQSYH(C;f<`wPC#)(4>k_UWmtWsotQd@lQy? z8SpHir>N3jIvV9~1o^>EZ_r79zny|}Hr+Ewo8@P9nhRo3n*rF^g56Izujdb*2XGp} z@w)s;^jOjBVv@|IS^4cSQI0)4Y>%0mUJC}Ah@#LW`E=6x%?xTp(G$yhG|oG0OH_7` zc6@K9-}N>^vU%P5yQ;PDHG6l=R@qwbHZpC_Nwij1wpLg3+b`VC*+o0P-=U8@y-j+! zWBlP-Y{T6uXp;9$foUWgA3~4YYg_hP0yg5Sw$ZUZMkl>itNp$;zT434?zxM5Tp=zm z(`J1@e3}d5*z%fhI1~hYiXJTw(s<&MYFH29TLHNZ{DuQ=4&g>}Ww+$Yj^xs0E(-h` zkTLq>DLl%??e_fGfq1q6FE>CFUiK7FaOj@^`2+P5`JHsyL*AY9**$l0gW%<^SzCS{ zbIzpd0X>ZTeSq7N@n?`6gy|jHWd)r0Xb(R{!M{;`hO3~u)d7U!0c*(`=tUm?rh*d zX(?$meT~E{N{*Z|lBY7O&)(%#_RiAV(RI2oX0Y`*NPF7E3Pb0|_l!dN`d855p11=^ zp#Lysq_3$SIs!d3fF2rP54|rgNz7zgeAI#YZh>F+I~8|6mTNe`H5DLi$_s$KpI~#X z^Wb@+K_9dNY#@wz}zH1XoI(JW9SdGGg+`pkd8az%FVJ*dR8SVeP4a zg{U~64H&)_!NokR4OsM(JY|u%Q|j9B@6kCEf86h$b)*qlMwhS2B)?lcvr&(MPs3~m z{T6#A;dGrLYgGm~qc<(hkjbvCxG$sB;z_42h8brvW(dIbmrN46A)_>`gZ&N>di$P}EzM+x#OBRF8QM}a$|B{lGuNbXwoF!p=^MQoHldoYIya8Lm_=GRPH+0&EfwAl@nJ94; z99Me1C(~7XqLWlqT{h5JL#MAHflY&YoX0K#|A=J3vI7%Dy;OY@0KFAuFyCCLdRP%w6^HZDtxVY zm8MT#Z4M%^xZKh$g{RkX+k(ESc|(lH>M}gt(zKji-Wy%M5&wt0HxG}h$Qros?Ik23 z&|x(yXi(5Z5d((lbzyAxf*q4xAuAGU)2uxy}oF*$fRF2ULfDjS5^@3nor*jMhtv4j9VMP z1U?WhTm$RthH|FJyF1TwPc18}-887k`-W#ZhT7uS-q^#IQhj3*ZWTCggJ~E3y0Mio zUN>uRlhQuSJ5Z}D(JjwYSPgBp@Gfeb!pN3Io%wq*$P)1!-fG@xcN;XVjubK#3}z}g zS7C~M z`-@Irqp0<0kDqxJOOXx)pyX6}1-eCfaWw+LtT(@mNK?ku(T(d_lsBBLpfPq7YVx^2;+isi@M z2XJuM^2-TWa=%C)L_6`T9BwzWRyxvswY)5;%l~3bT4A)k8Sw7$+#D6;BLtpgV=X3F zvoC1WSaM?MU-X=4xR*-Wu)7@v#!_3NWhNuE$~+b5!|n_C$~fmBTbI3Poq*$Gd0Bj( zYTsj1W=;otkXOE-TVvdEcG3M+YKo}aRIRGN-_T<7`opjYeNj1c@4kgnTS74qxzNhC zk!&Iyjv(E{qtdZMaL`J3AL$xTk>)#Vl0d@_-cD76E3c-Fk}nDHrRDKl(cH*RoQ$Y? zvjCukz&}}Oji?%T<0cjg_Gn->UAi|tNg?hTmJrrPk6GicArYIdhfqN+YvK|38vYg; zASX2OkWx9&xv&TG|KA=aOJu+Y>eX(ryo}ePtCF26mCv@RH+Dr=$?X#YM*p2`?8v3G ze-xFNnAs8T5mS3&;M51rbaoxg zl?T;8{&GFpmBP#nrLhSrZB#;p8L|VNRa(8i}BWg~!;o3gj?gL6NiZ&S^21@qq29^HGy%i%X z2WM(5u-Uj{?(gwkG+H6|%-}cOJ)Y#@MVqiL#)@uOv~wm`D>D)e_w7Bq7vgT$P>9H_s5OWwk}`E zEBgZuZno62za3zD>+G9S<1eX`!hQN{;bk}7MW~r`%AIjXM8%LBg;++0&lx0mf8CHV zh2f%{JFNU6BZOm##$*oJ{BQ`XZxDn!pjq9fjxzqS@NDkRYTpNjDMOHmb8QRrGY z`4+7WnOxye8T~OdKI~o&+#EZTr5lrjwB$_HpmyCqPkqE(4-? zZ5$qMH=aUlfx&GRd!R~M*`nB!V#S7+Ip_<;Zc;(nlFeeEUBoX7tUn#KGJeBOwroyPeRA#qJAb(?f)Hvyc%tl3 zcBM4@%C%zB^5wHi*&AW5%sWu1F0#5_YtIiwZVnyq?bz^s1| z6Ye6G=aQq70$UxBbf`KHnzQXfV&@|}qS`UbiG+y{lx#4oh8GFouZP1+c_B>ZrQuX-X zG_9IT&07|rQnUTdw*4M+DwP|BazUQh%54WM95!DW2!~b`dH>^C#ul$gFY@grzA+X| zJYIe#zF25=RUTJrYjPsHD6$xr9>cR_WDq$#BaaKZp{2qq4sB$4vbb5t(_wf8!9!evp8{wM>8ra(3h3~+U^Ax=?fSy@3n8p!@ek)`LU*H~kF zA}_0sh*gqIZn^}#eA{q_gu_@2TPPl3S}4Yo3ueS%I0@iKn07D6Fq{PHJj?c2=mBLv zhykKaUpE3H^z&69vVe}Q5rhhwrl{!9R~%vYR6eWJPD~zD3Vvc$3Vx(Y@YA}&#^3uP zzZgD7ke@;uF16l*l4TH((2jBgXaXG5hhl|wJgbDc@W^t;&+C zm{l2{wED1`!OUIiB}lIFKa2nK_`jO}FYw=!B|Z zyfRxzyDgTQe&bDaAy(I*Uo;D;l~c=5n=s&i!4Jfb??x#{L5H<2N?ahvWQN#;pH(C`8olnv^9L3f#yBoLsx#$kMb2K?lhPxw7QqRZIUkJ^ z0a4+kO&lePdkB%@i)9z`!g?XF$#x;@jzL)#UdX1|zkK?qDu%tGU8 zVy0hYLTt&y=$K|G6eBrciWUPVm~YQiQh>}j$#hqo_FiwXa&8p^o*~ z%Z>-pazQ@!&2H?M@HG9dnC5t}=qy2g%;T&;^h z-p(7ZkHGIxgOOjzt*V8TdH_@(ko@!rmS1!P3_xwQJnRe4!f*`I^9#vneQjj;5_~3YG#mECCA_#d!zK6?JIJMFOKUA-um$O+ zfx<^la5Q4QWI3x8`K)0>xvhd$1bFFKrCxDg{iITB28;ny3873cQm@>TUQ)WzgFSe` zweKTyty{i9!PYTB_b8Rpeg9vjd)#O73kP^^O7etd{q|v6ek9D61Ks_$amcX@&c&Bdh@Ig zWh$>lak77p;$R#&?tb|194@#}I9_~CKqDMPLSd__foQGP@hewhb@mG;z3pXg*>XR3LDUtefV(fOqlPPI z&1__2(yG%BFAoH#=9ARUbgu@&&~)z4%p?}r+Y}S=Qxj4a^Ib9e zQCW)=W|{RI{K+#4bEtpL<764sUCz=90iCH7&qnu&{BGDRrG~qVk|g2;@gvIzU4WBY zia>Hb%N3thD=Lux3tkZ4INA%MLFsWXh&xIJOb}vuL5xBh2S-PGe#zvE7sMGoV{Q;R z-NYe}*g20p5TWP;M=-g6rSVY8LxKat{jj`P9VW{GkGYh7v^tZ{oJ}gTEnm%=wC2vV zy=zko%4>H(N(#3tk{3pg+{KWghFCIo4GghG5;+g#Kf_EUBorPLT{RD^%X!Z{qfL=9 zH`yO^+bif&)`rNr8Kz&3`xqlKeUSyCl+N&-$-<@DbQY8}z4^u)Z-@YLC7o~fARQBl zki&ksd6u;;)F2Mn6zZGflwJ^ES3gGm?1#w9Tg`4XW}P@Fsm3j0U1-0`)OewK$>#!f zKAtJdm;JUFvPPZ$^#XwWu`^#w#!P&{_ucI68%oZ@T#jodt66FjpXK)+nrmVqnqV}d z)S8f1Cu#?Oo#k~5N0M_S@`l3j;v946RuJK>4NVaVVwzB0#9hoR4?365Q;z1!m{Nyu zQJ+vVJ|tx*rTC4-8Rq>nrE3qGckxE1NQN{1g^uuNAE1*&+TL&Wm_-sD{?^@)E^5~N zwv=eZ%<(z7_AuP#a@CdXu8^1aHO2)dHmHnWq06^~_BT8y5PDzpEQ8Opzc?Z%*e>AB z9ZYJ^^81Kl%1$o|m*R5qC(p8#L~y|Er5HkCe4^EioMR00797kBT|!&uBc{++fA|8q zs(saJ)ygHDs-Bo}VWjs#bg2iCud;mE-v&Kuow3~v&|ay>uYX)*l(LPnwYiE$Cu<)6 z6bR_wzU=Q|>P~zqybr`218OPS#4&(h%*wqvKKrJ+%kU_FS$gnvh%ys537Ow|N}c>4 zg*(J0Bjw=$8E8~5O>SrptiG3~S$|3XGrLN4{ug4c#WVo1dl*KRO`co!32q`6rnm4j z-{1Pf@vWTdJjke7FMRpo6lou;)bJ=k@MW^bj6vYT_kgq=FV1|gtO5}6;(V?@d?BM9 zi}n5N(~7*r_+Q+~>^4J6QeP>du&S~BG@oZytvu?cd1fHLgsQ&H^DIGnzry#@q6D=3Sm=)Ca^P1tTty{kDuZ-}5nq(Nk(i`J7Raw2C}$aC2rTn`WHquiot( z73o}ojdB&1EZ(3u({oofTU?d37%+VwYHT+3QrjVPCwQ@0nDLO%SG$$+f?IVG76v_I zX)P?Qp@M#q_yv&S*ME_u{9}uHe{@wvGb4kEC6kbuWNx~zB_pd~-SuA>*_|jy%<-f< z1|!?W#C$A9rbMJm#tKpXXm%qn!hunPRM(Z|4%R3^VP{f}Z;KCWTpOJt@Wju{$ zwcUxTNidMXJ&l^^9WuJ;xcek4!&H`+k-^oNQ?s(I$x@8Nk`hd_gx2Z@i;RUml`6*a zLBv7NTbg%s8@9r`V#7!{pV%=lahNmkC26?DAM`pPg83iB;|SzoOc%Qf;`P zIwO8Va17<%mK9HIQE_v756TIdSbLie{r2{DYep*Pu5(|xxdoa{+nc8_%M5e`CXOUW z5rWe!BO9tKk9|6fdM0z!nyP?Imm#lBreKm_rvxk%=hB0g&%DHc% z+DjCR$SbCipVh#S^P|y3cU41M`y*s2G(jqPXF@}7YFNA8gpt)kW!QAWma)`n^_yksR z(JEv|cv1D-eah_djnHe27h~Ayt6ZF=1@VM)LN_hQrS>^&@FVLUG&^vFQEl*x;nx>y z#QY&`H)p}J#3TV*$oUAYergOJpBxp9Ouea-qktt<+*8AKbN8_x~%#Mn*GD!zY>!AwY%B z^o1`696t#7&~E11yWkSfqKuns>-5g>0 zJ?G5ujX9iG$T0I@Rv`U&I%0xa3Awh3tq4;1I)-C6nOkHLeAKpc78#zo6NEEkFk2#g zousmNKbaS6QuL+48!&EJ{YRODlf3hCLYG^d3bX&^tqCsZyIGc!gOSY^9!XLJye=F)TTa%+MKj|- z;R`yxGw?DK2+w%6%GweE+}gqygiab{?}_FVV%#L?mLsiVMaOC&?%3U|pKPyUVg?v@ z6Coo6&T$5XU@r6(i(#m0r@TP%og`3BFLs$r3Cg(KH_6sl#VjyZq4qJqA(rabNxq-4 z!1!5x(kZ_6*Ty77^hpI~ppkyuUH zb(O~BA8iqTS-g<7&4mn$M+&jnC7czHtZI(Th)32nM>^w?_05rA|3Nhtz_tgAgkcQ)$s26jsd zrbY6iFlVEB$=7{1*SK?mhMf)f7pr4 z#@&WoRwA(;Hq9i!g<#pvglXC?>s1-n=P$1oD0Z34dB^p!E&P!FOBL{&?z>t|VX`0g zbACuWQ{>TpNIR43zsM8r?e{2L(3hgSu<7hoD-uGHEf||n)Y3zQU=-Yx53@mt89|%6HI1EzgaJ7y+aS40M>>A>?}ZbDwt@By8pLOYZWSYRy4C8EOE7YZ z_ZS>A;geTB(OVx}Ws{v43)uHQj8{DGI}!L7Y~*N6?vr-|xe_X5cj{_t!tgm*1ao=` zHIq0hdk%??jV8~sJOQJST=3^`mp{^E-=Hpk;^kR(grouElz?$#vT+4H`U+c+T^8`E zA&pG%w}lJkg|nuYWL_GS$u+7ccpwCut$&*Zubcrr%v)IdUiA^ z-zB+ir)SsvP6m?Y^z25dHi8+i+{OqITtzx_g$5!ebiM4zbo4@1BQ7&p92d1NZ>-}B; zW&gvLjl&gV03qg35C;F^P>RLMIr1X&H8VEoxr_SDoivOFvW!pZW9y&{_rBXPJavE0 zlVn{f(tOsf8nj)95 z&c@SbKowp&C0_MyXOUv#pzaIEzVJPqE-B0m`r{a)gSl*MNeQ-ZqK~UN{i2H0#LR6$ za+FOQ#um|vSSpJd>I=HF2S_&b;_G&>420A|w!Q*GXR4?1&z6`d^M& z!l3)8^-tL;u5)~W2p8A3y#Gnq$=hft#W2J+3fX^&l;(a@zzny0NnUoLvc=-vHs=Kx z{FN+;&_#yo%%@2nc3&HTunt9ogA2S(i_fcZ|A}lOo{mtZP*8;>p4KVxblf%(PseS> zgN$5sgkU<0bjJrN6C=Jj$gjvBXVZ=3fY?8>^UlHGla5z%k@=@H6m}QdS*=T@mu`|W>VK$R-R{j|KYYb+&A zjKV}oga7L}IjE-nE7O`Va}BkxIP54pnTRHF;DNc%!X_>tWo{2Pv0d@OgoZ_Ql2xs7 z2=91C?rGGGh;>>;?i5vV_sZN<1y1L1yCedYhuKN8PhUh^7~^;MvgQm_R~x7YlK&Sk_8+n2i_Ff* z^Ug~TorBXAIkuk3PNEqQzm=C}h>1SNd|2$uT814Aw%oA2@3Ke=F}5_m=r@`g*L!md z1-hgO4Pv5Yfz7#e;#eg%|HbKuHOY}*IB9XI0{Z7qTEx^T!&N$^PRXVl>A^oOkyn@7 zfMIBd%)b!H@R=^zT4+-Q_C%=J$T}eTYDZ*HA$5$- z6!{O0icKe}Vxg0$Q5kC9M&ZpGl_jk-DszsdQR&K%O{kZRz?QNc7S+kVGy4ZG60rwe zVhcui&}0!wbNaKdfE;~wvM>7^JaR40M5^^4w$X2p zwpp(O8)BC?wzr#XR*jYh?=r9Et#ATA02T3;`)K*8zUnWW?555URNt*Ka1hLJ2J|Me zMO6!MDdV)}G8C(J_cCHCqcaJ?ygI8_?xKA{jpD=!%DS-whj*$*#|=WQOm(4q}?`dO!E%H}HXEKJ_AFh?7n zL&QKLhVq77hx^RzXJuP$_!#PWit0qR93=(f8A)mv=2o5@9-AH>H8c>;_kn@vs(~!Q zFnI4y6BbA!OC)6>rZ9OIZ>1+|Qi!p7T(HU(+Y$4XWKz}Ur;|vuwO~=6EZ*d#TzXA@ zvV2u!=r>NHHYuYaLZ(F1C@RFFIt0uoQHYB@L z0Rd7=?<#GhImFH@eb$@wq!h>%l}u>JwA046I6)-rDfbR`hs=9b+mt`3E1@L0bdUpX zC$c06ecR{{mycn!idGMtQmV7|BJ3#xt{_`B+srFTE8ss85Tw_d;Y@pMSuH#cO#~LHZLm^bUNxUH zU%4-$%Z31Jcx_nABx0tKgwN3`DA*U~OqDuM<~g~7IurMM6yB{;tM5)Ib%~T3l8una zfZ0;2=)TQ$B%##Em}uY4oRS^=8ison3p#@byyvxVMsg`C6T8YpP9z6%E&HQBs$m;V z;~!`S^0T;XIx}FDGf(Aa3hr$Q_w!zsM+*R z48oW~CPSoyO(GrCiFELWNC(XBMOzDv+C1ZpJmWo^*wv7r?|l?`*cN@m6+^p7m4k166%MpLE2EyBzg%CMDs#BYnok8crQ6_3BBMf{`j`035@5Nag%3%;29 zI1?aXpJF*odk@XFFcj9k=BRiRIDP#DR5S~8`BJ`D4$u@LKaTR?;f z3`o0Y(wwTILYGm_QYohlij>Ob%6nl6;c_TAYF0iYeg(F*;tDy! z2H35{qbT3)4ttZL&XuCBm!g{G#25p(LXyG&9`;E;)S4^1S)!0V{#lZ@8voajj`7dS z9{(gcdi*Dh_IK|{C_|0*TPCS8Zjv(8Xs;v5uNm!+$wD>(sY>QfH*xu?V$GDO@~9KKa=aPNi_7oCqn6I&ZT;*=i>w3>isJ7D)~ffA02MB_SO>;T5IjX zTM9GtLl%fqoha!P*$2;7I4*|ZzBKngEiD|}Qxo0kD63)O<{~;a3#`_g-|^i-b*r85 z9r6JHPPYMQ+Y$ir*c!>bx&r#WR^)jAI1d1DPBD@=HftLZN(;Q@W8}yn1?@CXIwWT3 zuAUT%X(I#L9tYbgr>m3`QtN`;QzYEUCLB>KQf7PNC@d?)#;q!>yB5#?CHcRmve;gJ z!-?c=B}<3~{aCWZC9Y%15;>%fu?9t1V|)gv`YY>sIgYYOronsE5AKT!%Z7EPQpGm{ zl)n;fA7l0g(Z2UKYKKB2OZHwW60t zRQm4kp`JFAt>TYCFC8RRj9w0hp_h+%(BGtOO)uT;w2EHdB-t_P<$f#wf1{TO$$pVu zoYV%rbOCRFkUEYvMS8Jj(cvO1vBnTa*OAfKa-ERH zS6cx4Wol@r268KE_+Oz&XPzyp3mk}0ci%{FDzUYmIwcZ)#lo1j#@^bLnQyNz!sx8k zWT7R8MtsI>XuQ_!r+#lN2+tm9dLChJ@YaOnrt-qQJ znZ)8XF$2Q)uAzeFWywjjCypAWV2R`|pg8kfz!pZ6>GO`y2_*%*vxf$8-l;WmO;zsY zQlU{}qJ(C==Z@s3TEem-vDUyAZ4OwWhH1hIZwFd(7{q71ED7%nlKhN>2PxR==(pNP zuA|q{lT(g0_ldU!X_5uQ)3+qRpd`d%HXeZC8i7Gch!2zG*GPzYRHsm9so9iOu55p! zr1-$@A*8h*L5O!A82nB~CKw#71c0;tD7zruDLJ8@0q=sLp_6RU42qR*gq0O)2^3^Y z7H?75UNTxe789`=y2HCwuO;ljX9giMGxhYB? zhvf|8L38}0vQ${hKK(8t3&PhAH2<6{2>+84j|lYmz*Dws~$|NjaX&Hh=3mV^mMiW$*Cr@)PZ%$U0A- zEoHN8fNEg}0#NW`1x&~P3e0-J?au&nKi_O%LLfvMY*0RUvpUDKe3Rn6xufQQ;gurp zMci+PxSVmI7Id2*tz{#PeA0J`wrPrIAUXHoo7yl!h+S)*P08wRUw&1Y?iSxV@lDwK z#6g1FS~DLjE__HdYj-VCQ5|KpgxcqU!VKDrOIrYah&Tk$fpGzJwS2c$-Xef5=X(NU z*uYntFPhyYV1_ZL$13ZYCp56`dtZ^ zYfa?nxqkF*fcoX{WTxI|x$K>Xl8Xj~(t};{!Ua8(v6sOD(uKuga>M)JUq%)rS?ABL z;rOz@I?COuqtUwANBhK9qxonbhtAdgs;_ef<3qpq18!B_hQ!9n>iS?W@sfYbqmn*$ zvuf}2MU}a!86PMQAe7NaplDwGurOFi>uN?>8u zTmlEwC~`uw-zZ8)Fu-3;eXyg9hz(vUPHg*$s_lzt`y#vTX`Hj-G&F5rl-#hsMcbS2 zmA$aJ?O#D>iEX#;mbKgdeq!5CRBeAk(#P7K13a|7Rg2ST@iXxj1AeG(v3;146W)H~ zZSyYjspH&COAC z;*YV`ct}c(tu-PfGiS%swq9#IZKqXhjY%Xs=2|1i%KzWi8a+t%i))R0s11hqSdqMX z{a%{!-eQHNW2`ma<;&4)jfaRm=33*geE7w+#{bGn;P5$#G-4i7Gv?2&T(%#iujEQ^bcKWv*ffK>6 zzG=RPPF+lw-z5C%MD|WCe{Ha;XUVLY7x$MjZgF=`e>^if())>o1L_c0)nY8nWG0jC z!Iw$Sq2uwu#qspZ)oZ{NyoBCh>rwLu)@@+uwn_35>l({!zXiKGo>E{@9m!`dBE9(` z3@OGdl#1Izv)?YnDBKO2wq|t9FOT9kZU;XpSIdtO1rHj>`I} zOx^qQq887xAEmnnbw88e!Q*S4f`5SkySa3t5L(n+9>_+GBS+8a>-f=gd=tDW$=PaC ze?NEWpx-Me&()=abT&>2{z9&}Q-b2Y(%I^0eUy%ViWBFLaN^vRS6k3ifMX@NLwXwy z#~N|FxrOurBlkM={&f2F>UGu(UP4TA`onA|DZ;rv;uvTTT*ph!<8uvABKj-ceMs=5 zC3ePEH!P`h(}^}00uM4J{R}6d|_7yd)21&`kBfE!JT52Xt|d*Uq>)yy_RS-9iV(^&SadmVU4tn z{G5_vkA!Y?{=}dE!RSoAA+;TsNm?^rCL)Q}TI8ol5)|@CmmT3Qo*s+FN zsV?G+`lf8*OheaDYGu_C>|VQSKY!A}H>FyRKZM$HVFXF>hCZd*uXEDWvJ7Z3cEQj1 zLgVcKE^mxCaWpEflw=cO(F*g_BZvws{~WiSTVZy+*7CC=z9ef4s~{wd$yO-yv_-4M zJZ+JI_!0ngEY;SUHP=vp-zp#jsd;T+P-wlf;Wa;>CTggfjK;lv51_g(@DzNFlSnp0 z#7pJ4^|A9)ag#g@roI=gu*2|@F2grv+*Y6W1JBKG073!V0DerajG_whPRbFlIxf31 z#8cF`NAp&;c~lQ2d)DEYw}EqH;n9egI~n_)yI$e+-k?y0=l+ca-Ug3yE0nz5vuv#@ za^}_|<3BR=aZxe#KN`ibWTd1dKX;=`Ider5ZZ@1H9ljHbEv}%Dn%wyRmCty6H5vhR z4b6GfuW#bmls5wYMlL#(m&){5%S;($lA*rtOnKLu_ePH>8HU5me?|nBn}xj1mkKG{ z4P@VU(Q={KgV=9WVm9=!XgAE}v*@a!A`oD@>JDSsr_P2Xg$s9!GY#6+Ca*S0jt*Mf zQ|b4FS}CWWRSt~O$9FrjdpuHXf>q?wz4ai)Z+wp~{WMRuGHLZ>N5pK=lRd7&lRaUT zC%br!Cwt~vPj;xvlMUu0>N;+8v8*}9ppW&jIW{yiVED4IYfH-8eJuTGPz!W6;?!q>7Cly85 z%TkM0p@ZWP02<#eGJb4KB^{S-lJXo%d3h*6nSTZ}D6_zrp2=z}M_FsJBW#Fe3fop+ zu>STLADS0~1H_9g7Lyj~#3x?CQ)27smoF`WmWhB?nQLxOz{U&9h&d5jfz-id}bDi>XM&;qZb?t1_{nlM#xcbe+%? zwmJW4?9TSJay-+S7Qg}9`XX`^nawY6a;S;M<6jO(6_MPNsY$9e>yRG;;ao!7}522+KcC|KEaz-oij3 z@h;PtK6wmBhd;VWq3mN`%Fp9t&=`BX?_DGN8H+N_E*NJZE{*etCu9{xib3S3L7yMw zsV>ZM0_Fd(3wMXs`@=;?ae;Bn)3&YYhWg67%-4GkICKD z(;r2L#PP3mb0Zs$^3lkHrQZMx`B~y<&Bp?YkI4YYWNlI2ijM`nX8Et+V_r(J_}B+M zRqF#5AIlO3Cc9?no>758gNe-S0mXEFj+t3gtc_=`Q}7u>mgBI--GH$L_c5Q0)&VTYCk|abEm8)q6i7X7-H+yd{}K zJ$Kfki~Z0SPCG1YupuB0qXORRGv{891>*ty-*9Er%MP+38y@ER?i}IoEG>hhIFeC^ zuL*keOYm`?4K9C6zj{N`u;fIi?DB&mGA2coJRO7w`$$V2N7Oc z=oT#*sLl-WQG}lAQ>52w&4&(HLXW+ZYy1$&k5(RXlranBo?Hk$OErCWG!C;5r*aBX zjh#hTkzb9S)eOVD1GtZ5Hi#WGHg-kpTP&-dpgJ{y9c#^XyMkqxc@}SbK&!P4Qd6fm zK&JrEmj%{3Bln*K%nk~&gi>Q57Fr-~XKTU&am_D-_yRJdX{JznbImVgXknf$ z@NSoIWI>kM4pOB}YMbZNOihb>`KVli<HF2)waEi7Z}IG-_+*HDI9y1#aKI=NBS z9OQytrfu^<3ZO6)HKBcK{jDH5|5rf*WH~LM87I(4OV0Z5`RxXrB3YEAr}{yOUGU`_ z5PPu-q!~)86)SSF))DT)whwHJdnJ)&gi+WENv>SDi!&d~M(fZ&_pydAOs|-q!OrXu zB9xF5M$UN+iHP~4f5nX%TChVS&RE7UQ@#`IEfJy9ClZUdO>@zweUtx1} z5%I&)8*ji14lU_mZ$F5G6){2LsEXuzhg_b!U-22|)cXwaMg}&xV4-GshF&u?gIc9q zJFtRKprh%M+GIH)rH@gyI;>jL_WKOIaS$gaYKFx!lNYEBwe|7e^5&7ymu{;N;^K`m zJcKSMQvZ(NIXLR2OxO)R*1UD)?GP-Hw1wApZe-`Hy8QU~w2MT_3BA`F-}Of(GJ$?n z6z+{Z*;heV-**~Mw;?TLIYOM_t3usxOYkN4Z1M1+=UaK zRI?2rDQ2IbX2D|)mMWBn@XgsoAz%@{Int6I@b(XO#`2DSO7=zQa`6S^Z5wI|c+U$t zea6YYsPgE>fInc$NR@#f?FOYK7<3D+DV-TqXoxd1?*uzD!5CY7;g0;EF1P&rh8AG; zde>lal|2bye*;%2mlGdxjC4sn8UJ{C_lynQiTV2mOVq1HO%meDh{`A zBBH?tWJEI{j6Q1st0r4OU}Gh~c-w|ZUR2zn~!2{Wr_`6qS{hXjrWF*=DspQKpY5W%Vi{cjxP9HN$jaV>X4`pV%MFu}F@ z3f|Z~ibq6g1iftaFye^1@I^>zxazwc#jn!fSA8396`YdLf+)8cqF>LlgzNkgK%7;S z<|zwJ(Em&D+(5buVPUpb!y4yVGS2N`E~ET@MtMWmnFiT|+|o%{ zE1dtGQGN!78~(^*meX@`%qnc8Wyq%;4+;~8{BPiH`zWFncSD%84xb%F#gCV{A9=|i zLeJ+CgMGDfaooKPS3ihe=J5=B(d7QBTqWD7UhZA;GTimNSP8!Ol>$~WFmUYiZCkAj zuUZ*utPIad1~Hx8ZjOnke8o!nPb=j!R?3IeuiO0LoJ0;0Cyv^U{PH-_W7+*G z+NzgQ?37Ad^_l%ksZx}sneoHRX*An>hK%S?jPWirZ87FF7zS77UPsMZup7t_AKh%* zkK`2|-VKkG$>vVVYQ*~5-Q^|A3rB4VjEB=$IT;JZZ~2c@#fLKk5`a2ZXL0!t6H_91g=*`C7h1@ zj@_ueVi5 z(^d)puuFh@ws4v3m1428hYusxoh)(~Yc{k`tl#iSTKNj`TS6u<%(hG5n|rE+ky;W? zs{OeOQ3;ZyI0p*5Pi0LblebZLNR9o9mUIkRIg3SBr4~748^+ZEJJP7AISw%$aSX7r&QscR+doyyGzF4|<<}>jn%njNiZ*u(6(W6! zHdnE}p;p55=^()#eOPD64(Oz%gV>y0jO{AfbYAMFkky@42Fi|C=YoJ*~N| z@2J04@LjPf_WuGZ6OpUz$T$z8Pf>xn-?CDmq$h!NgB(wCGMk$V=F@GF&?coa-$gH( zVke0@N}aSAG(J7pAz<`ZU84-I-jaR{E5j>Ms*8ihNX$kJ?o!R?MDDUnS@3z^#+c!7 z+?c_`>3O)zA*>D9$g0O;i}5`?M9()8LrZ!FGX^LawUWvKmP16C2Xba0_j zlV`9?_->xutMsG!=t8CIz25xOT-CX6sLplFq(xtf*(MUHEYIQiTsn`dc{|@zZIYJwYmET~A@=#ZpD2_8$Vu#^bCLZquP_WZh8rSr_YFr>ZFF7!1o*dTV^r2swpE6l5 zPHuRcuJebx`m;X}6QS0lT1gdgnSmWGW!EA`D#P})9@V?qEK3~Kn>@FyqHsp_=e#uY zk@m+L)oJQuKyMJh0+F8f$mX`Af}X-B7RQFRZI=2IrC^q74edTf#xw>tE3=sVFqqGb zvzBzwaGJ_=(5y$JW$p%;RliMl^ac4gsyr7cl9DY7tb9<*9Yb>#UXW$aT?=x|C&&pr zO1@m9O0f%&GZX(ia{a|kmMEX6s@kS>Yj!1;&T^>wkf^gfY!r6;ztGs6xEJowQe$InPSD?KdXL|eETV1p&fwX~ zp`sc%rVkk9>=4_J!A`R2$@Yy%=m?2&C+=5%7V6gIZ=LdKZ`5Pqpj4dt<(x>6B-tiM-g^{eh{OWAJ~HkwVRe#D=s7RYLc|Z4sv2^n(!{v&>|_Y z;j-@3yaStXk{1Ze#@v;1gLQPHf6HE&mglw;;hKK^qoT+x2M2Aode*fy>XvPuf4xyx zxqElt1G!ZcG1PNc&3Y+o14BXc6ue@*R`E$w#rL~6P%XdrZ}2q7AFBAiX@jWjNVfs* zF5i39p}Ea4_V+zdy*tUXZef4D^2-ZS4q<2G-5=Upv8Srya7C#7%25#D>(;N}{*|M2 zz>NLMjYc(XZrf>G$YJgKoDo?;(OPvw>V_z_^w_d=v$hT6G5kmLfY*H_!NT{~3xL@2 zw3nMl@e+6`d$Jdb%4kaib1L4MMlxM$rKgKR?tPc=F z2Kw=vgVP-5YR|gU1w+al{vW3&mw1dk@;ka?X=~&ovwY z{SzNH`>Z+EDlBlVZ6Wfb$xSlmZZ}1T`M`M*fuq5stRnAT>r55vJkN@ki2;%GfS*$% zpLm`NjyW>TIOif?^fkZtz0kgfXGsuAlGz;xB^$lPb-#u5dl~%Cd{W z=>~2@Zft`E7nVL70B@MEh(AFQYQt;29-J);Dbqzkjl}{!B;k4PoG}*UulT)NLrs4D zN7?8LrQ}D_dgiTY-{_KgciOO8*ENEK+F%CK`E;)N@I2SqGtKA>m#aqU`+DeWl}*n1 zKn(0z;-S6UENclgFk#!D-OKgn`AN+%iE&q*Ia|f-GTZZRG45r(%9gx!pW7z) z`#lBq=zhfU+Bq+wDbd!;Bapqjh$}g~X4!dAr7wGX@G^hooRc8HDnzqB=07aTu4)|W z51-dOG<@0B$`+=fe6uhKH97*Ur5NQ*yj*zhH@3;ZcmxDMQUV%;n0KI!A`=&6(niPx zGpcZ5ow9Mo61#8J%7A<8iZt#zuEGQ%^o?)OqV=AeDl8t8c>Jz)fB*l1$H?uY|93nl z3rhMQ@tCk={OvsEeCbr#RFCtRHBkKjw>;*3!LSXJ#bcCzYUJL(@ufA*W%ysfU7DI+ z!~t)1lh0f4x#<%bQ;2TH+t9j01S34HRnA z@{F|Ma&HNT%D+P6R_D)t8^KZ-fACcJJiNg*92Q0B806m2bcRSwFVWgqV+0hRksmR$>kXMfwDR31`lVFy&?`F+^VAaX$$J zZi0IV%49Q|w~}XLYl$XwFXly367~<0ufnXCL(xi}+}-e(HISdY-GE z1J(0<^&G680!OshQ1u+9o(1YTTs?j2IZ{0X>Up7hj#1Bx)$&4C^<1o;73z7DdM;DX zo7HoLdahK@Th;S6^<1T%cdF-I>iK*1T&s^|Uc`6u;Uqn;0{=U>(HVfB1eJ^!Yj zPpIdU>baI@AkzJ!vzUv7XpH(Qq2UrrV~%PVETO9;)K5Y$ODIc1KT7B%3H4(tZ0IbZfP_*d zbe)7W3Ed(gtfr#V9}(#HO6UX0`-z11N@$yex=XsZBy^vIM5{XeaS3gZ&?X73mC*YV zdRRiAN$7qF9gxtS5^96c)38E9T_vC3KC1#!Bc?2~CzzKtduy zH4KwbSV99O^st1)ciZ%5CDcHFH7h_35oNFhSd`KSVFf+Xs?8p zN$5uj-6)~7WJ0qg)J;OuBy^^Pt|An@ub19U`#nVSdp+${hxVZUFyT5!%7+epivxWf zzvM4^Uk|;jHbT=zw40}0a=NB1NV!$lm+8$ZNE6l5#HmS!=W6YAxK;GN?s{hp)yE*` zcx^~`PQRzj(5E)%u)gOpLXxi3MzGy=bxNszZR_tGj`k)`)AF)3tt90}y{z?j$)9|s z=I`=o>LTlhd@m90NG_7MFJIAL-3yj&{pk+8T%F8>jY?<9MP!aJ)vm z^w(K>kIRmGHASDbov~Tx9{E^`c4yMPaD^vQQeI4PKAS@CE{TzZWU>4B0!_QXakZA0 zscDl^%Jl2vD6qdvA33hk^7%d`C8*E%E#G_TCu+9<-z~c1aa}X?UYho#p7OG;KbP20 zq2phlu7dI^bjM$H?ItPj5j|zSuCHxbUI#sO{Bacyz4Q+xUP4pVpQ3Sg&N?Ue)4FBb zG(S+&1}0yj4TZ^DaI7TDO1;A;x^|xqTmM{7IiTxbw=6$b@2A~Ex_k8Wr<{PWg78z0 zwhuV94Gw7PW@p-;o!XsFX8ylAkK5?f|K)7Pn$*)*KV4e^J73{&-|3`3la@KPhaD+| zpK^=`UC!ekcItmh%q0EWOPi-@^W6W@wN-k`m%4VpoG=AL-g(^ue08OHXOib+ct#F4sqE|0LZ%^>(+qwJQBh!VzbuCg{vL7H=lbv?DGp z>O4c!9&@FA?b4oerNR9-yPO}nv^QMr2kvsE{M)5}>*}?}t*>?`G*sGo8hs`G)pnPz zg?0Ezjh=>!wRZ%DPxO>;b-ghW9EF?H=vj^b(g(lO*;J_2({}6HyE^zhMt2DBO4n#3 z|Jyz3&>HlKcHg$_>(jKUnl?4-A*Z%YPkzLy-Qs9>hf~|+82Xr#9!nwScISCQD3sSn zGw2?}kyh){?sg2lGYn_b$I&bF_*wC9~^Pr9@Zoo-@wI+s(i^l7$!a`(14q0O2s z^mBZj;2gg9x}Nfpu5V3jB;_Zc>K>tGfsSL)WVemF`>;c+(`Rbhvkv!94(&@v`VS86 zpySkIq`z+kY)zY^X>&SkOJbnWA@}MXYm>Am^gDp;MMsBqN!nWuqW3sDJd~vEm*8?| z$GeiWdz=U`o1GmhleF#5OilaV*>S&HyVXV4-0$kR$E`gn!IxYe-*jvB65Q?T@Vs05 z#x+XQUT{CI?@Q9ZOd?t#K;dA3ewK#tboMfxWz@TR8U(#dZyRw!pZWI?cBI_w)c)m6 z+2PbTIZuw|1P7;T{5rYQR}QUT`iBl}SO=!FnJG^@z~StD4()di8VHWZ>7z7Y?iZ+Y zGdj>?J0LU4Y@xl z<%J~up`>{23a4Ek)?J@Ew7==pv&P}t3dSON1dHM zO{Ed(yHd5+ogF_;)oypCt#7Nn;7V&q)#_a5e4DEM=<4)ks`ik3)L96N$#{GRa=*w`+2H%cWTh>rbb2GSanoQquN$w56$@uRPkHQqvke+RLe(8a&$W)U+>&Z`~Ov`;e>}D*Qk75SLn!h}@zOSD`@Q{uWqrRnSE%`!c?RrhSzU`;N zP}BD4+N1h7mF_t0CcwDK(e{8-`==xAJE!)tV~bP(tQm?7lm7y#Cg0}JE_NT*wadQX zqa_y!G55Vz8*_rDU6-;zFK-?s7GI{-FhU2F)gi%Yp9v$^ziQE^B9FC%^LUNoPU!fQ zuJv~RUDsCVF6Pu*^;~I|#YbTAgO8u7jbn%a9$y?pp(~jf+?bcp%D6Kttx-3qHa&8tv`=@>e!H;$9hNXPrZzr{V7kVt!wAFfd zzCA0+j={vE_Z87E!!&K!iGOry6Hcgf!38t^;nFG`ot83bI6Bt5w40pC@3>$=j^|w3 zA5{1Or_9zHTxoSKy~b4#;|{7VCn$V(eB8mbki6ERy{!8QuW-n^+QvC}?B?#P^?<#d zlTxVXCgA*NT&8&4%u7SAmh9y3L5DK$j?Vys*}Y+ZddlB*{h@>ovC@W~A~TCXku*jdf=oL$WvYHv0vyzHysBsNJG!<3nFq>F`9jxsHWy;i4^*9> zR;-Q2Tyc8JeEo*RGW_}wyJOv-IGL}VTbfbc&Vokf)Ri<4^{m@}M zO;GKkk7hz+(nm-4;qe-Sd${{~#(ny8I&w}Dr>hO5nV(6Yd=@TX`>_n7tPa{sPNp_z zGQx6=^GQJD?-$}*j763BXCAD|qAfq=(3v@iXo-IkCx3SQ(A$UhJ$L+=Kv6;QjFLIU zW%GT-lcs8Y`z1zc{nXFVldmhD63j21IeSKNu%vX>#GqC%DLARDcv@yjdFG@UW#pWn zSyp^)NqMlitaxhX z7iWfMHD_;;T)vmion;j|zciG2R;E1doGM#+3AOgoCe4^pI%QI@v~2JtL(V_n{#Be+ zUUFmc#9-#E?99_=ot{}dZ%T3T)bh-kljfDo49(0e56zxkS{9^uNvBEUFSgrJP&R39 zKE+I)H065j>~ZDAW#wm2CjG3E>(8E2I<@%hd9!CsnpIpr_4>2NmQ6WZvc>}iCFOja z-)D*{aa_D{Ey_%+Y*g|5v9n61O)D;Im7~>%5yio=Q_6~qXN`@48;==Q8k#k=e8h~> z$&+TNLimz5V@6TwtP+s&Yrc*i8_QQz8Y(Xi2s-KRV@4*_lTZH#i!UpgHMMlEN^1rE z&ACw zhk~lsSge26QDBr!no|;N)$)srA<&Xp*9J;vmITXN!ab&xAwWm*xd_5+`SFsHAb<-T z@%CI?JT2eu);P!sahFWGz8JEbTso<2>hRJjA*(jur1GO9hm}#M)sjm}hnJPk3Ti)t z8-Kao;8|8O)&15eDV#M4-1d*WIV3kT=eP3D zF=Zul$lGVS)?+%8i=bEDXAQZwI5=^3S@E2#Y#E0ajtc~|>BovyITAlu;aSD=f>ze) zv3$)@Qd&Yj>qBB0Ql-jQQa*7i;8-PPO%*DT%-I?c#=mLPWAV^TGd4g*{_wFu890}e zj=dyc(MBLJE?6?7ywA)@Q$3Fj-?izPVK#He1eWuKw{hO+sSpun+7f&f=-m(GHdX>`-t!PqNW@i7)emVX6 zY5n@1pEKb6{$8!TWailjD&=rGnR{nWoE$2dF?AwS2$gG>OcybPQ0APH(iw^hkrHOi zkQfTh>Q#Pzuc_IoRG?iNPk^9eeM7A1RnFJ5ErgY8!;6Dcrb}KsB6C`4S*Dhns>KqF zKWmIk|Jsa6w0%-pA4?jrUz+_jbJ~oOYo`YhE@p;+skBUkkC%qZrWBXQYdS;nXlIX6 zJ(V|=(zL{Ipww!W6?cB7qL)6?%INX`hrRcXucFxh|7XuRDIisfbV5-P5di@a6$2yz z1VTwDVhJG$1PMtWsYZKQiAucCx;(yG`mW7v@=4z?-%JI2la^+4;U-!?+N-xY3 zIXxpwZ^sJaaXm?LW?caAyCCh52@94R*w z;|sFl{9QUfy|7U3&5H8kbPeojIQlPhFPxm45jSpp)_AErE7#u@ zM#%O0#KP!m$_?x2+zIJ9qcdBZ^W|tuo77Rh?zEdgUg`1YZw|f~YTG?UZg=&%?Qf)% zqCENh-oCcWM8ZXiI4~>KHsdNGbmkTayVsick_ zU0A5aX!E*d_y?WdGoQLJXszP(#y;IIP!6n&yzx1i{w#SfU{^FQQ?{dQ_;ksbEmv69 zCyU^h?C;V;x+bTlqzz0=>XX<#wO7Andjp#`C?zp1xoc{#!HH@8yQcR1&$&Z-CG<#4 zO&iiHIicT>6qD$mQsa{Ia?eX2U64_bKC*}#Ku!-M{nquDB|{F}LVuM@^Nr2Q9pAd5 zY;k?(Fg8!OcJBCIMOkCxCZ@|~v^#KmZk*ma%Em27&mASLs_Ak=ku|BcZ^|{4TC$$X z{~y%u*;yH5DF6Q!W&f5-bs4L@q$?V!3(i!9<~%w7@|c(XQg_>oapOnpnOQb&uH5D4 z=-PMf6~~5?Hq&f!Dv)!@KW5YOeqO%bOz4?kTDYKKw7mV|i?r14T~qvvL%zLhI6qfz z5;E=WW8wMfqtoPl;gx4*UhTJZTHmhyb^jQc)+;$RabQx{?ujSn_mX!CJP*lbWqgL7 zxv$Ie&;7cA?OT{6|D4_@Pfh~NoS&`dL%oFl-+7bA%jr(9NP2Mm-`Tnr$-a>#6` z8{MDeD8W@EN2)wgLg~9=9wGLW(b_mA6lP>+Wsa8v_y4twLH1ZY?>3>zntS z6YutQ%caXE9y?aw&`%s)lxT#`sXJt%P+xdyddal z$Zy({uLgP+)Q=&OB)zrqTh~8h<)_OsoSZc!eL~iWtlVgR?o$+ea&CPGTbM5wI+L0{ z!gQCtRWIUt5;cj18R_|1CdE(fFK76;LHWjy6J+C<#N15NQ{KgzK3OA+j3f=zdjaF8 zrO0ldQDo#kSKcxuPRhy{UnB+Prso%C=M~ANO+IaqoRUdq_sq)4H*Mrg*>>gv(_S9L z>1ZyLPy8-2UFGx6?k2$`%7;=t>RqmbQ|otz>E|x!Ov$wvw-% z>mrG(oF$)(O1w>elCezU?(%iv7KztNyhq|o=3EHwR~hN@zgf* z5x2yd9gLYR@vjn>NIXM6bKNTO>vooPk+`*d)o_Ev zk9HAXV`-qp62Cgkm`xHlA8t(K3i)z3T|NSrc=kwHPKh^W%U3-TYtOuUCC2y@69FNd8;uWOT2ZKlq{t_oHmal*%UcN+@|0>V)UMkBk@f{BtGhgCLj~Mfe#FdtNQ<}#&XFMm% zCGj<{NIlnhCSim84o2eVH%YrmeC6x%NQJ~x-je(hU%OS>L*kp>mT$HtZu_yUpTw;{ zk?kPy(9fhjBu@KLzA}|q`sOqyO}4`?Qm@3{9gy~s_`^f8JtV&Ru&lqt>Ay>RN_^E3 z`7yJ^L;jGjh9nLjldm*}%hwh1$#Sa1{fuXdBG$RGkYbzzO`p+ zj_^#(`Lb;#en8?*5?^E)5nA0N0lOL?bUJzwsmq(fCR?#N< zA^ATu#zZfUF_D(BCbC-o<$3nVcKN@iqKWL6|LT=ZXlP~Q6;?Kp_|uJ-db){yN8)cK zPOo9SNi|IDVflKfb4?SGAODyhwM?W+ZTSUfZ4;?*hWK@)sq2_fm%1kA!MY~YsGf<= zl<(Z;)HC4)^-aZyoFJw(Fi}S(&TnYKt>mk*{6;3UM&de+P57zCCR7q<%>FnN>eR%T zicL-E@}?%{U{m={rI`ucD98U7%}mUQ<|g!2a}(44OcUySmI;T>Hlbc}4!G%T6ZM1~ z`$Nt#p#|rd==m*8=>3)^oY2~YR<$-U@_WV55cxgOD{W1v|zMTp6zQCBK?M%~u)Uy|w$c-17aD&b!ruW6ht9hx3Z0uqp?_Fl1y2qQ)NAbq1 z)ZIkg(A`9e5=_(|2_|M`qKORaX(EGqnMlgzCbGD<34POBj)OiXs<@8{t(RkdWnU9I zJ=ugGPBu{oByKstMCZ#larX@{;iME}3Q|mHS&H#~OEKXG2gz~`GNH&|;|&~a!pDag z({iW@4IgT}r-qvFuwlkqCg+d$hnY~tD@}OyRmLP=Z9-pPZM+KCn8;^oa!yV+UafRF zM$%1WYlew^Cey@dZ?gTfj3@8~RMjjZ-F;S~>jJGYvgq!7>(6hNFW>B7q{E}~?lE+DVkCU&2#u?8Pn5ZKK#=E=F z#9lekcwbI5;cAnO*I}}W)Vbco+;_c+z4%`ya#OL1K6bN-q|PwWgJzn@+jp9nlzArF z%r~KJ^NsiSd=ox!xAC?wFrf?XH8F?pHC~-XCX~F`M7O@*nAP_iul*9)cmHj?u1ih$ zu?I|~+e60d_mFJYhfSo-BgVV_5fioiQ4_P}G2<01GtsG!8*kX-CX%<@M6X&d`_pn0 z)$s{q<~?DeK6pa5$ulMtx5C7%UTMNjo->g~t4*Zm8WXwo1zCr+ChAt{DZKxS#=Gl9 z*>10xsGnak-strvs@?|KPd1vETV6HZ&##)O)tgLA#%m_3-|MErPp`|d`MRlibc@V? z!-V?0X~O&8GSMC7JUD!-iTY@(?8k2#@56UY^wMo6=Hl(f%ieCHHg7l4ecv^a0q>hg zpASrQj}J}kyK=5P^s%Yf=Tl==eQKh*eP+DYJ57b_cN*{5P7`(6=O%jE=dzD|ZlYR# zVPZFbVL}h@GG_ZO6MO4daz6jsM9GiRLvMU-yf3~s;fddv(CTkY)S0`Dcgt@1LUp&~ z`&Ra`?@aW9?@VOc_oiah9uxD-9uwNX$AlOEXuKbPls5XwgtzWB=EzCTY&lPtNW53#KKo60+kV*(51OcUhvYasB<=LOi5?;6>e;`WaHl_vcdMMI zSN>>n(&&VCTj9A6JGn5@j}OCeU6)$`hUy0>u=+|__qmlFkWOr$n$20yr^#^ zZXS{IdBh7hmGk46C@-dQj2Au@Yf){%L`psORftN-&ou8R@e5z zXV#HxP#w>^wyqc3t)3U&U(fS8*Z0CR8+b7l8+u;-hF-W&BQNIbMxOU)BQHEM&I=_r z@uFunk@I;IFPz*|t{+Xk*yv_nC`qmvjhcJm2ha2(wOe@M=$2mOx>jCz?s>9|avhO7 zD7}UHpM^C8wM=6+BHoJlL&Uof|A=^Hip_r*d>nBs=AVwZ0pha|w?W()aRTCG#6uB} zK%9ek0^;BbufzP!h>H<#M?4Ghe8fu-FGKt(;@yb%AwGgQlxo+r65`s3;}Ew*+#Yck z#61xYM0^$Ek%;pVUx#=a;yH-#Mf@P*62z+!uSfhQ;`b4Mfp`z%gNTnIj+Xmh4b>3W zL);v3Ys8%pcSC$yysw$Ici8wHxkuFSiJVh3d@skehI%1e{+3QQo}Xmn5Atlh7jY=x zvbE%XZi?khIrnLhUuO8>+zdOPTnD@z`H{^8ITi_*7FoXnxCgirxHq^mcmTLQcqljy zoCa@|ML9w}9og#Sb&Ua{JfqQ}XfG-FC2$owtKkNnf0q+C%1@8wZgAaoHfe(ZGgMS0dZK5BJ zfaPaDe)tnCw~u}}22KSZ2g~iG4dd~mFfG2~W z0$&GS3BDe@8hitIE%;yHm%%rJH-c{hZw42G-vr+beg`}SyaPNH{2_Q6_*3vL;4i@P z5r!YW22Tfn2Yv?pBX|WkW1QW;SAzE<{aNs3V{Q5>@IItJ2i^}}4L%5d9()+Q2E6N9 zTiy%ckHBlezajsN;3MF5;N#$zz^6^HNdPn*MVL0W97eEajrxI zP4)P+G2N58vfuE8tdZ&CbBfG>ac$<-j897&mYh=5ww-jmI;to;&F^F~p>5&>Q@ou| zhk0`~S8A_dHe=@xPHx*KEiGfxr1TM^C$w#Qp}fwK?f}!Y%dxc4(tU2CDP9vbyxOU9 zw-d8)^eKecrAwXFfXUN#ve(;9dWys9wFAKcITYBW=WzL;A)&%Csf~KeCOOKRk z6Gj&ljZe=p#d9NCQ`)FWlhUO7y}~@{Y*YHBPMgq1l4Q_(ThrWHnn(I?%NUcEkv%4D z)OhJOT58Xn?Dx$&engsd3M@T|Br$58?uFL+$i?X}h8JeNLlR>&N?l!q7t5D|;J$Zf~f1_){a6e(tz&_pc@+WIo zb19Rhll!s#rIR^L&Mr+xC+J1l|CuRYn`lt3_8^@m{lAWvF5yI-WcRV&DMc5grL}F_ zZiIA$n1SAGdu1f2$h?f~^n$daf^_NeyH`eHqRhKUI^VOs-0O_Q3#H?|eCdckaqQUs zy`^g_DYn=SfJ>4SAtE*Epn|Dec=;D%8=Z`PUmVGE= zOrpQtxBL&v?A|tUVDFR;X}XNt{|DuzOTVBj@8gro%g-t6A*n}c;9yQoOKp>u+BPjw zHdIQ-G^yeuf01|DDpHCrl70%c7wMub|JXa?`R7#aI<}xFt)M7Z*RMF_&m3`GRzaTf zjF2AZ{#hI6gse0j-6G!~vOzM;wSu13rQk`Ui`2UJgf&9OxyVh+&`u0BW$B5O3@I>e zy!3ybFDDKey+Kl!ok$%i!%v)C(=#U${nLpGYi#ZQ!LGdC@`>w&_NuE1TWms6o{YpH zR|%Q3UFW2akYPELK33A*M$UuM38&22rE@ZJr04L=(Y~-pXJqE2XJ-1i-=d#G^B=KX zx+ukAKf81(>o@ESi-nW@U45?7$Wr%SADMNjlJpFnEsIx}mm__4`aP>_CCf^aw6Asl zRI8VGO?t*A>4{r$jgMJlGsfmCt|#VCR@?&Ao?n%>D{K9-uFZQT_e)6Z*k0#s~vj`l0u+xW@Wk@n>$7w+?5@L7JF@^Sv5aV2;u)Y^n{-jv0CU-HrHqCH7i47H zy$CG*`1)CO=_9j>Cd&NwXgxv8lzNy_+df3k$ongnL_@#E=^!z^Q zljYbwT03mskdi}%GVWil*EvOtZT_x_q~Nt!J8P4a4RWsV6Eu)0WQxP|VE{+q1BFt3r->y@A^uw^`q4 zw2Xw~kK=z_wc490t8`&IYTH}<-V@KrWmAkIvRT$VZ01P6Hlf@h1=9I9YrG>$H;_L} z$6s~AW|4GkXiB7en^2Ki9hECdvKPvb6>?WDJ?D;)dvLS1hN+rho{mm2UsjTLE+>ud zV-{BKYo4oYThrWLHQBs+x-(eEgEdmk`Wi{*mzw>};kw<;>iRwUrzB(*7IDyyC2@&4 z(gSf;W~!XR%!;Oi&GKe_q`&g<+Ijtg<|Zr~&1{bzZ5A{>VI}oVk*;-Rpq{mjO|)!M zZJk1MKyv*SJ<{A#A=BJZVS-s$VT9RGK?acRCu_J(I_!zgGOJ^<&E1tU%wu)z=mAl(PlYT6V%=VbvO!TUsnum>cq=BiBVAjTB^V}7j9j?}dmcC)!rlG)MN-($ExnALGz%{@(Q zQ~Vff2e8S?ENz7Kr)rtajZM^OQ(R%BnI+9JUz%f?G{@y zuQbm|_d}u4<{`=cyksen-iHKN3a%4eEB#rT%|m4JzVu{ic3mNpebS*&OoDl?A`eWi zP@#;o^m-*}R*o(8UM1ToX6os3)cWs`K5bO*!~~tC+9nQ2$8N#_XD#>Az=MS6BKA#Ryww@o9zf z4#z(l%<4)`=g2$HG|>s>;A#J{LgsCEbw1(h%sl-R3%@P6@LK~5Kev**@Ec^|9~dqR z&m~$>X?&3k`IBq+uR`;HoZhCUOM5RYGBOI?&7Mq`P1EV|Tm08Eb^57vIukMbZkH}+ zLUN&%i`TD}PP}D&Pr79Fhwi$)@<}6d-BmeaR^FlJ0hvlys&*K!$16*Z^iNCLCK8}IZyl(bI@xpkiC(KtSy ztRlUP7p3RQJ=MpxYxm^Zo^SBeKll<`MJeJkOIIYE6}hx#MnK5V^GG zO*T8Kj2J)49H=+S%s$iLRBmprT3Y%SQhISCr}WR7+A{x?GGDw$*Xz-RT3qRnUr$#( zF@V8{pJ7T0bXgTzVS( zJ1%0jf2odq4szsl|Kj8y>xHR#_FQ2$)|D$4u80R4`PWW=%&1w?YcbA3i)-NAeP08X zteY&y+|opL-mi4Q9{gITtG?0cz4wJ=`lLVIC{x*<{J9M^o&sWMJSVb1uBtlXl6^nx+n z@+O(jYvO|RO-*|-Hb2zlQk!i}Fl2##ge;OSPorhtJTX{=~3hcT1Pi>4kD%fMwcIOYT#q){U6` zesy2|TdRKdL2V;@kjn@oJTS~HwPmi z(8&X;ZIv5t9aO_PrM)2qEz+#v39`rd*VEtYpLdkUxZxnORRp=qU6r$)CtIiC28N^OJ@tG!NJF_rncx zURmMS^Na85AVB7=dh!XT-kRdfs)PxW|Cn$?guQ)ZVe`W>%p<+252)Vcy` zB%9yA&$_EV_Tt5|kaz5teBq?Lf?oa2GxfVoHcJ~6`gh?A8b-{nLt2PifWMd@*Pkqd zrQxW2Ube;jU$uo^{Y|HT9MS1lN7cka&S=oJm(*b22D~BXnlGdq_=uS|B`nh={&by8 zCBJ^m`&@(4(VEPQ(jc4s4DZUQ;xaJ(OwA^vI+&debWALJ4m5YlFbzDQ4mL=U(})bP zY95wNzhky)pUu(fZ88+R%<-pdWw2^FSnk&8(RDg~=p`*$-+!!X$ah$u$+G^uUg!It zPx|fhQA2;E9aeptRINLc+1oHhk12oDvF~I9tlbp$hRFCVd`q%cdXd-C=QU#KUrFhI z$l$#ur0*;+j8UOk)u{CL_TIRNS-wS=?yt9Xx_O&U4{g`!k$1zMy{-OKYWrn}&fD{z zPLF<|(>HhN^hp(xJ2I6sR=$j#>fBVXYFyxdf<4)MDJ}SopYw=6 zz5Qz~;X!};yi84q??(P?Tsle*_icZ`Fd6#Gd?0<~`}@u8xIXDcedOk1UYuNc{ZhX7 zr+@op`ET@=$C+m&b^bS6)8qd1JDJLHBp*lVdxNe;W@ntax=y#w(&;C+MWpOr8F~6Xdu)mf z5LskyZ`vn)gj{g%l7nWSq{}9~U8m2@(dpa%^jm-Wmp`5RfX;u!pRVwya~{+=8y?c> z;}7d}=c78E`J_%4t<~wX{&b5><=`zUk_MmFOh0`zPsts*eam-mGk%S;M7HtgR(MI} zH#ewezmt*^oV;PpC>U)&<$SxD9S%^=Kyv2zQZmXxyiuo5Y*OjO0dS<5-W$kir_fB3 ztR=5$rnmg*Yn%1;t#9dcu|GZJPiJh^Ip4jl(|h01=_-G^a=X5s{h>}*`_p+J>Fd8g z(JJ+wy`JvPp5_?nWux2*9NnoorhlQ+&4+aQ+;2Ml?RT9PA5$~6V0>0;UP9KWzPOh+ ztIy<1f4*ig>!h@$l3z;jr*9sMcwKemJF{I<7XGa%PZUSVbmtVE9-JB_pY~i-t=Yvt zgifn8->ci8%A~u!>Tw0tizZI-^ly$g+q3`kyaysZ>c3r~=5=S>aK;TuuY2-$@p^AY z=qImR<_$?Li@h0MZkKKo$FK7edJbRU#lNg^LHsg}rg`y~rCfGdLc$iWN5_&-iFes? zFaEyJC*BV42`~S;>y~=|_VTl{26Ve@Q2agK_`AG>;SYN$Q@otF!b`lTLvMti3f~#Z zpYJ^v$v@)V;=SN4i#qBZ_udHg=#?6uoG^U&Jg@Kb-jr}s%aU-bj>+yMxmCxKa89dk z1JB+Op5}GCwqnZe$Zl_n*QjE}ii;w3>t%LGY8K`; zh0DFKz396`i7kg-)qPuq8y1A;hCU1ZlA9Gc}#=sw-6U%CF9;kU!DdN-`_ri6Y7 zWxwG)DXlVb^2EhnjlaAXy#?OG(i9UjWQAmnbgC;>tJWC}D!%D0@@mz&X1X^m`lxr* zn-$gclTh{?uk*x<`(ArS_r%td7JCUJOT3=(tyX)3hbQ%@wa~jPPg|w`3fU+*`@EZF zi^Z3OlciN#bsSi$($&v;+5HmYhfnopM~3vccu%x$gXC6S>Pvk;g*JE_LbWcK;@u-& zkY4Vl`0MTKjrmW75?07dDU9)S=o0E%bs?hm)LUnCCTyayL=s5;&thn z^ik)oz~AA3)EakXk~3*GEhUlCg1)!7?rpOlr@@;8Dneb9mVtOhnc zyN%7i72Lmr-zonRe1Qa$lc|O{GgL*Ke%p#U>eCG0yrc z!6U#r=97jQaW=gO{E)EvOTb&3SZ>rsbIUkXO)cwKQ5t@e?X3B0US|21=C-_n;D=?q zY5IKd@4~u1r^Va+b!59~`Xya0UjZ%#-v!$TbIyziW^jWqS_49hPg z|M%eEk=|gWO+P~h2GII+j4=(JgtfkDqb%ouD`Z<<4%V^AG`tPgG08OS1?$*k8cuI* z+p7c}s9!Fu^<9Dv)c=L_x!^V6M)}tN9XtXo1Kaw`=b=OOQQ$S;5plMB9Scpvj5y21 z;AwvTVzV5)9y}Nwtp5R?0#20knC`D@z;}V8C;G*k_rNPBS*|7nC20OHz{9~cC)@Ou z;1S@T!Bwue>1VdHerIq#I3N5H_+{`>@U{Q4zK&z%FE993@NV$?;CeUO{8if9{F`sG zJPh2f*z%p=YrvoRY|K)y3}WbSkAvV_z;$o7{vPm8Q!Ix%+WdJ_EjIFBYr#{&Mc^gi8^OPV7tXTf z_2^{FUkP65bFn|xp5}NJ+~zi$pZlkd!KZ=y=W_57^ zyZ*6rZ2B$W=HRD=b^YVPdyvj?U1Bb_{-!&upCGLHU%k_EI=JRM%Qt~_>_81%pKIn@ z=K4Ggz8~dt{Frs{U%b!e{|NjZ_*dkQTWr(0el5YR<+`fNr(+aq;P!5@#BzU0*Zo1q zF4V9L`Fk(*(YyoJF$^{QjQl#5p@w#sT3^RB)G$L>>-&6_<)uj1u?{snkMwHKTYeY( zCHNQcPv8n&Y1 z?efHLv3wTz<2Nn$0qdBO8pg$I{$j&%g%*LY-Kwc4_E#NqQUmwbP2gYSt-lZ4v8&x5 zlHT#Nn_1uo!3Tx4zHh;4a-XF8->Ua){&m8d-sXMF=XJNd`2))jfIs}ua-9U5u47?p zmM zHE??+fuHm97n^+WabaDb(($Q!T3&y^`sv`EV4gpoIcU>gLb{G2s)5%R9ZOV0-ClP6 zW*@hl01p3cc`R7R7}YQXd>i;7@ULL*PnBf2L=9YD9h+3cj5xdeG7O^6uls(n*$8fM zx!oUh3{wrGz#oEN5Z3nKI9(qiy;a!eui4xBMc_f;Rp5Ex1v0jthL6B|!S(uBe;&pp zy;4}~n;vcRPxRA`xm(6m)vySxW2|a;0sewm%U)kw-lyOmKFj++8G}_rE?CE8)o>43 z$7a>A5nSsu%b)pNY}SJtC)@Ikj{7Ge4O~*$@(S>uV6UIe-$qwTLIQYaRm;=BvDGYp z1nvTE)!+J)PPge}!0W(|f{%f}@!9xe%xZm61JpO>r&`uO)8}H-t+wT>!JEL`e{^hG z4cvbUz!Q;wF?a>IX9Ju6FYp3z`+;`(H-dS7Fb!?~8~t=+W;V9W<7s{q%l9F@;aQfS z5!R+W25y*Qx#HP2{U%{OUrqz>_F3NNw6N)3s%?++TUu`DbFt~u%JS_<*Rgjsusw9l zT@7rH@4!#Puhzz<*BE5$&j)V>mw>Aew&{O@UjcV+YyG-IYXE>IbPq-;5ipr z|E#NR`f~6U;5Fb?!n!}|*u@&&^|{y#ywvjf*Vy{&#akW*=6FT3z!SRL^qt`4;HhcW z-w)>Y(=n1YaQoc{K8XCAz;lLM|C&UbzjC@|9a~w$PvF`~md_ty(+7jS47>gu$FPa8 zu5areHvc@Ii~TX0wY*uGHvO#LHvOp2#s1jMntmwDmOrbXP3QXPn9drwKHq^8M@sz> zgLT|<4Yz}J{BsTe2J1NJ8did12U~s(+yeYDxF`50a5nfj zcm}xoD7(DNz|Fy1z!!q|fG-F8 zqrf_jyN2t)I-a|R+rc`nyN0D;9p7EUvtS+PUBhOuj`yzN6R?i^u3;}&$A8zr{Xxfp z*TDTj$Aj0v?V;nsYd8*H$A{NYeY9;49VcD`_eUKsUIX_B9XDPB>(}w)HE@5{apW~L zLwP!$yatx1lN^UG{7*LN|P>r(>e{5guOy#Og6DuaKJJ5Hj<>rOd<6O55!UjmO||8Hjr9HU!%shqvE_5z z!A8oJjftCO(>n-P5pE7nLwXBvF49|pry#uzcow)l_#SX4@I%T~Ayazl6Y;Lpdb1%3Kcq_OK_i0;G^LF;P6c`Sd873OSj%%+%j5Uw zH=sN+{nM;ox;`$e&+psk!za_P6!2YEpWn}yz$eq6AMjmPpWo+ig-@nmH{iRhKEMCp z1E2ig{Kz=@setqTr8b!FUs?#qp>B;X3vhCPhX;6kfOUB?b%GE)er8C1_jp<;e5&Jz zzi+5iVD~@r9m1#Df2yE9tvXpIE^GT$Im>3KRA|d1HxzcuyC=Xki%w40@|(;5BwJkR z{^qjQ$KPYj5nqpg^0)s-d9woLxvb^YKig)=9B<1bb9t%b^{1NcU^rcx(s^4YxySK3E`S8i~ zCkA|%)n5z$M)+jR)n>%`h82nZ8?JvdnZ@{b%9d2cJyetxtWI)$h>K*1rrs znZ8@!sp>C*zZyQ7{+z)2yR7whKG$Y=4L+Iv?11mG`kUdu51&lmtxuQVW%W~A*$Tda zPp0qIr@qVT?}C32KAFB-->K@)Jr64=4Xx(`GW~gh^>{yl>%?>E96WT~?pJ=ku<&>tD*^>H53%>GHd* zK7aq$06w{__4D_Fo#2z{Ck2+@Wv!pTFB}S=O#k(O@3Q**J>n$zWcqG>y8bS!&)+ZJ z3!hBitxtWI)#vXW*T5&!zc{e`F00SqM}7pKOn-gAcUk?qoo$BS;FDuyM>*B;jIRSr z&krtZdHj9mbn*3gB6E3u3M`My>ht%UkH9C>?-uY~R-eEBEc}F-5v zv_5&Q@TuCvJ)V-qcUjBh?@hbiWXmIG3!kbycmLAzT-NgVd(}NCk1R?4@ruiJ>GpA1 zeg3{RTx^$zOkZaEL0RiBw&<6qK7S9}>SpVcHGgyYpW)yzns3HUCn&)?_vlg8Kj$@DJ^_%5r@-}6Rpu|App#DMRz`lrR)3`5|P z>E{G|@+8Tx@8|e^(=0H*Z(0oI_f1cM`F+y{a4f$6c^}*Y{5`lQ_)l;)xbm&G{u$sn z@G|fP;4R=J@E-6LV1D0}18#-yhi(G%`=)u|*+_o`TmoJL-U@yTychfhnBO-Y0Q38% z$aK3t{J!Z7Fu!kV3Fh}rmkP&W+h}yTrdK`jdE6CXejax%n4iZ@2J`bc-QJlxK?uHI zo+bG+nJDqS!uo#saNzT%;&_`WRt_}XpUGOZ9*^s6a_RZNW!)by>1s1Hg-@oR5b#}A zzZiZ7>j%^C8Sq_Je+%;851&kbc))jA{T8?Y?1WFIzaZedtUiBFe*`|6etf`pS^eXv zzr#%1{$%+=kNCi!za^s+dElix~x8DEP_v_@3y!4F00Sy13rOIrawHe{4T4% z3=7m?mR)}`efRSKt>0z!`8>j<@X7S!1NFPC{;))w;YRpm`pW{o%j)y_hXwG-^xgK> z<#$bhd@_Bvz14SFeLi1N^)}mnWctGc%kQ%K`;u&izVONPrv-eM)#vjZqu`V2 z#|M0u)nD1eW_SobnZA4dOqQ80tA7CgYWQUO^0Om9D68+X`Uz;zcj1%iyY-!_{;BZy z!zY*3-w6LS`QSj$zhwIE{-X7}tjizW%dTG&_~f$sm&3mlKAHX&TYTyH-({_z&+qhu zPo|H}Q|h~{KA-ow4L+HE$3XoqtAEGkHp2$^Wcsc2g#?X~W#Y2>FZTA6%?I$wn!maH zm)PV|-(~gre9|8HWcvSY|9P~Jt)SuUcKeg*9}m>;vewV%q1wYI(~l4ME~~%0ugy>h zpG?1=zL20%vP@i7|9G;WY-YhHYkqCNPi%6j@3Q*(J4+1@z$eq+VUtUJm(_o~zs;}~ zKAHX#0pDfyQwP`#@4+Y2m#btCdmw~qY@Ep7S$z}D| zz;6JbOn<2@zO?;Z*7}FygxDTFnf|{6zRT+W4!;k4GJUtbbp2gce^jci;2QX3`q_c{ zT~>b^{37^d`dIC4wfeo#)9iOcFgHpHe6hfk(|mrX8RewWqf^P=P7lj*zHTdm(^^-G^Gg-@nGJW#*O z>hpQjKj4$;KOFE~R-ezW)|zYEpG+TzXX*O8tUjN2O@mLSKP6DV%j)y_*xB&O^m78f z%j)xa+O6=(^xx7K5;RJdiOcHq`P&2V$(p~p{4bGz4fI`BpU>+yzSFiJnLd7AUh2E7 zKA-RH2A@p-4SnI%@3Q*Mhx^H9GJNtP;b}I>pR&BC0_C}^vM*BKTFp9x;^Fxe3#Yd^UW8+C)4i`vIQt>{VuD|=b`iA zlj*z5tG>(X^ZDty@X7R#1eV`r_4&N@3ixFD^0Am7l(l}B)#vls-@+%;e<9$ztUjOT zZYC!>|NR6mnDmzg+RtV6`TTbhd@}u`f%;umpU;bD!6(yq?_ZN;rpxNfKmmTZ4L+HE zFMT0FBlTTYpU;C7y|4`p$^$+DrCJ7(GC)3B^`f{=iz^bPo|IC zl~Uhj_4)jKoE#Xs{mAs=o%(e7T~>d4p3QJ2d@}vyfbX*Ud|rPnd@}unfbX*Ue7?T~ zKAHaTfbX*U8*xDX0H0h|zv(zz!BO~R`f^zLK{;6_E^Ga(;8(fZwm+GE-+=G3`s~l3 z1$;97=L5dW>a+iYE8&yrU#Bl5Xr#;Uvij^VVG?|@=GXlnANQ2{F00S}6_&s!({Cwd zXi(PrT~?p{F}whuOdmhDEcIPhpZz!d3ZG2Bm0$ab`dwC^{XMi^V7DKce#e0Cvij^F z;yUbtBy``Z`>pG@Cf zU-ey9pZ#+@0-sFZU0?NGR-gTO9E4A%@2;=rbZd)_1D<*U0zQ8j9hQ z>AUTvzROxa`xki;KAFDTUh2E7KKmo7aGza%GJSV_)puEa_FvK+KAC=wUA@xths)}> zE4CT#fKR6HuCLbbvijG+-wdBj-(6qz$<-Fw?*sWfSu-%7C+i62^JKlie4gwoFrO#O z1M_*ZDPTTNb~l*MlPv@Dd9oM5e4gwb<;t>6@O;A&;W*n={xo*+$$UnD&kb;g0AD7o z-)F|n)|Qg*#ld_&K<8%KBtJd)ePyQP&-7F5WTNn?e&4&a*rxB5biF?!Ytedr8)%bD z_YaqK`yMQ|8M@tXeKP&C1HQ}Z*S*zy=`gM&B%DVn8tIz(P&VInQKUwoPm;ZWJFFl@IR)6a(n_)71 zGX2be@3Q*rPwFA~WcnQfzRT*f|EZ7Rlj$c0e3#W{e^tlflj*k%_%5r@{;ldhXxooW z|Av6?vij@~s{}ro{-l8Kvij^ltM)^-elq?30iS$>djz2U#<21)Aj8W$aRj{p^pgJA5+zc>$k1Lh{EU zO{3cbyf(mE-aobXKFRO4_g})NYH#)znERMrUow}sK9)&2Stc&)`hF?jTWNR#KAC>1 zzL21i`Yx+~!JU4xc?CXM^Ea3Oxi-1fcUk>c;lB@`On*SYcUgV*hj;)!xvW0>PprDk zwjY`PefmOzM!NnkYyE%A=foP$gHP7{y8daJD1pAq>a)MbB=}_dNmeiQT~?p{JLbSA z(|51;y8JGy&;B5%!za^kAE=-FsN~n{FZ&}|17?3DZz{|CNj^`m<^9wCzEkqM`}_C8 zr`q4E-E9{r^>Mqs$Xwndf#r2s*Ee>7%`gT&nZ7KtAC$GdTvq=K_{H$a^eYB@m(_0q ze*t`QS^ab2KMtQxQ zR(}-yi{O*X>W_ne1$;97+JXJYW!-A;ok(GTvmS({5#;2%j!P@ z|6%y#XN9L>*)?K$FNW<*1S-- zKAAqc_bK&VR-gTc4}edmzb#O|%j&bg@iFkp^eY8?m(^$ghb_1XXZO88{@?)_J?%ye0O_Lsj6KAFCI{Z`*)_1VAvUijp) z`s|Ot!V0_pkm>getiQ`zKl|@*0H0h|pZ)!}gHNX4J5ayNTK`us*$lnmlj-*e_%5r@ z@deW1lj$!G_%5r@@d$2&Pp02D;Jd6o$1hk2pIlb|npbQE&%r0t-xa9eWv#!)=Inok~M#G`FF23>btCd zBlu0>lj*zPU#jo2`j^0O51&jQm;ci9m&@uWz)yltroT>KNYF^@cUgUoUvU+DvL@;J z50HNi^j%hez^gWW0(>(4k@`XceV5gLev?hV6F!;#qJZzR`U5vx|6%xK`ju^RY5gv% z&+$5*hfk(|Ea1DW{*|xW3?IQK)BiT$yR3fv7Mo!|d@_Cae3dLST~_}#_*I^@`!AWk zd%jZNW%YN!Zv>xAe@|ffT~>eX8#Y6G_++f8b4M7Q!R-J3dNBLH zp95z9_YVliVcTi+LV(}a{Bm>1{>{G%r2i4%%Ii)p@5}&SB&@$*W&h)S1L@ajdR6Hk z1HV7b2M-6|2rdRM0kgkp-5)Y_f)MT1cK$wY}a3ZLrxMUKDK<|Vtok+o<&Uh1O^ zW!>Lg*8TPRFKmV!_+HKAHXvRxkBkR)6w0 zHbbqK?e-(nm$y}ZP}b#lS^bu~ZTea8$@D||LV`x>yR1IPW4jbSS@Y}qkJc9wG*aJX z^*MgqH27rAuYR`tYoPD4`hR_A(^tVK)5q;?sqeD-n{h+?9(*$WCvEYizRT(t;)eQr z_+e^_5g&`9fdS$&RAxC=g6ll1sWl79{KT~?pt z8Ah+S`wy9ZOO++icUgUof7oQb^~v+KnmKU4BBv=Bbk_4e}p zHpe1K*W;BeFa7OR3k4|a`ns&`l?MOm4b~@Xe%;<~{!{ry@HfIIm(`yM|8w}{vieKl z{|=u_zfNHNUDowq4L@e1U4L>}{deHkgHNXa-`ejR_~*kXm(@Q4zZZORS^dffYy)M% zCzsW43jZefW_l|8hmnD{hQ$Lgiogb-?smJ z_`kp>m(_n9enq(v)Z?FA7XP2lKTV`O_x#gZ_*Cbg^{D@T)K6yp4FboX%ewtIe(i4f zWcn2YzRT)=hx+3;+4U#We>32_tUkxf9SomLe{R5cS^eIJY=$S{lj;Ar?LQp;Yw*eR z-TggTX1c8PPlEpid@}uO0?Y5R`X9nS0G~{Mdcb#C{i_e#3>9Cq?N6p33EOmKU4EC< z=lH}8;gjhf4b<`$8Cmw z@X7Q$2Yi>+=lIiE@X7Su`#W8Jm(}NZ)pOyK>0cbE-(~eVzV!?6$@KdMe3#Ydc-Zg5 zC)2++;Jd6o$It!+KAC>yfbX*U9B;eE>vsPk)9)VeT~?ptb6*diOg}N;yR1IP^L_w6 znSRTF@3Q(F|9c&LGW|&b-(~eVUU>B_cKylp7YBTo)#v!)SHUOKPYC!ftIzSspMp=O zpAqoMZ%Kar{F38geh%h%n7@EI9;PQBG-!T~hglQM@i5N@b3Dw>V2+2`7tHZ6hl4pD zW+9m4Vcsenhh^7jPJkB$_^|*#9pDWC*7o_Q`;T`ef2LFaXTqnt|0u=>NIl-P+n>z# zFF_f~$ue4Uqg-@p6%1=G+-wS^nd@}vv0pDfy`$TC@X$SaZ`bmE3 ziS>6`{dw@;g-@p6BjCHN{wMHH-)h^BO#i>#zwLwH1U{Mm!a)5lYyH!sHK&XN2%k*< zvViZh`kUboflsEN7w}zHze9}Xl+RJ&lj*zno5?cMW%c{QpA4T|RzC~=ZScuu_5THb z34C%{{k!3>hEJy7KhS-v8S|5Ny6`YQsy%jz${05C`3lj*zH8*P7=)&CTJ{M&Z_ zCDR`ssNZGvJ6F)0GR_`+GW{Gs^~CY#vigt0e-b{K{=R_kvikEYYEHQh!za_fIpDjj zey!6qr!3z)cKu6P<~5i9Cp1xl=1P`{%j&O(Uk^T6^Q#{({~GAW`(#;tQ%NWC93p%& z{Sup8>btCdNoAX134AjBWWV$i^}DS8pYZp?C)4j3@Lg8FO%=^4>$%OgADO{ScVreXj;{yze)J<4~7I9|TyJ=b!F(_DcRt$Nx+CRQEe`vA+55+Vv%K zegE6_>Jj+U;FIZB!ZIjpd%LXdy#oHd@X7SA4)`vsUj-emu7OXc|7^f_S^W+0-+@o2 zpB?aBR{xySHK%-T1fNX5U%+=+{Ymg+ci8qP(@zNaE~~!|eh>I$`tbqZW%ZB2p8}su ze|W%mS^cYOXij5ZflsDC)lWTfzHwRoFX4X;pG@Bid|u+R`aj_ZYmxVC`;qAn3Dobh z`rT@4PI2Lr>AUxL$uiSr^=HDr3O<>>`}u(SE~~!@ej$7^{p_$^0cG`FR=-s}O_BZ$ z;FEQ3bNP4gZ`F5M{Q~&U!Y9*jsf9~WR^Mgy7sG!CKAFCIeplaR^?NqZoO0fN-)=uL zefRpLzRT(_fS(GVOy9jesPD4+8{yvupG@DqKB!OrK=SMPK0aM@%Ji2|y7(ThI{?+g+erVU9On;2Nkf4z+zsp+x zmPR&1Q}|?^tL?Wz{xvA8@3Q(c8*7UE&K^El=c?b;CYSmytN&)4%`g-`nZDazTEENc ze+hpKd@}tDbm1f@tM9V&ktAB1& z%_;pv!za_fIpDjjehK`jkL>m*({CK`T~_}s_;K*b^sfu}E~}r|OmoWTZt%(Uy9Tab zE~|g*nbsc&pG?1YpnjLtUkpD3KAHZIfbX*Uhu{~%C)0QLw`7^=vih-SX-?^P9X`3N zena>R;FIag$8>&B*7{x6`oDu;0-sFZZ7=m*R{t3Mb@0jbs|4zIS^bJ>*KPPcRk9xALWtP{vYM7(t;$gJeRe+^IO^s9X_?oN7lJ|e*0Wy z3G`i7ztXwZ9{`_B-@PBw^>JDKj_^moC)2;mR$p4b%j(aAKOR1r{@Q@=vif~mX-?^9 z1U{MmvjN{__5X(NeP-LQl*QBbn-TC`R)6|=w*JQO$*liyz;{{w>vbZbD||A2_j-~n zGhJ3S1_O+wz$eqcFHpbB>OTNK3qF~?`~8*H@3Q*e!M_bYnZCQfsPD4+)!JxI`CJS> znf`D;^~C<`vikY(EAF)0k4*oPfbX*UCGcN`Po|$7@Lg8_Px!HNVCnrSnSOl0cUk?; zZ8fL-t_nVxetSRl#QM9eelGlKU)cJ|^t%Lnm;LpJ{{#FIF#QqwLV`xgGI3e`Di_!c z9lo^nlXb2hKTG6agR=TA`}M>B5`GDozPr5YyR80?$e+2()=#G2Q!AICtiH?Yw`;E{ z(*C=wPu97*{8{p^L0Ns5)xQV+`CnO|tohZyIPm_~W%YMls5#|#@bJm>-S@Lvzsu^^ z>7+U3Ip(iz{bc$De(H(kcUk>e@V|ghrth}5*6*_VTi|c}#@0`!zd2ApdAH>Ezn@Ll zoW}eHE&*5AZPV9*8-VwM&j;7U4%rRd96Siz37oB5NzOM@ZGATg$N4qe$*r0$?_c-h z{p*9|5}SVoIQB`)8^Lj4o%>Jkci)%%nNEGXg-`W)<(!Lb`KjO9_9W}v=JMYFWhm?R za9Ov|9HU4AnCJbfWSBVB%%wf+tl+YGJXlXb4H z{|5Qjpsc>j>i-763w*NXSAUxPYfx6-W%aMSL{nrOD)?lbtG?Vu`axNJm(?G5siw$v z2|iips{fQGN>EncW%c<$-8=Bf^y4Ip2KsS6Syn#|59IBEPp0p_ztQ?#R=)%M(D$;u z4wu!x9DW1%WcvN|g#?YXewVfWg_qe3t>BY&uD0LJ@~=TzeV5g*7q2ODKLwwxbJee| zi4v66cUk>&;pf07)5qnp)OT6^tGa4V=_d(3nf?Ml^+f$HtA7yw9q`HY>jZq4)vwr1 zbINnO@X7RZY;x)HyR80%?l!{?_+-(~d&C1_5$ulm8(Po|$3sNZGv?}I-aKAFCI|El%7to|nW*TW~%ckjQ|cUk>w z5;dpv`}w0?elmUc`m4Un>Mw@B06v-ib%FJFS^e5cnp1wK^OLQgOh4XFJ+c3~to~s5 zYv7aVyUTm3<)06K)?QmbnZDaz>XVmCe!ZXQiR=A3a5i`wcoO();W(^|AN_nXHwy42 z!g_zu3D^5x;Qrt%!P#ZJ9~dq9GoAV;3!mzKpmh&jb7Ovx^yc!CJZ#^IYnP^LE&w!DzALjJWp_BXl-%;zQL<3&H6&p*oM^_kDJMvLqFvYs01g86x# zehj4P{C-0(1Iqlq;%YEIe;W&C|DQL4`Tfd#Fh9?F1YE6|t$z)ezyE&=%;%AIfjJ)H zL2#oD){n>r(dFakU1xy#{rq`g_HVAAi)()V-f|Fl>@Hhg7MSVd;29|_LsGSK5mF!1GB&CkHPG}`4E`>A=i*&OWU_sGh1IvFn^za37Ee(91P~~ z|FXdxKVcG>_kT0N9G_t!nBzS>2WJ00TflstcPE(rYwiQHzn-WlyZr2*xF(q2*R%rj z`TA~Pex9BJu5y-L|4cBSFT4rN=LHvn`TXDG-~{a7uYlPf)u&+gPxuR%{S8E-?eg>c ziJD-J2hs+dfDd5$fv1A61+)LcX<+`|=3em2I3GO;-qp&k?~CAP^+YJ)4e;6)mOlb- zga0jf^SL(tFt`LK>~M@-A3h)07|id#E&}uWxKuEoN6ZED_eN8|d|vM!FrPnt0?hF@ zHiG$l+9zN>?{*l>@k(Q2?eg;btvX=7e{2Wd*we0WPjEEOFPY%evHiz^`F!UzFrRn5 z2h8W6o&j_G)s0~G$M!y${XHK5v;XC)73}h}|FWiFeqY)ie4vM2{(j(<;1OVczdIhx z@nmiRvwzD+!Tdh)c`(0U{s6qYudQz{_@jQ7qbl0v-88^*Bk-DmmOFx9A7r^VnEi`g z3BGc$O&O&c{7u2^ z-@QGU-$x{Y`F?&dnD5WWfH{87zrcL|Iv33T^Ou78`|+p2{5|sPVD^{)HMm2Joa7}O z1ZRPxD%thn@2SrKb3B@s;PH6F&$3~op{3=0;7iW2d<@*Zh2@G>?fRs)vRoJ3`CQ8_zB z`&&*1cft8+6nIpsP5&2oXo}^#!R>LrdKMgw^V1gaHu&FyZ$bV)z*F1U@?xvo<>h!M z4Z-~V)dgVwo+<(SXdmle3FhZ#W5LT3Z2BB9zppI;H$nYdz%6h*?FRGrtI?<1<>Pqm z4Z!=7Z229*bvs+`0lo|8j|}kdXut8`)B!gCY%s?oTLNZ({jUkjk!lZCQML#8rvU#I z;A%Ba_Rk4$Ps?(bX2Vd+a@T3Y;{pC5z%6U~<(KA92=LVbek{O;0vs=ISY>5P%bOkG zF9LjS?UVBt1^A@^*FEF^WA8lxn>d!oVY$*<=-rgiu_d`v-DF$1DV8x{ijd{AEi6k$ z#RUj0Kxm-^2rZ!|^xh%#7D@`egc4dv=)ESuH@kZ$o$e&r7y|G2|HOM2dHe3{?Ck99 z?2L8(7C1cE++GMLJ%baT$O$jxlwZjSZy@>2@ZHM^|3bp%_W$CfKjEa81VJtvKJ__a ze@CC!E6x59frZbHWQb;jNtTFP!ixPWTT_ z_zoxhgcE+n347GChF5t`xH>27#R)g#gvFe29pG>3!dDNz`tW(d*8skT@HK+3F?^rG zhwfyX!Pgu<#G|!@uN8c);q!*i2R z96kwrk?=*q7Y&~jzE1GPz!wW2;`!p?OMve)_!8lh!jGa__`1QD0$+Fd zdcfBczFzPt;Oh+^;ulllQ^A)89|d1Jd>Qa%!Uz9Cn!>LbK7aVa;ERAy2A>)}C%mlT zux)>a;RFWnc=^IdOa<1yvcC)<}wk0TK-{R?kU>7^*;S)a$aWizR4P<_PGQ zPD9|sbjGALhN|@{y)vBvpAMqvL8zIj3`ddCIwLe;?k>d0G$t4q6Qid9KvvTkj-w(q z>WoZdtWK9hH;QAWT7yw(=^KuVQ|81f3n+TdNofRQb~%||m&yzX7a}OY&O%}&`E;B~ zZ_w#2(2Af^O&L*?G2EorQ_L9R0cl8foD6UTvH)8sSh3v?5jM zw6Kb^<(U*kqavLWt4yUdbhjaIyeT`CK@pTAA+-;sGSWzhBCIA4!by6i)}S$|V6r2W z`m8V=jTjOw0#+noEl?FwKZ#a>LPq=Fo}+bAhkX)lH3w=_{Z{B_>v`&d{FXsXBVDq9`o}5>2+rw9%k~<%h^8ARtiq zFd!~zhA53LRcS8DOHPoJrnw7Os!i8fQVLWWij5zTn}#6*mZfnNnQAVELiDCW7oc|u zI;6JBnQNVx%Swgitp?!1!m{24P(83Ys$j4MXiWf~u=>KJaJD>L$dID}f|$muPNGrf z7^t))HAA)_He(j1BbxIc4$7{m}y>Y zx-^E4kOb0wONGWv_9{ntFsUItO_DAe*c6RrU?gw2Qlm*#sFl{uv zG!#?HKvRt!idf$qfC3p3 zE8dzaVWumI((9FKZP#uoBzGbJj-Ze=VkH8r59?IVbe16y28JJHGB9jBrYbZDnKXoc zp(+&|4wwUwIRysGRLOLNG-zQqZKt!T9a9@%rCh5{PiLl(i3i|e{DI|SnS(@FDrzGF zoB@+Wrg?l+Aw<#~1(z!vDzI!btjJg; zoVjSCilWT`WU7$@Bcjh`crM5irB~);!jXV=(uG)pH-N3FR-6H(Fmq=)JV7MJ4+hNU zky&pHcA}Y$1ZuI)&uk=?1idm>ZKTiG=2*`5Vvc7PC=dxW!<^RHn~%9jB4tqbgZ#0u ztus{9oS39GG9+7`2`3+fD0HQnCL_orv{tw;S7)0va9Uut06J?9rOaYe#w2AH%EI00 zI&0C&VQ&kawR(FrhE#3IV2j3BQu$PdmBynpmNY&paoc6n8cR7Ywdt%iSc9)~P8z@o zlM;keR>vlKPc=xj3^p(^G93t-(h^KG8OJ+gk`9q@I8G>1!~qH{p-KjJ0ac%r31WjZ zxiXzH7RX{$a-jkiXLzJpv9SZ5o7agB!QM$7&E!aiq6_RIBY2Z_277kdLADmH~K0RB9S;%X;7;a1}v43s^aAk zrvlI^;Dib2DOE`%5El%rDB`B!oCXn+K$R{Voy#TJ*)U9yzga323l)l7d>m0g&6EOi zX6v-l*i?~3g3^qcdR?AEg9oI5eNU&C0t_!wJ-YAV4=!d}szJu{4v_-S<-0`{RDK`eg77GVMAUk*gB}utxj>eLd94~@Zr^?S)rmAyAqCogtqcj*4Mi5#k z)F9!I*vN(!szGfhr>$nvG&0-?Z62Ce1vEhEjS9UHcm!C^{U|*MQcy3H3Yw5m3MyYk z(I-MW#Yp9=fzXmrDiUiefaIuv?vW@Ux*CN^OXcSPeL;r@5}ghQU4Csja5zxpk`pMC z6Vo0Pzyt#Qk&&OT$N{EPrv(abEKuYMQ7lN0RapvEW|ksdsYZmJ6$26oJ#N~lGr_V2 z=31GG*?feENGb>9Ri)8^07VUHX&Pl(8vey`D1vS~O{0S=3>0A~0GOrI>FFdkD?Bok zp|}xLy3(Wpz+{6I6k0RrG$tdZFk<-(jzfQ9VvFVzFy~fh`ga}E1pFoiVB55P=oH+m?*uWGSl+ge{R>OJU5}8F6C_tzH_-2VSP#RV- z1G^Zi$f^;DApJ5h%>kT^mQKJHgu9D=QFq}Nh&KM!G6`BHMX$;PutFC2zd(`8RGC(w zNrPBZsscF5G&DPk6j1=aL`v&pG8pMoRk~bZ`5&5JSQFX|z&1cI^QyvS15sIe|0abo zo{Rl?@tEaBXoSj%MJSyVpe5(%D8WlZ*E(8LjyWx!>`1=ZAhhPwf+FtD5}8PdnnygC z!U)y)Y2dUc1?qwJaz6#C*)K<_)=LpZkq1FE{Ch8(Vz>xZ9;`KKG&x4#A)sD*6OI*$ zP=A1rM!b?NS4Iz2w#O<0w*t(hXamCBpL)8G^KQZ0|;{?m5DKoF_TUU(^Wcs8X7%D zbIdEr#R#?xWMf4^Xj&{qfY(zKy2(p|0|6vqeBq@*v2^>zAPJVFBE?oQfV<5kXbqAO zS%YH1yiVpqS7d56-5X9ily#U6z0HL_$I#od03wd63%ECP-PAvVESnqij80~PX61zLb)O$GvjVBQ#3roTc8 zX@D?+Y2-2wp(UWR6;_5SWVzM|`M*9IzjPqQXy61ayrm6ewmVK(eTgwige#*@ECg_P z?%3yqBC}W$l?HKWK==qFMX&2vJBJf{X9!>zElG&){GZ1vF+iTm1|g7&0xnA37w9P3 z(v|uQ*c$>Bof2aZTGIOhplL8dMKotpykqcbav>9!O6D#iCjmHEHU<4(M_5D@5Y8&7 zzHog(FgFpSC_Tptv_atGtrRUrlE&aQuvR!-Dvt#Knz5H`?Emvfg3wq6H+M$8No6GC zu#XrDk&s3t*z7SmwMDA{tHc0N^UkWk)D5Z!VFDp~pAk%xAXNFkg((0nP*Oo>9gGr6 zBO%#5TyTIrfFpn@@PF14aST^X`#7x7d)l`UIy;`P0NA7=$b2z;4U3Zl8ME4`NHrm` zzf|mJ%}K~jspuLIG%OOK4K|yEj<*sJ*koq|dkS!ficJU$jfGDa8yN+z<`fjAO|ik1niVA zeDHP(7IEBmN*8I!c!3dFHD}aTy(XtoMy4HQQip-8f=ZK-1!}82!t+=WKKwGpm~)%s zLh-g1hy8B8<0wUWLiTyqlnL0SAg15>E$mvTras_QU@(^&ef2=}5$$jGXPKIsxfr>nr@g*;e+k({E%Y~bV0 zGxzf5nT{0)z-6LY7n0k1v5;NDs{3qMN9fqu$SK^?In;TpbeusHi04^qNC2!MOBe?3 zc=ftG9zP-kAs7B~(Cz_>Pf!5gzN2eLLLo4olC@1(CsKqbHnByo?D1Mb41kNl zX8GfmnSyu)GYp=>5qpOhA}-5hH^89`*fqH?&9N1|E{uaQprpi9Wv&T?d7#$`f3%Hhy1uQY^4Yw5ExJT5VmFuutVk(L>S)Q9O|^Q(ck{YL~^J zD`h4M&hmD;Ew8>XjA`Z+q;-pAQ@~Xbrb2|*C)Rk4 zg|1=gfC%q^M7;?rq%-1*(4zzLlmPbr7!_#(<6|U+*g!^O9_j5OU3$m^8woQ==JqEZ zm}1UFJ=_#P9RKb~#2aut2%n|&wHw}0XxSirvxLPv#S(4f%RPL}Ct)c^U|~0&M!aW- zqD$DMSUKj%$VDLl7b37m28n=66%;{pZ5Y2H5B;i%C^?bhegG!m6pab;u1I;D0TUlI zwjjd;Odm}jtX4&)FF^yWe&?jfpm(g5U@#I5p~{kUQ15%Fk;ZxkAu_EcTA8#w%f|HD z$ce6a;F<_)Sb;{7jY97QCy=(9ArG#kbS9%h1$wEVI;f|GbrJxH0^P-0N$>!d67j_i zt4q90#qS%m3AfP%VTtrF$Vv*z?aupYDMCzhnAXcq4Yjjml4_Vij)0SyYtAKa8at=R zUk*wJ=64&EUKEr8hwdEwni1)2fa0e?B8$ug{XlfGmc^u@+huEkXXm6?I;*!T2NXE? zm(L>q{2Wa-l0D;xj`)_J)p_fCXCfD6o-1&K5#-p$B*NhfJzO&%V69U*2LtO)qXouP zLu9n%h8!MQgkp6d^2S9^2nRm+M}l?@Nki0}(U;_nRwO3J6>_Sxo+bbx3;aYxfk-^) zccLvJRFzK3B07!$87uNd@sUbeBJr;KBdiXxh2Z^*)iSM*ZrwVW305xaWDZR!eB9Pl zUW6A9J;DSnEe3km5fU*Bkp+?+mF_g2$XJm-twqeVN4O9S4w7P?16+V$6l^f)oR4G| zAcw?@gH;Yv;f)6DzN{2d4zU58as;0k_JLiFg=wTB^aj+-4v5A0IWF(1E-n=>3X+>! zV%9T|DBMZgi6RGyW|Cv8T87Gq@b(PLMS`?qN#`*igPtDXI2wmVSU6;kh35ziAA@)5 zSX~AgZWpCq3*?3_MOGtO{lEi|EC$?+Sy+i*_;S*4opiDANc+XC(?}ns2J_^zrWeV| z5Vt_{4x|fsOynsC-3FsjMba7I&`+h9L^gJQW}-|KyevYps{$DTClf?#pBxGh+?ZG! znds9!lLNhB68Y01=HZ8g$N|Xy@t(9hv0|q@%xeDwwE~tZwX|@0V8%0=B@dvP3J~fF}U)4E0=q>Sc?6m}4}3d~Ie35v|>PFBR}RPpy@*5>c8Lgo#uw`E{OK(A7Y_!8h- zu(nL`+rmtY4F5M5v=IQ#)=DMsp#{*cv#nVIDz|7PzVCl1eaKKOqao8yH|Y0YHfX0! z|Npp6ZnL5w<^mo#2n=S$e*kA|lp#PC1C)XNg0qjgWwjP*d7+1m?;i@OR#n z>cOTQ45w&Z!t@0uh`Ee1Yp?@uj>ofpx=Z4YRpZ?sY$-TUnfHXp+b0MG>1v z>1k~NGG`1}WFjmIz;Ddpw!ks>980s$=zTP1RFZV$={T9gPa_lS9CdK+wwbWzDVaw{2>fiVy`~%texk1P0oc2&^Q9y5FoET9pugc$6Ez)-JBB7z}qWrZ<@FPNJ=_D8hLH0R7 zc9TvxF}y4-u|--*wwt$7iHYY)tIYxgTRIN5Yvdst4_R!Nd#5W}3#{k~Ed*cfbfK`t zM+?S4p9m}}z?0K3Y(bHbe;yrK=u2v4n+6?pDY)#BpRfeOvGW~#F%1u81EQ> z&Qq9ArJn_%V*zF;%}h-Uu(jl-gvYz$#?bYJuYoeciv-*%e({H%pFxOy_QEgHAktSM z#hfubI(GJY61p!Y&V3|71s zFc?zk35-+$|7Q&h$=C3cA+X$tY`H4HiY%z4lD4D{-_ztKDXc9yFhD8__#M8I6QNgf zL~v#%nh5gDdmlCPh#B(Oc+*HvA3SO->}_08diu_w$LNNsFinUV(bZdED>~6*LnsRJ z5=@GrlWphOTTzBZ+f@Ouika7B_(7WGEqGzTWnmGzt-x5M#}>hgi8mi@adCkQl*k@v zKUN=$FkQj6)&fl=VJ)zxi&?1r!O)mf6kh86>}l`3x(K6XA#8k!P-mkWUdw?YY`a<> z_|%R~1oAjWE6W1(!o~a_qWgr4m=d6$@!8Aj__~)t z(L%uNU>AqS5Jg0K)P~)8DFXizXkpw~JPcB~LXYvym%X;wHhBMShleR-;DyrzHGgNs zAhAsf3Te*KcCCiZ8lk)yRpAf*R_&lWh3(RX^zB_q2*MM@8igX05o{{Sm>?mluMX%# zxLAtD4Etyv*k8mus8mLj!z4)vIf5x{s9d2=mv&Vu4SIa5X;6UH8CZ&f_hETp?1;7T zBI^|Xps8r040=(38Zt6Z#gXM*q%?p*%&(gAc|60E1-O)v$V9E^$7AwlteMzG~# zwFeY=bbP5hbMwS3Qq&u33m<68{=+5pu2XJihocqpXf)^iU4y2p%$^|%0)1$Z6e&!` zbVZQDr~^wB@2c_zH!nhk6f6h9O&XZ+!NLM$%7;BooLe$vX2@Fk85d+9Z%_>Z4F682 zD!|6CGE5228jFB_Ni6L1g^PcUIu#HV8G%CM2Q^CroI!|LF&56E;~I@`5?}|(4W=|* z3VQ>8anSOQcrgAWmBm0O;j{<;M~lx2&@j&c=^%T6E+RCL(k%cQYmO5`i?Fd`wR_fT ze@8&0LBQMue*j2ZsDq?%NXrm9K+hs*Rd^niE8e*IW(K3e!)fbq3NXyCq5K5gm_S~P zh!+#YiwWk%h=lwoeoZ1VKbJ2*ir-C8nBNI8zeO>> zdS5;yeEHS;@~ijdkI|1`m!FM-`~ms%`xU_N1X#r5qDTP0U?6`U1Nn6Y^6LuZcQuG# zJ->D_f7JY%YygYjDL)&z_&xCF=kn)cQXn77f&7k&`Ct(9N9fDPBwv1uzKA#`$;tfz zTThdY$BGe5Jc+Z%>Z4T9m(HSz{$%s*^{*a6>|YN^DvL7>~xL z?~xjG7&6V70k54{o4x%&NmLR$ss-t054l%qQv$@HconAnjup2aLai z2osoEfs+?xuXv;C<@2;iVScPLU#`aaB>5dy@6rWDwL{p8YAew`DQSUnoElOGmsY~ z1XIQdkRm08e+MY>1>;A!t>6q$ia?h`X2622c;&(NHY3Pb8Q^jZ)%S%*tR|89Xy$N_MThugU#v&6#W#-Y6Pg3&&4^DagHKnq?7V@B z_#jk9PlbIVz(fx+>#X+yT5SaJNwxtkCwLs|4XYDJu=2 zjR{t?s%1-`T#*mCz#t0;y&R*-wcz9QCL3tg$7z`y^FLDKS}Ko)ft;gh5pBfUv5ow3 zpb2kMu-Js)Rk+fIA5*Edrz*79|DQJDjHnoTKS_@4==E+$+ zt0VjNAE&nlV;Z@vqkC!XqswVuA31~It4g3q&B{{5lzIy}cnR1QAMb-49~ zn)xQDcsD(WB}exy8fC!;yGCHzqwf*Sk`LC+Am$v%9RTx`kUWqix3sLBZ~N}gUIm=@ zb2c6v+AGO@_(x7TjJsX-edk+`%KAAXs+a*5@17KS3NMBU<08LI#sJ~AN&~-e*f}cg z7=GL)@gQtFw*xld#0UY+QDHh0+!&>oDY%lp z)4opZ5^?*}Y|B>)LLsSvhKd&Sg0#s0u5AnV4r(qcg>z5^&%B4(CL!WEh|(@nrof`q zw_L?e2P*I1fr?`d04u!;mNi?XR*~X#yh6+alRXAO6+|i+u9E22*`*ZN*aFv| ziiE|-pt>vC2R2du?rr7UQJpSL}lA~VExigV~4>J97?@y1LB8gz^WjOJZ~ zM1k%YxVWa-AVtc1_xVDe={b@bqm6>=3!WvleVbz$&xVMNd9Zh`D#Y@Ky<){NQDe6* z+}%RV0@)Z6j^dtNXx6hRAaPW_5U@BZS{%?gtPdx?J$US#Yl;FHJ4Fitik(u$frq`S ziU|t)oD&ZkI4dI!L57v=mnBQ|?I*^5jfDW%e!(KZ7=w-(7!mW>Ca#5p#CEyjg2Q%g zg@D3#A;)0g%4L1|Z!i9bU$`LFugDJ*SfV=+U0Q19zPPFL)ac1@I?QAa|rZ-FXI&|q~3%T-WdgJMpdu)I@T;(xYo9f1K97_ z->VueP#5wV17wR%|3F1s{AZF5Cy*F)*9W$; zwFZqz1@A^8l=`eN9dj`NX>yikKFZ5HIHN@ZkszgwP-jzG16+a7-H4-<2Iw(ek|l9N z{-geT@Uj|Yztmwi5@d9PWm3q786qa<$8fF1d-nN}UWlUUmC}zSKiHx$H)w0#WN+bS z4E3JebTL)Z$WCs$ERi7Y#BvlSh9lc2nzl?L=l~Si9~m2du(p}o8P*n6?A?ZMg@x%L zOca+=@*m~H3qAaLhW!W@^)?zFgnqD@#*NXW54nj@D>ZOiOP&hSR79R>GJ-dFtyLtp zfR4xz+(Drm7I4j|iQOG|~tp5GY^ zGQ@A|ErUXjm@Ogf%>#$8@=^U} zH!}bIF3M`o7B#l^sbjsRVyl~G1AH|1&upp=w%@`XCce{2!p@UNObtJtA4UXcg6hme zX=YDydS=AWA325<@SQvH_5=GW+dc?RDV}FWGzr)NBTxtW^*WgiWE=%i2I6s++X zBdQe5AzezRm&(ip%c>FNi^-f~({ByVfK(yuI)X%vfes7y31z07_DXzo?~tgsFnidK zBtwTS1o(aWjKnib_%;F@OEUyaq1LV<&6*zA`=oW6EjN;=en6VI0%-)Z;g}d#p_Wq_ zT%|ItqXHJJ2rEFoCozU$5hLP7ti4fk^UKv4aM23KD>KHBnk`6V<+l)dJ}!%}^IH3q7QHven;(atR4B-+Umq}cgLEy;{zI+g#9T1F z7a5#wTmMd1pxB6`c{<2N3AR>AyqY>)fjV7*>hx*Erycu}g*gNiPQ!{J{r+z!-Fylq$k%RY~3|0%b!Fh zPsDgkB_GgL@Vm3@;3@^4C#sDKu)hd~=B3=p=6aLG&Tkw(iA7*QYnZ!fi1_s1mhEIe zjM@K%JxVl<@yc9v2G;)lU>69iCM~j)NVVQzgp^RV`Lfg)57(#cC`46Q`4ZBR?Ja`! zC<)osB-yzs>`IWx88>4&bz}AI$T+zK%-@0+6;dPQqaTh^X>=O>d^ z5j&+&ioH@$BU6o~S5UxVWUSH{%e(=?REx=N?thd_&T7&EENIR;3E!g=5&Q?k0=hX{ zn+@zO|6?w=(Mo~&z~)k!jfu6X6;D0Jo=_V#2GCJasJT!hw3nmP!+R=DJkkfSJYK{& zZ0Q=x3)2k3D<%%TETc6ELREcDYCT-p5j()L4+Rlo~ESF-G7P5jyBKRl2;+`S-#yM_%(3Lkl9^0+3Jw}CX~@w%h94;vt4w9KSI7v~*85N@de4S% zXKfBAMh<#?6gVwHJ`reaM*B5v^qJ9Mp&T3JhudUkKv>ZQ8|P~RuAWKB5aWOITQ3XLWc)qrEP;|7C{w;jc>gy*;r$i<;r5x z)6>;*ESvPjuU{+~xe7WsH_1v~#6VV_BSBm1r;w4o^BOGtX_3RFf)fjQZ^e7R<*>%W zJeb?0GKD~iH%QzA>z7xBRAHf2XvOn}R7h#Zub_}n>g}s61oYhfnZIA!a+$>6#cjDv z0!cvOJ~|LF0rI1QD`6laA8dzYHEB82OTamXfl324Ez6a6c!5eou{Dty8gFqe!jL0E z8OergNhPt243-;jc@Az#vD9a0+rU)BlAqqDi%bS>7cUZxuwB&FR*1v_8g)h{9Qt)R z%!sfq0QgbFL=$6XgwB%7GAHRo!3L96OKg!Sq3s@Wc2b&&ury7!9)CG@bdsu6Wg#5U zb3D(#!->Ea&9>cB9ueXZ5!>ZR3x&{F8wAaEZH3S=+l3sHFD|9AWhO5GD28QHuq->4 z?|}x93~L|4A4W&f(xxpbkX>y<)Lpqc+XS94C`QkgCJH%}GK>A{ftHpd8&%-hDvPE< zbS&{+gw=FuN<$P*Njxo0z$*)LEfKmz3hD<3O0?S}ngJxrIkY!TQW0=+$!fjPq|`vm zur^eBb&f?;1F7-?aKx0&=nwrTs*wmv&=L$U-9Q?mW58Dzu%=*&oh7$NNs@e{Ua2xh zsx?$7Xue_HCTX# zV+aMYFKo8Id34nU@vL_!v?E;X-W1-X#DgDesih4y?F*FFszo40!?U``VK9=)P=i$` z*rmv$G_!N-_ty#R;~IGZM*X0hm1xsGl0|$2Ibo4YBf2+MyVA!|ThhRx(6aF9ev#FW z4k`4)r{fdA6)_D?n*qe&FQ+|ZHahz3VK>nZ-vklJdtEvym0H?&=PT49$-#|JXC z8kh%!El7hMS*}MEg2c#`xs)ZwJf?Tp*9qSLCkkO4=EJ^g=eL**KcEHZAFOsecC5t; zc@WDwF(MwZsUlnis05_JpALMyLk3J;SQsM`B9F!3dQP34BPDvR^n8VfDUicpHf6%M zlQx90_D64%<{?tbshLn$2SZnbzhg{pSuW!PV93aivcn;Rr({$)YsgG**<=`vjMF7N zSVzDFYLD{Rs2NQl-@!MJ?7nw6ysKeqv!8FNLM~;iYas{hMlhub=KJBAM@1>%nuF3K z=ZTcwD8=UBX{dth!Zef(d}k9g*SSdw*uiW7sVLwV`zsU_xWtC*D}_m`2A7kHEUG}E z)MwxwxKkq9bIFQf?)VfUD1-Z|hAtu{QM6avuvkw|UlB~!7p14~40=2cNg~hT^xI&o z2-FQ=%mxNngiFazj7ci)1o-3X(9#f#Xt07n6OoIe0+%)Oh!EqM(PK@MV&ct5TU=b= z0wuBs+K<)8B1~7Xt+hZCNmvW4>0&UCKbQ}`r@iy)!Ww0;x){R7e>!V9KBC9z+~Y9c zUVyFZEE^Y9Hlp~do3=en16#-U%*^(Z`yL&=B94qcbb5c7$NB6QZ5`NUB79B;`BEyl zxdI$yGa@VnK{KC-w^zh(kOLY%IPAwev9u4t5^cOSp!SvA$PS$bC z3@x|?Qza|)YL+HQ1eKAbH^E~d_=Cy9jLIB=Q&BbxYft>}a>Jp90xh{nBE#kT4-dpy z!owu8TzD)?w*;4BjFVw}cId3t!0Exd30;;c$D9d}!d?R+f7%H<^S(&}J`BxB#L&D# z@W=sM2#(c?NJSk^WDywRK+8#h#T5GiQyhp;(m@}QmlHcoaUlaQe1lQ*SuG3_>%HZj z4|PSHC`SyW8rVlf6wvCYi+k;@u( z^TbW0v~UU93NeH`wDJ^>bs8FX%yDF6iJvs-d4GP#HM1czM zB%G(zr?FVUP{2EXxIh5U@On`I%7}PHy$O`2pcX0Aj6uxsj`}Um}gn?16s5~9*yRl&&RNLaV{6b z=RCwV?h3J8kR-W10*Wv#DcNDF)KO||ksZn-`#o^#!yc_a3{%2x5i=!VbO)O~QkabC ziXeqirw|1s#=Mh=T>{EvLWLAq8WH>#ksn|v;1_lc#}_3$^W_X|@UvmteL{?rNTdQ^ zvCLw_EwcF{)N}xIlBZJ@pi80*Lx=bxEc+zZs`m{-;-plVE!vZ_B7-s-Kqx?b>al1A z65P=1TmlC}@=!pUE``%RpD58n?|6B*LMn@aPJ-MA{*O@6YKCBa!4w7Ao1r2?gPtL9 zpbaymqGt$xt@d?}mTnQNHUkSp+RkcjYIwmHGcu?-^+_-cM1feb`a%GN4J7sSAoDIRv@Sde|lCF zxS*8s0?3Qvy#%fv0um>f1_{04gLpw3f!mB#Ra^vR;cw<2#r(nhbs21lDvKMyD)WL^ zS+rk#q$F4zAy~M$W!KX`m1>^!nP}be(v8;rR3o~!rI6*XH&^~Rd)AbmhAoYR-=c*zi8PrymHgUZz}o@@eX*IJgrl& zsSP3u4s09q{fO#KQd))Fo}ak&af6NW-lxtU5=M8F`ea{kUE;xo$fc_T6RzDWy)3n7 zZm9d4TNgiB+~!*E?KKyStbTdYC#t6x&M!UoEb-;*WqsopOZ5lVlsbRw_s`B5LX5tV zCmwt6pWos^PP?qZzphzRw(2hox3I z>e{X{>7|5QWc6fw8oxH|QGVNEozi#Y<_cHJt=PD1K<(g&%aWOG7EYMydrhZ{NFUd_ z|Cw_0+)Moa#Z14wD=salr`l6Z-s;$|nTv+$ZiLh-`Nua)OrOk}bFYDMX1zvV=Ra@W zu++4p=z_0y8;_L_)glmMy&?pULWm0GGpOCJ-bi% zS=%~w@~?T1WWwZ%wY!!pH)h8AR&y5Y^X(t{z$NoW%VpI~FAi%D{`pKf!c;zfYv*t3 zf74&EvSs(B%|l*K-}@#!ez$$JaM#j%=(h}vDHpH#3A{a%LDL=k%{lI4Gikhy&OG^HH zRwJd$gL!vmUJTp*WS{HoJ0;3|y0mSF)fsmyZs>RJ+f`#LcY9u|%Za$HUp#K4Iui8r z=dOzmO&a4p_0AVpK95*{LE>G)h9o235jHllWIJG0-LC8042mD!O zQAWpaMy$^}u&nvzC(689s?f_J2uUgJ2`>e<9YNw-rJ}Hsq zw3VHhxc{4p_YQsbN9XmAA1;~RYW(ad8RiO zN>eKK$ez~n%ihi7zY}(TadxN6rD?i|AHGkGA6MyVyQ9DCuD5#Y^O?6cMXTB#Un86v zIXP;0xc|e`r3dE^2%TOgbjzCM-^TvBD|q{?otN}=)`YFODXexOd+@W9F{eJC8C0?N zmvx#{>-39X{4C|4*=~|HwQq+;U0=W8!pw0`zG<~w_@w!ZHOW55hmGpip-(&YP1pNw z;kRzI(%uPM+R#vcvhVh84gVNGR$9X9eftUOM>C(@S6V8MM5Mm+`^T zJvCbugnl-z#k^O4Kdtk_r`cNhFV|C-4_daSt8V{|^quafj~>l(P3Y?JX27}u{f7U( zZA|p2RtuLd8r8HQbaK5XXLe5>KQZgR%k8lVSqq=tP2bl0#i9Oly1h8my@O!g=_B>8 zHYg*lb9i=}yY+oduYN7p@!5sR*|QcNE4MVGZ|v5j1%CZ6U2PkDeYomp!_WSoe7+>% zpWWx&SFDkYzAK1*L|q9`#*FxKoaT;Lu*)O$7}{rM^JR}KHxIbO4BeuwNq7Y^K;<*Bb58&bsEm1zS5;)}_wa*ucB`y!(4L{y4&Ydc^i_1AhJ^^rzc1 z_C=OZU7cOfeAxL*DSK5}BU9!`4>#Mf;(q0}BlrFCqRjB|$HsZ?OFGib#kg$lt^DnZ ze$C?i4;@{2IAf|$_7&ff_d33;bz@qOh_CPdb-m%LYg?xqyC0ajX~dn)=_%7s)*d)v z>EMHP*YDZcFK0!{`a`0~z%x@?$Ll`r*6e!YAF6w5W(;sWx?tw@=7Zvs-WYn1ocXxT zCjg%00Y!>Q?}KB~dR{)5@UrX|L*`GsezW`8?xPLQC;5c_wdG;E zh4Z4GG*Lut5(^^o-Rmvg_37azHCq3?u(6k^S5~d$D*Id}mq}V>45*nOS7QH(1>*eYfF`H!Tw(A>AIySrX z5&y^uzDr{6#hh;WY@SZ|?Tg{-eZ(y?;;(2!vg`d-dD1sgqq35!KX26U_O1qXUFEWn>E}Jy`^NZwxA~~sj6xDzH|Bhf~FJfIsM(1 z*nj`Jd3S7dR=eT1c5S-(U5(Z1>zz;fl{wU~PF%Y^Z&v$7{X5l5-mr(qrB{jCjx}Gc z+Hm%Ea)@`Ddfkuf+U~vDGrsS()sMGb8nkz;|59Do7t3!av_14ZXZYx_LGFG1XSDxn z*Y1b;OMZH^AfbAfVOe!=z5M1$KkDG|17VLldv?zpe&Si*@!xMbQ@TgZyqx3<5$A&% zwV3MdelO2!>$D2~{@Y#+5hn&LJKjw;b$YTV|6Y5GjcKd#1^V1uqABkxo`QrKX^@mR!zvVqDWzLWz4N_93 zFInliJlSi?)V>1-HEOS1_A+5s$`^GWpZlWOB-5JAt0mTdzcS?W#}SPNYdpXHNiySy zAZhZ9pL1g>WeHx-37#C$!o73Ui86PEfA}o>yM0IZ(Z3HIcx%}9;64!J1duZCY0sEe2oziz2Ug_KJGY&@XJTIvg=Wm#)P8xG3MET;U z(?ehG8kO~^RnvtHC-!Kz(D&Cx1HKV7j@ehb=dfeCqoG}g4Zm>h+$Ze@Q&n#b`Ke$; zt239hhi0_CT>eJYUDv;_?74q(smAl?zG(LQtMa>QOX^jc^I}cq?I-#)=<;L7mOn0d z)?h)uS^?)nI^Wy4>dn==<#PS^j(1m!%6{8>+MIr`E|s16soyJuPyfrO+BY*^xqJWD znMV$G{ITsS^R<+}1m4s`f4yT;o3e~*gVak^B=Yj2XLHLv>Dt+Q%(d?j_0F^5kbsWkLpe1!+e#v^A-#-!)ZTe@uFm1D7Ac01_m<|1&JKV*S$ z$b4a4n4-Gn-K)7*=~Dg9yx-0bm^QcKrGK}7*}B!ktJRZ)6;N_z7ne8g9zr+x5!Oc$ zjofPps|~Kw@`yTWa&D>DkF&n=4q5OlDsE88UP5n_p}u=l;itkza~jO4Kca4?(U{Z5 z$48~tcq5UK6*eSZ-^3>NBJwD7Tf`;M+hr=vbb$`kbSVH5|A6F(nSy!Y|NT_ ze*gF516zz;Teoz?)+wz9ZSA&cnev|!6TTL2KCz?iE?ID&2;;ol-RtN4x#U8OrcR^2 ztrbW2P1=5U=I9)1=y%nw)~Z;2RO>~*yegaDRa&;$Am6)!ezn)-F59sF$Amu?)&A~4 z&8eNrBxm^S?yzC)-Y?qR&&xLM^=|ap-5Ec)>3To@A$p>zJo2lJ~aqXdziy=4{Mj*9v~iM*gJi zJSyT~Q$vZnL;s9_k^^+$N8wPn`GgL*xUym7@!<%7FhJ-h_7{u%guVel0DS#{00h&) z4?=_rTj|#(E-qDn;<iD40Mblm!J(T`!##HTAckSe7Prse@n{3OjuCk2rCD(a9JG`uwmo8^R zM;GDPjp4sl_^$nIT)kjVIfcJC|B* z>HNN5N69QETQW9E(t;$6}?@X#R4;SH(hr$+~C0lyBczBd>b*WYlQ3eB$hP=Ey7HPmlLZ$Q( z4%uVQ>?$0xq1KSK@KiyKlmWeTS}$X!+Tf)!?^={sYJrzhTi}(W)EnV1g8|HZ8oZP$ z6_sNoWzwMxg+8qpY6JESvC~Vrg^~~Vj9?mhnqw%UAh+-M{i}- zP>v4DqQ)SnxqZm(m4n_NsG)mMCp?b;Q|Jb7&eFu>t4F}}*w*0_~*WpF}o2&yRZhs#9 z#TdEQ@u0n{cg#pAo%N>Wzugvklp0VyB)L*Oc~)-dZx?UP_jw`j(>-mc$~W&>n-Z;(Z~b1OLHXae7-}Z0KN~P;*O#5o zE}Xtu9QMzdlYM6moSV3@_O?l3jX!DeQ-!)4;=b*rIuJ9sx@^hllfPg4_eiM{fvZfW z2Ew5pfRXO0G#gVXZQ~ysF8MrVg9@=RACZMX+)bb`NE9p-`Um(2BJM^k3=#|Jpm4}c zQ7vH&&(fv7ZZc}p!&Yf7E@eww1UsS-VFy?U?rvoRtymw#LD3vm8?RVpHdx@%d%<&3 zu-K)_^lE0QpgF^{m9eU}rm#AywshHw+`?82A1ph^4A9Zp6;$dClQ*eupVj_7ukMgh z;qsO9Gw)Q}x@*Ix>&8Fibvm{lt6e*P|1Y|ulTWXhwQ7Hfr4vRkC^$B7OXzP8Ry{30 ze&WN=C$w3gvFzHLhnRZGOH}_m$*Llx8o9x%u2<$tqa=A6eW;0wKPCn3X zYM)uXwk5ypm#ey5#^ukut6a}l8NJSb#0GWjxhnC?y!IcNGQ~aV)qocJMi_H%UR&6_ z{ki0hxjqwK?d`bk+>&4J9?kgXLG&c8@4g?`y8P6%WZ1#R!=#d#&HOTZo%zMkuOK^| zA&Zv*QWs#VXp-dO;*Mt6n+XeDMl__E7oEzG!y-{A*gB2MRi_C>EEej*&)4QY@)S|W zdv@8`G^vVW)>I~W5{@%%D{L0@wv-@z+lU$#Ki8obgea>$PuNp4cbn=tlHy8Dt zvMX_Fxfc~PfBht@<-|^-p46PXM9?&>{9jiVR9s^0+WMb{a@`ogsjR)~Z~8~C2u#Tv zy6C4SscVnj2n~ro`E#|@tMgNiJi4}i&hnNgR_KB}Z}j;@w=lC@?G0-$hnSl7c-Sd0 zEAeF9^43pZl@blDvRpW{%3@c9T*E&im31x2ru?jv@0_8op8|Dd&a|c6L}ko@5-!3z z=0GVAQ3XtzeT9C&d;0qcQ-nU2RCiHBcdxFKzPqzz_ul4N^~Y@5-(~B{)4kh;k9~6O z2e+-u!(4ktM+m#q1ypIJTt)G)oIP5WcXO@fUZq-%^`l2D*uP-W@qDE)=jFp+*L^!t z*qU`lclVlcVD+aj zynXtfNbgVm2T%Sac)+ylgO06SI7mC(Fx~xL`)c>A%)D6fR8^P8`%1*DyWb)9s~v50 z>yLJ5_uG_5rSg6sK465*d;Q!NC+@6ToVi+jIP3FMxBsa5MQE=}p9Rz%UM2S5^UY^3 zc-T5SHY;V)jEOE?Pd=C({Ibe{6U(o+dHF)R*(0y?@S&mu64&(V<4+x`RHvCX#jA0^ zIp0BFt-37TI^?{#<&qt5MtJP%-z|6G;0;Sp?NC+Uw&?Dif3_a%*{O$n-L%R5$GNoM zT((`cft!9!ZxgV|APlT~aB!3^YVYHX3$}&lmDrv)VfE=(BkorUEAzMKk7u84>oa#~ z#ovTOD<1YNLra88Rdg*c8d`A+L~bxI4Ujqwt+)`P=DWJU>H=vIL3-f2`msv7xX;OQ zR|_+MRCs!{aC7(Yg#FH1O6BgQkKU2Cz-5lA`iTRsV~-B6+M?a=+}b@(?rqsg_+#BR zck^6Jru%L^w`$IhJ8M(`iIG^yTC8y7cX2IQ;n(0vE&moym@~B85#SA7;b?o4<_&dU z&HiNXqX`2!Gc6n-LK`*av6>>bit<7a^nvfr&iMcmCSVU?9AdGb*cT4HzJxvW69(d- zI7JvLsw=EbdRN8LFXTP}WMFZjB8I&yU3?+dfwj$LzQGTrOExEep})JoN%bp!wY=N9 zli7nGH2rLLCC@E8Rz~>UIHZrdc=g=g)#VJ|Uyqygyw{7ZM?z|KRID$()A%|?c3|}y z<3Hl$Qva+omaE(#e$m}E>oj6Xbj87b%7;BVRQfb0`|E#p2h{dBRpr|uk$qB^E!;9E zYG20W-%mF3P<9%<>brf_x10@GpCp)|>%74*r`EFvEqC9pHL3DnW!BG3`Pz8Z%lGWP z$}eVY@7etCCY@q#?{C=dtFgP9)EpgLW0AWqt4V(P996wZ{hww~(X*7nYZ)GH7m(O( z4wx*zUp|fh_^?dRB1brrHl?Mq)^DRa=9k(R*UEG0sBTk^Sj!=Rp|h4=;}ddP`%Tw^ z26oHsTI0rIzXJzG)#~;9nIOEvCkel`zZ2dn==GR$$_-`ilx}ycE3&$k5kCt^iBQLf7$cuxodw2fC@LjK&4=4Cf{>A^{ zHP=Y>i(1O+9($gb`d)k^a7%~37>`pkIa zYKaZ4^k1u{oV{52t5+NSlf!~^)9>6%mBtQ}w(y$i@!i-z+vk_6d9BORh9x}ubu^5f zx=6KZ#UD4bdN#jzHTBV;{R7{$_}lbdT58<#nl&q42tRpb*SF`djUOK9@o2}|CmW8R zRkzuxRqv&yeINYL8&1b1K+u1Wrh=cxc2UiKbbliUR3AjfMg;wSLVqOg_wyryeoOEp zQ{uvoy2tZs%zZY!Vn&Z+-m^B1Z@sCJ}*6bQ;mNOAwJvoo{{Zqdf@dYznnSc zD!1EKGJeJ+U2x#9{t)$o#rt;^3w1Ad#M`r_E($# ziE^Fyll!B}jXmG~spoIH5ue7E+FkoV`TUVz?P|DbOM}WY58WL->q7tTZ|2`PI)BK( z*Ke+mm0oLG`bEVBdfy*g?d_DJFC8p1UTCH*Pz+qSsLF52Ym+rU+_=AY#fzI><7)f_ z_ev$>Ml}g5==HSsRY}*m|9mFx^>wGX&G$|i*8lF_|7zmw!}DwQT$VLWGwaH2W9x_x zmy{h!NCx_unoJ9sX_|FFcqe8@-grVLxw3wnMDgRw`b*h6t_2)>aFj{EwUY0RFU-#$4! z_I#f{Z7$qO`ut9ntVgFhOgfO=FG=w*d|bsNxjkkI%GQlP)b5v;*Prd~px?OZ;@^Ht zs?J%_BV$q7Wi#thYp+%ihWXuCaopwj!V6&r(}2&yhtKF;@%)OW$FedG`bu;Mr`4M? zV^CbBNte}cZpTO-#UE-|zRT%`CH`!8;EvQF*!^M!cG0r9-(%i}!f*Sxm&aNC$aF8y47 z&B|#$%SKKE8QvUN4I)TS-(@(|34+`7Y%jo2%Jn?ENvS3ak&N8lIG*2<-j{< z$XH=5^T8NoP35c(z=cSg8d*xZi{KW0=*r1I+~_(x_OFbh1{jkUC8oj6XXo z?dYIpPjiH6(G3p-mg;BN+c)LlkT2c8`E+!Jqg%R^tegHkXWzgfPy2g#{;}#xr7L0j zq5X4)`B$6TDk-^n-_~mH&I9VD%q~^&^r4}*z8b&jWYUEPvo7vDKBGyk1^I)v&9AcJ z?wJ;?E|>p%>Z2*9TAUkncM89VTwEAub~YroDgtAzzG2-1e_3XLcj?DCj^`ja6-Td0Vf2U z5O6}k2>~YroDgtAzzG2-1e_3XLcj?DCj^`ja6-Td0Vf2U5O6}k2>~YroDgtAzzG2- z1e_3XLcj?DCj^`ja6-Td0Vf3hXCd(0%R8^Z;y<#hkB#MW$4PIf`3f>{wEd5P3C#e<;kZuOwX`% zX4ePaXa=Kpn1A3pN2OBG4wQ__RBnCCz9#kUq{Ojbkz>@;^T3ovzofjE87W+?`h~h1!^*BuAY)jT2r{phu$L>Ts4*Rd z!j8s?;Fg`O(=s)1>x-uATSU+fXJgmLipFUQMXJF02!~+qo(bP?_^SS^#evv^u`qv1&z@YB}3P7HC^lRte znZ|B{@ix+s11{7~$Je7u-~6X-vlZKyy(yh=_mCLkyx>El$E~`Q#eb7I_{p^e#G>`i z{6qUhCVZ$a3|VyupyW3KA9;ZR4AuI?s#En!eSuFTB3TG52A^=9o{H3&z%(v0gv$b0 zGO=1`@CoJQfx1yUUD@s6Ub#4GCn1N@M#b8$pQO?C=2+Dm1R;m@vTUu&DSa+j~YroDgtAzzG2-1e_3XLcj?DCj^`ja6-Td0Vf2U5O6}k z2>~YroDgtAzzG2-1e_3XLcj?DCj^`ja6-Td0Vf2U5O6}k2>~YroDgtAzzG2-1e_3X zLcj?DCj^`ja6-Td0Vf3hS0V5?Vf*4&{aqHn3KvX#7f)!r1oXe;;#Y326JJ7m(J^70qdf(F zkK8<$Ja+R~^2E)3$x}DCCC^}N&)r;>ynueW2tu}b!FSoswRI@`_Qrp^wH^Y$bMW8p zt#`ujrIvzi|3IC}mSLMOxd|o?Xb$6d3ke?SM#d6-pj=nf_b~Xq1n_eK*a=)Zo&uvI zewQjk8*YMam#T+sgYdRXwV^&&_^ltZZ72F|1Z|<;rXkw~qu-X$5BNp!uk0d-0UIw> zeBp2OtB7&kTv9OjlgyT`o58{X4x=>GCk6EBl3V2^ulh#=ETRA=kpLSBz$jwzzq;_n z0JDh*&W~W+D8HP}|Gi8w8SG$8e${`+;tTNiA^5kdE@4C^l29tsLvH(>$dpS z9>5KNLuMy{EsPE3(jU*+&T=)tVng4#u7ac|kiMuz=!?hjd%#7oZb%CPGanjefE#`& z9hKX?ysSM555Wudt2N{s)QOC9WDD2Lulk2W`(ZGi(8bUnt1&dB$6$ayA9?d; zDynnQ7U+wMAWJC_BzZx-zrA@=ox!gIo2}Ch&}r7V4|w4o^5Urn15XQHBY3c3aT&p~ zkzitdfS=dCauregmm&NQltpm^H!_mVt=Tua{C3H{5g7xJQ1 zgOJS~Jp`glZX;))IYsbb#>^fsyRI~-3(d7Z{61G~1=v{6(G$RLGS4ncPC%aeA%fMZ zZi1x8(5L!61P|sx+s0mk;HOYWl8azH*oCPwGE6YB`ket^UvjIyBmv4iMg4aTU1OXl zSPc01;*wjnC70c*F1g}XWyuss|D%sz5WzRg{5)6e#p@r%SBE?yu-*lALh$-V`1K0r z7YwIN9t`m%y+Sqv&WJ9Rm|g2t|6RD8z*Vpg!Eoe{<+_dp+$mLgaAN6Dz-<@7EubAq zWy%fSoYkPz%q)l-1aXTXuB1!Ii@#sLS&!g`=DDPx^kH@Q^keFBKRmqQf8yb&)At{i z{Jhl6lI0Fex*?l&Od7uVp}O2YNW1i~zDucF0^#f#s2uKV4bs;)djv4gKnwc=-v58x zy?cC=)wTcs%uGU_NdSc;BwREXyd%MN)4uhXl;Sda>p$$%fV^sB!P`m+nc0=#Q zE=*UrFo7ELRfeks4V{x5U;ucQA1U(i4NzJ0jw#$=wiKeBFWbNY1Ph*u}! zV@y)t;%yHf_OSZPgahSUCp28<@%Q%OWj7}CxXPU2!f+2Tyx$89!h>+^;i0P7;6eR( zw8>6}h5RshP~RRNlz${RvRpW>1CFL%;OK^nlS18avHMiR8=^ziDTm`i`A5UW4$6oh zz6uOK?gfU!a53U=T)dqO3;C(IQ2vo{(dxo67&vZo;YgJ^R=`>#nPHz!{|j z0%tR@IdC$Es{FulPAFc|3%pBQcw^8|<(i$jWMrTRuXr{>IS+q5tyAB3;o1OPr}P5X zA^eT%9e>|+;c@Uc=E(TFma-oHX7K-5@OPODXB}`JIB4d7DxD9*-?_cx?;ICi2Y;07 z4S#1*?nwA6apAfHxZdpru0!~n&^!M6yYM*pJO9Y|%c87@Kb!x@g1;|LG4u87!1+us za2|%gNxkE5EA7QtUmW~Vt~dO(QSM0i`;!Y-DRBKja4nVooQ7_gj*i#|{UL+(2;KRv zAo{V3|R5c149~lLorAB-zDvHH-9SsS7rI*t+W?RpA?^BS!;);`{Q<6q@pUz zYN|Re)FfSE$c?3|>~w2D)p1tS%;S8WGZR+SsWbS3rc%;_gVUO%&$Tn2#HI9~ZNLqgQMRM5nD!i+=sp^ysB8_K9BdbVhW_Q+70#aP`H!P`rb-)aJpvra+r=Xml~O zx(J$Gh(3Qo6dE4V9RyFSt7ra=dc0$oBmG^nG`Y=poi?)@e@2+B^F9eJ!|s}%gI>1p zB&)X0Z_O)$hR%MY*g_BQ(u1vOnctJ1rhW>iXMRKfz5HuWv2v2z77UifnuE?4?qkK* zx-fX~1pCS%QF%zfdIYi!DOVUgl$;!jN|y!x>ACk= zo%UE?yp(!-P6IY*^QUS3W(@Y_Z=8^ryrMe8stF!kxFwitt=+?#Tbh`(VxrIPu+Lt$ zGH8AANTzk*k-9*zBm3+JR_<8yL~T|U(voRllfBW%iLIcaPo>Bq|LqJ(Otz0GgnPXvue~vLxwf| zDZj5~YUiRYGogDawA!)TdZDqgZP!dIv!m$j>Xm}w8Of@#p?D7c4Whpt!!L>k>2r1Q zY!Lr}T#3o^N=23H83?XKoTYx*_8_3EWCAzLm7i zpC=xBfzW2}CL6?J#$g|?eVEzHsXa%=r0nUu@|Da@wW~Tl>`^)Sp}6)gb?nh2jB)Wm zv)4;NN3F$G+E@8QQEwmN6P;(VM+D~H_EnwK6}(e`^QXY8zAg4q1wm^*`0?OXtp?LYMd+u2w z-fTyvh8eTuT9=;JwcaHr`!;pX^ue=!co#d^U1``dd^KKQWog*GSflo#BkiF*@l%!M z&&s>?#A$-TqQ8XSp7$)YZoenALVbk?TJhVF=T8EI)jDQ*JMwWN>9??_?}`6r_JXg< zZuq(Y_$CAAB<2?Og~{FRWmmd*`x$sk>j`f~UmkA*|6RP%*O$ec`sxX9I~h-JcpK0Q z-m!)iAC_S6yZwtjfe^6pL2yX44``R$jKmE6mspDOV7*>_%r zFAtwbOVX@04gHP0&o4rk3D_NN=yRUlCmVv+&_DBef;>mZ8`Ss&ZN^+3Z%2xb2Mt^u zFE2^Q8`SvmRP-in)@mc>=ykdC>M5I#zE^_Yr+$406ViDdee2*|-N*OYciwdDlzEB7 znlp;g0Z*A6UFQ#Ww9!U`KNK(U<#b4IYXF`CUv`Jqq6XFv*`u}YtKGG%6%&2A9gDw6 zO#dfqhU!NSB&M$>eI)CubU5jzTfy7;jIqI=y*!4FAYJf%%I{|kJ=uJnHEe*vVdi}y z(2TAD4(W5?vg1wqB`1X9H(+nB^JQZ~#r|AmHC>V(ileu!*%8QUoQExSVlvq^H7h?l*6%hIVc?fGRZGfA65S{7;A2i@}g11lH#b2?_7Q@gU5by2#e(nHTjR+jQ#^@^Tfyz+5( zuBdG6)Vd*cz-ATIU1Qx{FwMh(#-H53<&RWcL_P5$Z<*I>?@{!(Oy_Lu$-idK5dJPD zU-;JliyfTiGzJL0^MSH$L1%B7Nt)_cy`MS5#@=sR7H5p+oIvYw>RP;)wRfva%l6q; z%@F#}W;_evZ6A9T-U-i<3_)Laa4WkbdUtL6aiRD&N2Z9^1~pzz+HT?rcnuj;GmChU zBM(ITE_vXstv%D<@YG}Qz@BKkr;2gxXWo2@47lBI#d#n-=N3Zk!4+3I@k~!VvhS+b&{;cKkuqDj_xD`NQcb<(T*vj=wNPZfEdj=S%w^^Pp`XqgY5)c?cON#+Uh z!lJvaXr*n%CqqLUn&`|%tci$DOci-il`@T2@CauWm?5n6V-wM?l|F8#`PjXS#lCbV)E2 z&jQ9p$TQ8yEa-E?LuKQBOCSBfcNQ}9P@2ygJ)+VYFCCJ()3Kd)*<+2L>$ApJB9qkL z2-=#7OvCm!y*&_QD`n+)X?%ER`Uu*)gfge4Tk(0|Wlj)z4-DmQ=)uy#Sy|@Qr*%&8 zS@99%l~bljZ85h;kT#dPQ`|Zw;9G5EI(-K_c2L)M^@z^WG%H@DGK|-;M}UI@;0*$U zV9ErBskEcMGpVnB6bimYtSN$F3NVz=-$44_!Fbfp6xwjwp`6B(N&YdlLw`Z~5S~)` zRP)BurwbnRMa!VI_Q+N2hqX`E9*s|POt0>fv)tOba7z)i*4n_HZ?nxFH0rlkg-@}f z)r513eNiL7&DopBzi+c&Pv))mcl$bah>74YhCC^F$m%SC&)WJYob&}R9dJUe&;9AI zz11y`EeO7f7gm{a%J=v;ZHkrCvz+KUBav*1yk=xy(d$8{kKzH5ioSz6Ct{B7D7R{5 z`xFV6 ze==vPSl?|Q=iqH-Tt)3B^pA;D{GKvSzU;CCt){R))a$(Wc%iL7_DSSJ6=j*PPFN1l z=D+x+a;s)9dY5)y4M$c6@C=_hSnY5UtJi-Mk@Z>g)x|J zU9NH^Epzs(t|{9FO)r@pY{ISf%jzK4TB%@<3aEv8`)~c9t0;3PzO7! zW6KWagyIjdz7X$N%^V1Vrw3?Daq#QR0}EV5o-ys}+uruiN=b5 zaj|nwv^f=T8b^QVnLHOFt%lYuZm7AC80|@cklu8FBfXKH{ZGv@C^|bI<9bWhu0ri_e8e z%Tj1L7rUL}g)ZOwpk?6`rfqLNz5!2*Ug7^V>Cm%Q_QqtGJU+kS2zHk9$78gV+YQU|P5vjNdKGJ%Si>zO9B66T2y>!bED{ehzU>*j{ z%xzcB=Q?{%Bj;V&jtx_?-Q($I;o(tJS9WT224{XpYE9Z%#0@`pUmGPeQgI_*xfVE+ zdAaZfGlohx6fe(k`Q*#+GJN@^<$AOSULHx`sd7EM*6?!Kvt7J=rVHb-^729Y^7yD{ zx!y(J&{DIOw=6RKy-^&g7)*a{)duHJ!|V0XuuG;JIvSa7=vd;?(UapXt{iXvfoTI? z?op06-)HiVCdaQi0)Mw3g}*O34DV*o6TaJw*Y|xBE;$*y#UQhn(;8RugT6ET=#$dT zC0{*!hVbh=e7o7jwc zYxBTOzvTSJhfU9q%{jmx6TA3b>73d6j_5<6GsItIh2r%tZdU&v)Bo1fBNgAEf9rVG z|BKA|{*Z5_mF8cUUOMP3%ke*M+aJ8n3Iz@nOt6}AzmXQrzB@fyaCe_5Hjdix0;}on ziRcA48UAk%40UWMZG;E!x)As-0M5z4I|;bUICuJu*~2FJK6|o%{J$ZKPCsl;aP~dN z;CS&&mu_c8D)JcPi|DIWV~qYJA4qrKa)@S=j^}o@6+xm`?E$!F2ZJy0JF>U6s zwm#|)H8tEhbYMY|Z~kKTw!-E67aCovdJuXzcwC0g!~b}&FfF=_b+&qh{-;NmarRKn z8X7F@6Wu!ueBNv|RTracoo~h0&GOCHe!|h|##l{DF2iPbyfuFbX|v9?nzCHIh&_2u zWK#2laAxGZ0_J;oNASAvq`-ki=X173-mG)6kxvaZRT6*a+lEdJ=<)WZP<%G)yVfC{ zt*H&muD{GGw7%OGh@9t?*)BVQ>^G*2753$za=r1&E2m}R6FkmVaD&n^YciSG2(&38K(S= zobhT+2Jbu5j-UQnJ#Z`lpNss~&TkEz{@H5mv&~nUvbR&#tn*!VmEL$PRB7OEnd0K- z+DOG5#vxfCd)i;Y_dATgVc;a}Fm?wY{GBd1=zmT4W^Bxwk7?|U$j8pJ#y8)bqdrS| zlr(%6;yVJN@$4UVUNAUxrv)FKbe@qlw2$9Iq$0rYWPaiY+2Vdm-4_S?9iIl_uyqz>1ZueXyJS*dv=&KiMwk@rB@3yARW@@X~&PReS!P?)Csr z9*pkS`<~}N$vcuRcuGHf>6hvZu_rm1hE5njC-ig1Vf9%mZfH<> zo(YS;8mZ{x(88Q=+yN~@?4vpvPvko5AZ+Gq&M8{!8gr2cij)}oO!_5 z%13nJE;7-~^Ti`w+=U_)FM|)!Tf8v>+%+>M;jaFx26sj0bm8t97k5?otnQ!YE8Tmo zztqEF>qKxUndIQm%wzFg-nD6^xzo~1y|HdM`Pjz#;1R~E`zzuT?IDu+Bv#xt*0ym5 z?xNF8_~hhB#of+W4WE39t*a0}-TZTnJg@`E-MyM~hW;V=!%6$Z8`I%@AsUM>8dCVe z;TQNq{Njx}c;c~*`?4d9TmFZlv3!Y>X!mSrYD$Y-$@$-yZy0&O8 zJ9S93ycSwc>!M}V+0b&QH*P~qZyX!)j%^&n7)P?47C%N@*cKNU*k)bM`kw^b1HcB} z9l!qiQ(gW$(Jjl|?MvBeWLpU^dwge~-gk!2p<9>!T!@Y*dFSbTN86uRrKXRTAui6! zBNaQdH7|@`+_%Il!1Ypz;gwdc(Q)xgt|KdiL!||B%bYZwYZ;qo*B&wqOv$?U(O@b( z*}zgX$b`jHBNe|*f@z`))1Z@%0@L6x2U9A|>WfVO?E_5sMYaNlFK3$-*?7g*6P;rU^jC6SAyN0H*Nh4OqFR}FrDwhlss?B z2QqIQ9zOEC={W6IH>TcusT%gwWmASddD)0zt1rvqo{4DRoNZ{e+A{raogS$uq+f5I zw)UsLe&WUK#_$PGUsiTP<7LGsL@x`Z+=1yh?bkO52R)w=9IhWUyS&zZz;@0Fp1cCS zNb1+l>N_JnsD6!KqR!B_!7m>HN3tFy`+YtA9=`8RvSYY>xHxY5nssHQ;-3S%#@LX- z9x?sM^Q}8=T{}TvL$j8BrrqMJA{CpG+Kr`YzpZu;w-a=4k99lK;JCe(zz4_qm{gxiSXK70}{8sddX>(F#q~c!M^!6nS#c*;85y0fq|QYLj@QWDRaVIS<0Q*C>)93GRchBN1*>`ROeHaC-YSsUaJ zqy17f|IrKL)!5#vpu;laLCyyiP9a{xxs7Ob9reEKxz5)!4?owjzObG1l=f|AtWVC4 zRGgcH`)9$E=C5R*#-A)BN_H}SpP93k&)nrZ9+_MJvBARta8M7-l9vtO)#7}m9^Vbw zN~QZ1SlJ!Bp=Du*DX%kajV+nBsr;Ma(Q2SMC#%meJlO7rvZtnrR?0tyb25!>*MP%q zprL+-2Z~&o>SxdUzm!wE$7%z;6MQF+rDvIi-m}ZlpyfT62H%NP{F%POTMb@{z)PXK z_U!%8l)dWjCU4BUrcU+EvX5lX(^-!64%x1?zWxvGce0g*bpUWp-d~L%E4e&xT zep2snI()ao{+{N3`|nNrZ_JHUJVLultNJKwMyuLlzpSxq{>a`i2%c4b!?vs$4YK{a z`LfBhjl^GrJqR`!WC8bRD7SQTR{kt_GL5>YknZVWz~k(z4wv~xF01aNZCNuyTU`2W zFfa=5bAU0Iz8j?5B-t{m-^+6Bgz`yIef?tZl9ptT)PCNBL1*t_)*bEZdb1yTdcW@L zd$Kw7PlLCjHw{c%ABj|4089z)47B4H8To^ub&2+L@RrWY^RuwKXUd;XYoXCmx4}mz zVG9YPpS8ndZ2_z1e$Lrr*dwaZYuEWX;|=_HWemS8oAG{hzG&Q4e>h_ik69Ty_vQW{ zb@#&u$ltZ$jRpqY-yKQ0Q^5&$R35hTCh30C8lB5GLsRz6YlEXhO>@Ab%H>hc=h{fV z<-!sJ7K?g<$7UQs#!=#{UTIeuxYAh9y2fPoYLY|J5!I$(yPCEV{qaww&w@OE+{Pbp z1Mrlb;b+{EONZM@B&JkNnzSBDC@HwjfN~mc&<+#T)uSh;E$hGYm zCLYlmil32eGv)BaBKTeOjEo31$yRn8wpz-JQoMyTRQP1o< z&A!i*FKy46cAuhO@k0FzCVnO53xQc@#T@GFGd3C|*|#!qns;WEP02}|%5LPqA45|$7OuKLlz>*U|0{}%s`bN`1&1+Oc# ztb@hG?es_m_Jo`uA?tij17QwflyDHC)6O}jd^Yj&KJ4cSrx41=wxMsN!X}IoW)fBt z3RlYrb9+GuONq~N-dIQk{K(S)=NoC9bEI?L(TDRG z-bGpOtC9Uga@09{ZZbUEzS5m%kx0cZ{5IN`$`+X0xKi_Mc&Mq+*Eu$ZJ&*QB6@gpr z@2`TN)rRr~>uA!?cf*2Kcng2F7qipX&XU z9C$T0nY%i`{TI^yHc|4&inG>~(nq|-k>`UPJwfsc+jXt#$w#9dz6|}Rf%j>2^gWif zR^w>^E{$39O?b%FyvC*}|Cjnc(%mlx-xq=R3&H;doGVG31EuE4Fa<69X^u z{i@`@Co|eync*KwpIZNjYwZ66EW%kUIO`{mxivLW(QPjoJXXjhBR|!Wc z_qbFq{4>KxmG>GxdU6#!34dt*m8{H~p|cR%w_;^E^3BtgnxU%be%@_m7I>7^8*Hnof$aTq3Pp+?qkI^mTMy^{sPvYD| za=ePOxK?xn$z<_=7{2~G$J_2VeGH@z;a2OeS--o>U9J0jUD;|KAN?I#WuHHCj?zjho{gy|NtN1WBeU0`NvUcT2)|3(I z+>bFgP3Hd;{!bt*Cp?dE4x!|372$ZoWrUKu)r4%29JwsH+dv#Y!ki6+lDn;hXAo{D zr0tv-VJTq{IeikLO^9z-PAMTWH>ZTKh;RxaJ}{1)m;9eYTynUIa4_LALdoH3Lgr~s zlu&!P21534IU5Kihg%8z5pE~631fso!XWE{WSdPWy{429xSAxBOZYE5ln7>IaLo08 z4SF)T2mTbl`~;aA3po3Vu`$+ln|UVsNv^WaI6m>}Q*(wla-7iP2bGiD0mfR{-X(J) zj?C#!`=0#bJ>9vT`FR&G)Zc3OXof34BvT~ATV44fS-PFG9_b;gksAx($5x#YBL_zY ztkJFTY7G8vfk!p}n>cr7T;qAGYE;ZE`-UScjNL}E0=RR?AMNB*-^7E>Z}xQe%X?p2J~#k&3tIZ#q0w<{-EX}{!; zK4)KfsJ~WVwO8nzd!%!}NoS(+!S=Bh_|PZRW{k7k7;~s3X!esI6IUPk;J*H9)9!1u zt9`DIIr$229@yEFoOgC^bN7^s_a~-%`^P`J?UkoPW6Ielh2m+>Ua{-#nso4|ajE~e zDKB1lMs(tiebL^;^!jP0Ums(OfIrCz-s}55}l;y zflJ5U@Ga^Hmt&+CTx|NZ=ra!*N=NQ(UPLZ3W%qIyQ#faFtkpiumxPZ?U3@$NK0fa_ z5@mF%aT+TF%y{`?v)R<17o-=pAjWyBq+eE)dk{8YAnR35y@zR$z zG#^rNV|*^y1A&`0!p(Zwul(ry0rdVf^nZNc?qbh{@4{~Pyk2+0z4s;yudtnUr07h8 zpEq8ORMdhW3){}kw5ffS=$z;u=+v7c7*}fRi>;=nN38L$a93Qs)JC}i-t#NQ-$r=! z-t&tO=RV{jYy1rNJwJOgci^1&{Dw4MOPx4n%L8REbPnepOojy>2ZR4X;6J}{HTe_g zjT_fa8{(hI#Pz0(_jX}9@io6si-txUJc%!*vuLg#yz3&yeIet&06a`)-!qAK?Tqh6 z8|~#%S92}7y-}oT&ZQG3+rm9x8|}xw>^Z>hG<*VuQ0b2HZL zM)uu~J-?kd8be<(<3raxCVQ!~mp%LC?MJ|2MH|^_817}31-QY3a*VzYtl5O_MxDriy;nBfU zb-q1YHY4nF874O1V==f{U{~h0*RNJTcF;zG1wicdkJG`{mHZU#uO{8L`1C#M1 zIR}{FgEcu1TjR4!^o~?_UhjGAM(4E#7@UoYBfs%&)qML=e}jY0Y?Jq1n(4RUW}{cF zMrSo^Zk}T&ngA>f(o zN!5$=p2I&K+rD|{wD+~#Y8?B8X(RSi^VSx8GJQ@a=cX50uf+OTaoH*Mh);Yu8(;Zi z(hA#oXX~CV+j%oA`bAmN8(Rk+$+S8jDd3H*!MxiPXKs`v?%7g(ytTG)|2?hi@%FZbI zQ{_FA_*r)4iCVW>zHeVw#(z7%^2C>SbssD1#B}>U>wsu;Qa9R6c4@P4%Z7A~^YHi2 zy3=OimWBZ1+|8S5f|yWYcfbtma1 zksW4CEvn=Gf1UrK4wL>W|C84$y}$4e(j;@RZ#nkQqD{7Wf8lN0d4J&()gfPN&_DSv zUU`b}(EAJTWjOL21HDtf>JRo|?=Kul*8MTa`BPtO)Mi4-((gmd&J510x$jYe?6X|? z;`6y{DZb3VqpZrk(#KkJ2RhCzeQXDYy$K_O#-y3}SicEhrF^sGG;P|nDL?4~U%qo! z-<%QTHa|~M!!lU%!SrhQ{p}h7WfBG!3_IB>1zRaFyjb&iJ zB5ua?l4ZtUP1!JGiD8pLF0zL)?fB2*ok8+Cp_AGw2;_C70gwFo?;?E$^PGOidi%>I zlvnzG?snYHTGf-ROVusKCl9ecORp3^uy?LqlyYD9KK6&nJXVY@I14;_cE$3(#<$17 zo!uy(eYGwpcoXH1g)iq(?pt2jqwr;za=r28H1fWTyu6h1 zseC!gU5DQJgBjBpcl;A5+Z$hgmAsz#@=Vfu;!CCfzs{F`9{ca{<<<B%uX|;W!k53KTyK2&EO}ps zFMme)RKC3B4Fh}bt7c5Mx#Ry4WqaexN6G7nFPD+t6JIL*Xngtq$68u(1l~wq^Q9-; zdK5k3#(zUk;M**Z^`s{pX&s*cZX_?yC9LmZ9k-q{eChjn7hjI1Y%*Wo@}i;P-e*ji zG0&U$*k71%IOUIpFAFG_@0C3YU*=G*H@?gu@5}I|PyNzgH~sQi1N#*}HDh||Srh)N zPw#yBDS18dN^D5rwk=|Ct8$Bb@+miJ|qYq{~ z`k?lJ(g)f1I{M%o;?f5dPSKtjpYf^_TgJ;q9p>DrZj86DGIv{7jp=Ul6c5im3J=fv zH+cBhz3^~%JYajr|DyD|=J8Rhb8P7ep+_dRlypR~U&`iGbW$j)cq#Fmg(2PvHD{@> zGNwg*XD1m)$+pA4Fh;$3C%rW`i+vhc7 zO}1+G*IDD?i=5ab{Jfm=jhx2ez){V&iuOOn*+v$3)j1P%>bJDKZ)inU7#XvAg_(1K+Kg|A z29tQVC_p{=mV_U1^|nV$naL|mnOT(4*mYMx{tQx`Z^oJZPqrVvOd)}Jx!3RA-A zdrkX)N^1WdwZGJ~zu9eHbWQFfF*%*@ARNaT+VPyF4d6^|AZKgYoGIq;-gG)=isoKc z8+XEir`GCkZ2cSfAMR(Z`JA!sj~Kbn8AMHt?^k?3V*0%MD)Id==gie9@Axw)p5OQ; z_1iLKAJ1uQS!BvLt9`!lR_(`kA&TD^ei4IxwaAmfjqAwM8y;%!SNylFA@e%02Uo2x zS)O}^RdWsaxF*B8ynaygxNFE4T!neflcgmY~6QfL9Mz$~p$`$e* zi1yjOn)@hc`SEXkHFSsFFK1xEfYAIhogFYQ1k?8fljaF9;iFco?`V|k4Lf8+8g=EP zbpj!4R?~suRy2I8ndcf~GW>C1kQ@z@E<7~vmLKb&#zNu;@0t#Mr$Ofm=zTeK{|0Z8 ze4Tf@)15mS;wAO#$OQWR2W_RwgygqER-%$+l5&Kf_L z_0(yY#hY%}ON$tr_bmdgw^4tv*KZM2;g2#KS$xEA5g=c##($*^ddX(pKwr9BZSySx zy>H;1#h$J*l)Zs4`CfwOBPv?lLtU*ow*sed;n*^%GgEbG`+Ma7Zd=cH43fW#*B|`r z9DNq>s}1iQ{Yc-%TSnVjCwu!Y-XF+6+IR6Tr%Yn0waNR|rpBwYJJpr!l{_HdynQgr z${{^xBfs8s;^a3Fqzi~=qyv%eb)uJ3^%GqGvLxx*$IUs`C-7>i!fYKsR>I*9Qn%Wd3@KdyW}V&rwA zhv@&``LDHTAO9WuC-ExY0_Xf{REdAw*cg6K+ktBUWvT+>##Rvz`m&v|>O4Mmtd-my zn&Y>Z$EY(@b-+<8FpKwXUvRk%j#O_7INAY@%6!YP`}*e9J7Nu!TYd|eD)-=-ZF{54hIY{n11b8Lfj zXXLMZPz6&7xKZ1-51G8(+yPNt@sH{^Q@=O6FJ&rJCQzt*imPwdy|8)m{UPon?k6tW z?MeK;P5R+yzRVHc@hz~C55OT=qP`h-Z5Y^ctsLhY2LA*G%}wQ{p7m;;g@Io>R+us` zP*!txDPih*Ugqn3+4SLSe46~Q--_DwQN@CJ2Whv>Imj$R z)lr*{?BM@@^IvdO5_;z#zT=EMuOdzSUXpS6ImqESGUwKVriY>>X}p_`9vVicxA;y9 z@4j!+`M@076D^T_n>3X9`_}8yICv!#y?*_G5=Khb;8nQEI_)Ar{E6rBg8Qs&W z24>FiogIo7CY5U)kU1kTTKw2mw?t{G$+v2YS(6%GsIE03EPmJ z(c(}PdAIR_Q$kUFe@Oc=(x->cG&*6+S!Pa5Vn5MF8-M1vuaBvZ+#a>ssqfop9h|gc zz4Je?v7m3Y^BtY$vy6VW`YWc5S+wy7>Z^|E_*9zSb1`+7NJjW4zS}_9p!uM=LD)*z zN|?&`$vA1Z3_KH&RTGg_*?Y}<%xhxt%QIW<^7nvqLjSQ9@CEM zdh+Lo=XBo_2)D`fyR!#+^uCUpyIB@@&~Boh+RC+f|1*f}%e0)g?*xCzf#3}La;>fA zoY3-3e3$(AoPZg3iTf?EdgzwTx4@#h>v@7dek$`?_4oKPXUIq4~k z#|}`-`KI$00diJ%%GQDt#p{tz!6IvuWL1d&%P2Pj`81PyA@KLW53J78BGtt%LEVNE zjc<$U377gcdlD+OYuFyDgoo|Y094~!r z(lrNyLA`OteR$g3K)ke)J~_`Wq+gA39e3q;BXoM|{7CJqb!X3gUAg@TeSQ1b`qCZ5 z12_4hU(fdt6MSA#Pk@TR>( zm^Nkqx{h*cmv7k}HebAR`@MfQ_?L{euZOm_ba}sXCsJv?t68()>F^IiXUuw}?2Oqz znsi1oUlp?MCCgpuTo==yVDWUWvez;k-;+0fmEq`Imyz%3T;&doIgM$Ap3YUdzR&kG zr?N;>Sp90oVZJBr?;E%!-wXd}WU}P^lTAjxm!2(KXF7Y|?zWR|x)5!bG|@J5yk&9n8a~f+^b@1=#njLoN9NlCbWTX(H~u{qG9Rvjy-PK3mM()amn_DLpFu8y70Z5 zcJxh^!VK=x{VS38FMeK( zvUVr(*6`cUZ~O3H-FV<8ANCBsnSK}FNL!Chaq01!H1^hKJzNj#ETKMcx6ZFRUi00@ zH@xdF+a9n+WL|3Yg5}&t{Mwv3J)yqaO}+aW@1H+pE)lx>=8D0L zfxLmMxf`uLOa{K)bCUAqYoYuW@^x=FA>Y*DR!uhPBk^-{_^bsPeh2(N+pgIC7DqwT3lF#L;iX2Ia= zXJGsQ7+4n$jUndd7rFWGl0Pmfzs=1rBVS|qy*mc^Xk;VncGBO)oC#s4I@IPCw@#(o zW(##BFC`b+u$3S~4wY?n%Pw}?e~GgBN%_rg{%SY>=j7`?rALET-24_dU%t_HQvP#p ze!EMfC&*Xb7f2UBM6v&i4iEe!W5!fx{pCAStg$+~fQM>4f7=5$l|{D?|Md;>^=UlW zs@=&xRlE^GmwdPon-a3;6VlFw#~qnSACJ?=NxIUdT?W(;Fx4lo0GcWLeW8Wj|^!KSe?R$Fw;aoaT@>>h-jPb>%tWEX&xEorV zSQLmRhFkH~zc;d9=`+;MdaLGBlgdU^zd&@xz~X`xs3+em!10+(%UwgwP-E>cT;x}I&uUZdC$78bxF9M z?2Lf4}} zKj@@;!AFdrvyPGWEOI$kQ0CBj$C>(Gv1t9MLunz}#^wNVCqaL}yZ-cah;j8O9AEk`Bw^j}gFXrs!BF7Q z&tL7{yiMPA|zaJR^nbL_=FSNuaa&U&|B@iV*R zUdulAflnEEY{AoE_7&)awF?F^Cpq^Nek-+CWL(Z(k#Pzqf2SSMeVR*m@pT)t|B&>f zeOtS28*eO7PUGCe+NeFGczXzOoiXTtE}_mgJs##Rpp%}QmORcDjVo!KuL(Y24ht{9 z+@v`0o+^0Z1yAk@<`xT z>7mVY-+yUW7AW?#)+o79{y6 z9^Jyd$wA~doH8lCta#9>!a3MdIDfI_(+>PW_QXMKRqRh1NAS&4bow>r{jB)Jg*uCH z&SBz`ZQ3j7yNu}g6}pGM{pnCC`tc|5IY8R3Z0{w5C&A8=^Qleo{Ne!X;ybWhLS zcNJ%V0rw6qWq-z9W7S!JZsyfl#+XX6Q%~WX${SA|H@W&@-_<13S=Q>_9^}+a8LX9frI;fi>$y?nh^^W?7ButAKiY;EQ#M@zHflhjgx6 zG%mU>Ft~GFVhr)T&IooBeJee(G3SkBMyyjF)UakNs8s zQ$E(V?8c9%+rHSyNTvOSc>O&l{*5B(ZGS=cyV}wH8pxNtol1J)Jx1PM+)J63MJE5r zfPd4?+-a=O_UL6R?~P^*x_5q?o9?v5n4hEGXS5?dk2^E-t>=Hd zQtSMAn&-@+&-#oTEB&uw>5NXvxiV~)qv0j39fG@_`eq%;ZTunsdtEOmzf5I;L3i07 z0sdagQsy4Yie^C{c2vGq-+?XBURD<0zNmTp4rI3UozU}-uXOhQv|R*FgcpQiH`#u# z+WD|cwnvD6HnD8{o$-ldB>V0r-pc%_5BN9jXK&sUjaz0L{E2>kkAB!U(7kR;stK}tD*P+;`Ourn-)PQ(QBbgFRiQf%*!D82k-hOvg>+e z*mcOVYmsT!;HPsn?;KaRiD(hs{p$|=^4Qp%lz^`I()4!X04x+X7N3B zyQ7u$KG_Fp>Ld4V9x>>@ReJVb|1wZM$Y#nH@!ESFap?nt@3&<7HqlK1t~1{C9kk z76%-kq_F#a1nHv7RF3d1LeK8OJ24LJ3rkFUGr)s0X2!#VVUBN-;;Q#6)dyEoDDzWr zb)@fRB_I(<00oP6w7}9Cu+Y?0hFuHzZbF;*zby*&AJvVU6ky_d|Gl zqBPggC;41>2>T}H-Pnt8W3!<;WamK~gt@5|dbEYY=x+I|A>6ekY9zh1|AS}te9 zds)vLzPM)#-<@Auzwe$c&A=vp(H;Yzu+0Rz5(I>)~GvX!*lHE>fo;e z!g}mlx%8=f^QnA@@V$ILdxhKCE4<8J;XU>W=LT}|y|QbvfT5iAMK-Rf?7gH1l%t2~ zUH&3u)<=vdw9Ts7Mp^XX&8$(6Tn$Y1{R|B6a*hrh8|ia}y)bXpTI8DEdA9lfx6w`d z*33h9=MdoS>JgLTR%Kw5i$w_z0TEJumkK?e5MbU#;x842z+uHAoj-#A;kllDbZ}cjD4|^JgCl4`nuK$yX zNBf(2Teb-=#on%RD>~P|Hz4aoI>17I&2(&inuGc;csxE0!KYi~0|z{Bq06Wr!BENC;;rGyei=HC5-(ei zr!^h=4~_I+Fc-dK=X?L_Tg?BS=AX*yH*$kLBaG}^#F=0{b~xr>#fmS|&6!=wc*j`H zn_vEe!L8=xU$Akp|6CIT_S3*~1b^vF@Eqhf51h;cCyUapo%8OiTiFrF+W0ZJc?e!# z=d(K6z)h)d(DJF^>_K#L{H8mKpo3)4%yho@0FIdJ1L{WL2dy(Cc&Mkjo0?Wc{nCTs z6|#So6lJc;#=py6*gW3;A~9wG_|>-zmbu@&C@l>|r;6Udt+Qq9dz(ee4#qtXIzJ7a zH$vyB3$s=M)6S`k<22x3#8@S3EcPa)z&?}llmR>S2YR@Vwc7aw>DJleff(<8g!dSn zDnGJ2{d>Z_{#S8FCFp+d!i8sJuQ1T>6!4<4*(YbNvb?cj6Hr@iJGHwlF^fz>}Raful>T{d->U+ z=xTUeGOrSTKMfg@%{(lEw;%LnZG4b9^$9$5BRuphJoGzw=)r~kR@Idib>MR~{o{ad zL_cV-{EU99=3$p!gnr(E9a}P)HCFE~k1s;rmAi5-M7vc_A0w?fE7$-`+vS7g$^_Zs zH6P%=3WXcsDLXABTmIW6^kdujeL?RMx4$Fhsa$o`&euHN@KXcRvCQM`z~s$i`$A_A zd&u|0gG+5U{M61br|s=e9edjvuh+JZw#%4Xg_iLjsidvy)yImvq7K2y8}o;7m)f2) z{?&HAt?@r`>@b4sLoiwwn)iK@=e1`WS@VRQU&|Z(u~l6#m#}VYFNPgrGj@nwQFv+t zJcT`CmGnXG=uB^WE8Vd%+{AYf1Y_)R!~50Dl|wSc-Ov0V%7ix<`KJ4i1Jp4YShp4Q4 z^3C2d7x=R~ut`i$UGr1>x@CpI$FcN<-ckEy`s(eR?lgQ-M3?IS=%U3Db|}+vp#P+wUeGL)U)J(+5SX0-bMhH=`9<=jpG1xQ#mvF^C#mA5#9 zclIUZ2_JQt%N(838%PB7%W}+{vqwTRSAGG=gv;-e~0XV z7Ir|5QNN@4hquE&vVjz^f6%;)F0%8p7n-)WqsQFFe8}_-I)V-q?1;Luqx9;`Ri%$R za(lGeoQOW7`g<4g1{wC5Le8{gql%trWlv;H+3~YbbR_;R+bKK!`DH76k|9HoAv3XK zU3Gum%J+Z3K7lz3zsARbw_&UwrPmHyRr0sc_)Kg`r{(G{fi-_FwxpTN+cMVW5sUdw z8+lV4JyHG|53G#&#*LkZp7j8C{bu?~=lPINHhS-Nd`)%)hBk87Yt1FOp>e14Q#$MD zJn2N*$FG3zb+#t|n$zJ)i+ecZ@qd_!J**Qt-L*7OGf{r&oX=>z+>br+9r`N>SU0x~ zth>hZu}c1KO|sv)-W10tqTFoa(x%LXu*O9I{`Y@p*Pv@I8uk6#5cIZg6{J3NTvJq=WCBh z^DCkGSO3{X^RX_?gWrMX=am_n7xh4MbgBPaH2($o7R~b=n&)@ycWGV_7<7o{x+g1| zC;ZmU&Bs7<>yUheC&r~!ylgHV^6#tAN!HuH7vXm zKjdRCI`C7S67n4%d*UZ?P7(!P@7}|P5ncAt7Gyu;#5QX7CkJj?@AxIJ1wXv4icgA< z^V^=^?3a((X~^Dccl=3vtu6Q&Rp4iIGyX+GSu5s!LO-S0uT^KPFEV6rATnf~KX2X{ z;Hjs#UFEy(z3uAxYyKGA4_bAB;~NycC%WofpTA}mX^-=>=iJ#D10P1G$!*jfl^Ew& zF>Ksbr}9k?@}0ZyuI%^p8ylN;=~#bL!k;^@8JVxL*RTex#a7axvvd4)yfP<)lQ4R@ zJ;|M~$KY4BopC4cmFx{g%dJO4O_I@`4w0&hif3iJy`r#>qjRsGdke7R*F^u=Nk-}J zTHP#br)wi|zN1@LY@ID%caM&}eJ96j`_>cOw(m4;KTO-$Rz^uzs_Sps&ST!y^}*%> zjkQL#PGDb>j=VV6jQ?2HsAa6--rmU$<~U>5`M%mKKiAH$2A|8u9(#M*-yUj@y;wE# zzi^J3Q=+MGdUPC^d*?d)8k1}A&~oRk;5eu8G8Yffzh+$$9=P9j2oKexSgXOqhO>_y zZg`*z?qKfn>_@F8`8x;?_BqI5@G#}fV{dOx5+1aNYzGf*VS|U{@fWgBO^%E24(GQn ze7w}x;G=o&t(`hoi*RYQ)MjG6#r=b>eWvDwcP5~B1dI=3_F+DZmAolF5&4DOoh~`^AIN@3 z#+Y{}^v*BF(D>?3W({+yE(E=E1Lcmj%8F6eQb9f)bsqytxW*>gY%Iobu^=@V5bQkj@(!>Ya+l%Mg z|CK&N;VeS6*`Ye*>;K=~c2*O5cQJkY(;OaaAWij3K21ODF6QC$PX5E8_&cmyx9~=V z?lGgAPOo*&+;TX|(wSS1a|c%NYd<1AOYepJ!hxZOH$%SuI`$KId$Q&D6xly9XQts1 zq4<;3sXE_{^Ub*@6#u}*58tC&srWtSEtTZGb{N>acun!)_kDCu*5J@NyOHxx*2qx& z{zLHfZnqV_a|&hK$#M4Fxx9T5UcQZ=cuc&iJ_s#y?DMRFbFO%_V#*b3@%4$WvJZZHOOST*E)T9! z9WzIAo$p=^r;d2sOHT-|mNn)x+SIxnXAfED$A_bDmw(7U%8Z}QeI&j|7x6crSB>1z zn`Uhpk@L=-ZPgSmZJAJ#$C}Ce2N8edyta(y^K`eYB+rT$E?qoG+h6{_&?7V@tRv zZ^I8Z{IJ14*m=`SydhiU2z*TqZA^RL#LlF)z6<=qp~=f_#DShr-Xj{1Sg9#-|XLfqDt7m)-8sE}_&cdZnOz`N|!1(GJ zpW2Ra*4PPe0K=yJhx*TJobS>mPFlX(uiliJ=cH$_$Ib63j&UC7;?V2U0>`#+?BdYt z(+0;DIQ|FYECg;3ZznSTec*Nk=?e4zo-szg5am^7?PaXTXK_z?YA|bg$S0ko>poHE z%nO;n7vLkxH-IO*_xBl#>@@8AYU}w{aVkH1I7#JY4<|9;SnT3KYm2^_cBDQp23D0{ z@`jfm%HmI>Zic=Yt>)ds)C;5Uz+=YgYoeD%WcrSzZFdR6dcSTZc7p4MmGJ>nZukM-2A z*IsJBUVA5~Uw6KFeIBijp=EaCkLa@v`Q(-N>PKi#ve@e*73L6nq1N_7M?dVkC+zuY z^kzre&o@u?y*%&ya~t2#dlVS7t{Ry+sBu2=5Z@MW28PxoJhl;!5pM;L%}IESdGj54 zsQHJ^{}{S%*Zgzo=e1W&`AAazuJ+7(JC{?xkT><}Q*at_aneBj`lR|^dkgwo1LQ-+ zIm-ayWAXQo<0hsH$Hs`PewOAm3YMF9L2?pM>{K34!ZniyK>OO zbDr=7pL=-m>U-^V;l=QIECtUQ!c*G6kLUfI;h+b9c{~ra2FNZhJUjRX&knx9|G$H8 z*|oekQwBBjR%6)02X#>6r@;3pGEzQd&FB``OE*iG)%wvY*mZ_AThbv04-_C1_6tj6}!8*lk&Pjf1{oj=fy@KaCN8}I$yotvs#Vp)zZu^k;09dK8W za}nv7<=6#ehn#w5`dQjH;Ah$GJ&#((=E;|P7;A)gXT$L5mywBD+iqoDt7N=_*{p}@ zjStXX6*O`5Z}bQG0n3gp8VE1=X*O0;rr9}PG_<*o@peM9Du4bV+AJllV7;M@(jD3a z_+Bb?rE`cjUU@?s$!M$QR_Z0+hrW|IK9>U$#jI8Eh-d_D&0AE^M|dh^EE>lW2QS&I z>*#BkJn11`-fYHuubaP{Jhf^0tbx7J-X=dvyA#=?Z0Br+ zv*i(c&@B$}#LQ-McZRd4slYG%4khf#M@;(=`Kjppgt0!8I<+UM?&I&wE<`8fr@Ci2 zZJ52l2>!pk)v9UXCpmKp@%l-=nihV;`QNB?&Pu_p~Nmtuj@O?adFWk#p zkoXznAHGREDVbfxUeqS7ioM{6>AWXYtDZL?}Zs}i2e4@T_4h9T`jq-mIpH&`?2@7U;WmD{~vqr0$x>dHT=&$=Ooz) zL4yQ{2<8N^CV<=#uwG8MnJ7{WLGjWihveu9ge2sGL7^NJYY=Qf(W2NI)P8S>v@f=( z#9|GVwz1k)3$L}Ut)aCw5ZgjUO}yp*TYJw=b}lHi{l4e@KhHVOlgwq$b^k1rhYzQg@(+`*RqtYwxn*bb`I^Bgi~5u72hj@sDQjpS|d1wX%PK?Wtu;3eJgL zi`c@Zu^%U8?YuK?v3!$s1352JB-omv2F}r+${UAu+*KrR98RPEayChD zOL(;N#^J(~yl=Ql()V~rZzORiM*6lK=1=gDGZ}J!?XTtDm)C#^yr_Nuk9`ZIFES5* zO<<18`TDJb&vkd$w)ICA$8_4(rvammS#h6fS1bkzNEAF z(>dPU8)=RAqON-*_f*9F+xJE`&{p@jf8M>3ACbPL)NWtTdm|s?o6Uc^))(%3BmE_I zzH-t<7$dRa@4enr^+$@k_n)~lHvt+Gdkw*TGfn17`!0qNz+GUZn9ChF*X04{=im#B zm%x|%_Zm*DWh@wj$e(;SV(0$Jqhh}_Mm2=F!&llIpP1QZ+jPx3xbwjWb2dEKP@as9 z%wh2JNyhjA(szx!+&60XQPxkq7b^Ui`MoPn_|49nPSy|XwtMtL^ljEy!|N0Lneaqx z&hcA(9{C^x9Z~Dsp6@^L;Dg+!&~N({>(rJjEt?_3dZ(5*`<69JnY`N!EVf*+Ltvz= za~9GzX;07j(2@;;b{hwB9#qbK3#^NPo5&*4#)=Wbk9hwDek8EA(g5rGd8_woVDh|2 zEnA0tDe@y{^0qo-P_r;@aeNGW8QjHphqUWO?k?2h5n+zWht4A0n>^UUndJIp+#q#T zL5FqM%xq6K4C`J=85_CZHJ|TcPx8jPYkJ??c`{lT8ce5+($DPcPc|04acaCX7Rak% z`YC;izfO2>^0H9_7Jhh`{)fMiX`NGu;1_<$K3`4>d*;8r(yr%2#_Czd>gOX;wqKDZ z{5^SDCgYio3}^nr#!Zno1V5#$*GRYjQMF|n{T8^(KCm&HAEm+Ureg`d)hE0HGxr_egBuyEW+O(+8mAj8WfB z2Zuxk`XY6TO98|4QuF!7&ODzw&blS{_rnBF0y~?}&)g|; z&*72APT5a8ijH|HGRzTl(TCBu#{ChK1K1d8P5NmvK1HK5cW(WH zxqTh_V%);B@Qb;qwi(bv8F9@b#?TEpz@hh6?{^drJP zv-D%bXY@n%ubn=mXT&Y`{>0{=wmjTr=bx`qUsJ1nWj)*VmCtF{pRl{M$I5QkBHHDr zT{Z9`+djC9zMcDfGH8=!XQF9m;Mu+3j*qOe(mCeao-FYsAy$?nk> z^K9(JIEUh{S7@klWpCIF`JDD_@6nz!{uS5^@7}?xnGTGo zxAU$H`St_83BU7UJ0JXc$2ZrN+U1EXd_VVI_H1Wes?CQ?+eWF?j~pPj^D;MxU2_I@ z%?|JFx2mG8cxvX(?_t9nVeG{As6T(dB<(NZq2DN~+}nW-m+J6_h~duoj2jppz`1ABr~f)fJ`(vMa2Lu@9p(31;Ygoh%F zP=7jkWDnW@9kGE--k27n+h?uEWnQmKu=|&+?>h0*zt=vEwP@rPXl4WBFq*c>+WRo`MiXI? zQ~mT+=8F3XzX!h5YI(JmIbo@Fc6LyG7+xx#VRwC zrD&>U&n9uK<3~m)OOzS7)LRNqy}I_sBT){QRxh z#aAriey)*fXTa#H%OqZ1*Q5SF6ZhrraZP_BF4#RToj4=ZqyEFh6?KnmX^veSw>-1G z+0~yc;=C&|SxvU^fT@uN>+gxQr0givxW4j zoUd(#&lX(~o(`W~7QxRtVZ|o+t?U&DpRW}DHR6mJ&bY+Cj=gmi>mbg5v|_iD$Nu|K z>Ikw=AO3OrMh|lac$?!lE_>|}^11h!rc$q?i+9df37&WEKe*16jMn}BD5dZH2lsn! z50UnC@8lgs9??gg>`vYr`2Kl!^8SIgIdIAP7301Rp6&X)wJ8;== zaLP#k1-AKX>^VW=nhwOKa1YHgnO}W7vTrq2&Co?MPauEh;v$zc+=nY^vtEehoM~@a zus5D~;LY~Cv68RmMd}pWeDFdsW=Y^pBXg&NOFQ5z;(zZg)2koe9Ls)89CmId_89Tl`Xz8y(z8YEF`V)J^*=<$QuVij zhk-B7lygDLSV!mj!7=bVS#0q0;hl%|UH7r*VWx5?)&cTK{Y@{}{4Jij+0s8SzX^U$ zy;|*@JU}(@M%5Pdov)-nX|&IyytH$C3j{9G=Oy$#`IxQO=~(O8*>R3)m;R)4&Sem9 z?0sOtBf0)V`XjiMMSkb)L@A^Gc{!V)br|fGE@iLOt;5I~)cxMFqwlKk*Vi|9>Mx#t z&Tjh)GlBb`)s|)GGF#5)9y{7TkhUKkIeTY3?cd)`hvDngVbs$u`PR(6xsB*BUKIVs z818mKf6?+^zMY5f@}mFK`U~t8kLosd>MsVMzrd!?(qEk4rN5X(xdOvaZo7hU%Vzwt z7{|-8d*VLj7i^oS_ppDFx$_4aHXpz%9Q)cIW9KKfwM~pg+a2K6n`*{W;Bl9}dQkms zS0PD*B^$CG6sL{~)aX z+aBvi^i}ZQvn-sv#M5vVcpUhmr{O-Q;xNV%Dsfo@m=`26;FR9{=`Vek3K)Gze!m3S2?R?ohd{Pv+hiE z=aKXnhIW-j9b)$^_iH{*yzr1J+@5+XDZ~7Z-Bw2yXFZbZ*c@yiPt6id@6Q?Sqo~_W zuSXt@)%Ojeljwt9Yrt3cJ%c^zwP1%`xA2Z(@Jr`@!DZBI-7g5O%6g&p5j&mm)4ww& zl71ZNd+Mz6zip=rkYD;1X3Udmx2(M+EcyIW5Ac{sny>#z5#zxSzM>VB5GWgZjTn-dn@53GMm$Gs2T%Nj-K@%DjTbpOGhZF;n6$gx>Xu3tmG z4ru5E-|c%#Z5xj>B;Mh{`o6Z-C+vIb7ee=y*xrXV-9O6vG7jAf|9BVv;?RAHMb9bq zgD6k-+)U`+q31)I?!(aiU@P6=`hL0}P0;Q{?0Yqm)z;Au^2f9@Z{_5iqdm9XQkxcHSZ>TGqAxGpO&A+ZKS| zUjonPgYQ={|IEYYmOBE`KkOx+)X9FQ&Cl*oTUOu~el|$cPbUwfKH*iucQ%oxlZR>E zCOk`c&z<_4goTH3-pk@)19W-9%PhL2-VdQ0q0^l|k@3>;^c9)KdZ(+LvfTYFAuP0X z8E((@z?Q$+=i$>UZFx}SA7HzCAmi>{7l`fF$=-dA=rYW5yNpb+`7V(4LUMgNdb@j( zb7vK z?VzU9A9op&_cCKpYY}4~k8DxPJr45j)p?||=wLbRle>|?OZEeoEyoqzmW8vfbx2bM z^ujvi$n($(`T>hxC?^wo5jcvBD|pvJoUB7+OvUfqV=KIQ0Cl=;rGQ_jo>F+3jHSCT zF{F3DabXaay4aM%ZqD=SC$}NP&hl7%*1X2yv#FfLLw0&u^M;Ygm68v48Mu)~-(sMv zI&9>n|Jk`+IKGZ?{^Yi7-h{SgDlhr|Hu>4*tz(SkM@D*<_Z(|yO;I=OJM%XTdwl-V zVUNwfa@eEu#}3;uzdvtn36K8t9UGULf;JxP5IAcdlwKrjT#?%b)z=RH?)-JbcgVJF8|x)pBCpUv4`*bo6x0m#^?>*j+!sq z?N|pMIqhgEjP2aheE}GFo@7llG?J5cw#c0O>jG9Cwys6;gm2I|!~7hG?A?B!5*Jo;3Tb<^0Z8_hktOPS-2a-P8i4;&d--eRkP ze$%i8YG#en&YMk^&TtlXjc2mQPrWMB)3BfO8RCzp4br})*U&!PEL_3U+3}ed`OeO~ z2-z(6$eHL~S<|Q|Hw^8VW$Vd%>c6eLxs*Y=!{j;4I0~)(7Mk{n{D=RK_)n%&{te#* zPt(EEI}dbx^N7ByHXWUEs_g#*H{{LT{RRXY5|L5XQV()wZYwsEqW_HmpDU0b<&HLq zTYgVw+t&vK+V7d6cHWZ_Xt;;9$UEMC^?61=>ul2))>20aTQtXgB2q^hx?|~wIp6L_ zCjIyybo~N9i4R;An*UWqSLLTqpLedx%}+%KIE*|(+l~(K@HC&L16+bDa2m;X zM+Z0@zsQfjP43bG8kgESz-Hp4?dcc(i#kB?FbqGu`%+`H3xT+o^}3CGqLY?z;EeM-u_uO-8=fv=0dIiOz+Zvev3Sr zPC7^b8S1V7ypK29+-)@#G#fNl>_E>i{ZsuSIqN7(`mg~zAF*wS_j`6mZvXMcDlu}& z2F@qejFvdx&TsRcM}CfKhy?8RiENhQvS%?bVO|@a*}e|=-;O+W$IL*(`Y#B-vGp^4 zc*~wk?Yz#qM#fD1<8WnP%pQlXvx@Gv%eYHB*R#%i1U*2Qu|bbyxmk=6n>p>Azn{Um z`SwcU-DTb4=?({{tQC|MWK9~Tz3`|Nf9CAIuhXvQ!bpxm8tXguSK+f%Lq7d- z%Yg2&mNNgr`ZA)+l(9*Krkdy3YrOrl?eaa-xc7;4Qf|E5YeBm7{f`Wl@{4i;GhQTr zo!pT^+nu`ZLto(d`{vuWU4p_+@mcySvd5c8d8=f!YS?p@YX8AdY=1Hw8W0=pE?WbG z@p1RV!Lu@O;dF7f09WBPv z0vmj>>wI6^b+$oE?et5=U2%t#Q%}pe>>s2FuAGf-C-6qx*hLy2M@3J+9^~#(ZM;{g{>k#7(v1+;D3iXv1Ns^npD(GX)zpY^x|7XyXFbuH`kFy_+BOYzQ+E#eU#Oin$zJ=KO=oF{&c?PPpMt}=>=Wxsq&{ooHcdxr=DXlMaGFS z7TPeA;QRQ4dQR|a*uwLK7qGS|wvU|I7v zA#a>gx)G)+TrLY@awW;fDkF%%fwC6$Ho}=9HcscFqOEwOi zu+N7Kr#%5pV^6(n$31<_c57&t=psbt|aEV@fscYm0+FqQ?_F3;1kamg%wSb>s)jTfDaW6VeMGlrl}qG_j3IHBv0u%|4epsQyvP-A}q_ zowQ<)B5ASh=}K$U#g9q*H0fHHgNIU9R)OMP#FW{yr4PsYSP_q*icNX}!VPocioKkRtwme@f1GtBoV47=_3f9SDvv+wJ^ z-Ameh`qDBYfL>ALCc7NZC6Syhe3QFmq^wl#gz(WGnS<{nelfBq^-il5JNX${hcEc~WY?O7(eU&_xW9B-(0akB}h zBkzkYWBve@EVz;7S2NQ2#+yj;wq|=z*0-Tx?b%<$9zH>Epn9>;-e)0N0l= z_9MVyHxK?S9GgQw1;=LL0)t*S=0EPSbn9vVuwgAYb}4DyIJWhKr%dF7L4UW?T=P#m zeC;vY9ZUMgQ^2uw(xo|RKL^K#lkQ|Vmc+Ny!LbC=_r$S7f4AFS^|sxo*L2_7n@^5o zZG7ts$KD~nFC3Hj&%-e{&k_E54`VF+M&>$nrM=c@yrs~MPn`>3@*ajl-j=xLU&N#c{@Zi7XSw?fk;$AbX#&~a8=K?QC(Uu3i5#i6@V1Jj z2S}bCXn5@Hj&DA~xfP+q@M!g%><2_f+59i*NY{KS`cr2v?Fr|9v{>`flrV3^rUuoD z2xSF^c^63C9efMN63;#kFv@KnX7eK+rL@kL)+pX(8g9p(AWp?ca;{CXbz72O{%RUx z7Ms#%=G4dt^_;|||1>70=2KsWlwC6py(avwhV@!0{fS&e7(0TR5zzb(?YT{K!n2uU zga^3k{m96D$UO$@7Vf~ljr%rUV9!tVPQXrZXb>>Eo-*ZZ4?5G_6VRs9uBJU*?aHTJ z0zb#TM9%RZ8F`>s#zqab;o0-s-j?q8=kTk*({`Ja8K*}0nCMc|k@Goo(<<|Dx?lVQ zTLsQ(@VYd3m^E&D?0lkY@oT@+*D*cTtJ1dtnm#RASoXS`Z2C=m(RM{vK7%x;Dl0ql zJa6*EEw2n!+96{MdUG&g>QM>juZJemA#`(aHVO4Jx+%irzUV?54h99 zoa5kfBRKOK;guqf{U1Aj&-wGn$e$GNgHOrbpt7IRmgl8?KJYaLe2v8x$=G7iIq$)p zKrX0KYIEJ6W;e*$x4J*^w$x*GxyTdHmc5p^hWRhdyq{&V2QW_LyX0k@6Uybzvgb^{ z|J-}fwFgH8o>S>*=PG~txhCI&7a{A8DaXK zFZpKp&#k2ml+iA7ztC+y{SVV$X(is_p^XkBr9~ z8EVQR!|~=_~Hv)dvemRt&}ZmZoyrtqn0{MC(QRvJ-%<_yUbD8A8(!eqrTSw zwfEcYk@c4&qYu(?HNZk-f8h;|j4t|tt@KM|^v3(_ylxqt`&YWneGctj3hy{w{nf-i zc#F&}iGQ`{7Qz48Z`f@R`OD!+$3Nv9)IV%GcH%1D?%poh3;8W@5m-8VA?r%L)?SDQ zSK!vnchNhD|995=P095S;5z$wJF0B?H=ak~wRzHO&@;88pL&05?29_bq?`}5Wo^`v{uN&7i+ z-y@_uncR0T-%dyF+eG@Fa$oWzcH5u&rroE(y8pM4HeYxhJf^P4+TvEe^(FU}5Z{;F zC-I*r_x&eiuW4tTT=wcI?^HospCwl=??GFqB3J&3GW(J%d)BR(?}4qgPnBTddKW#3 ztl`KeEu}GwJsafS3R_N;_$=a#dwSUamJqkajuYFA4{tWm-Flc~yv#AYm3tfW4ClIq z{-lg>F0{j1RqkzqwOe+iN^WzChS6vkLzUKI}1G=zi8sc$k!%mE9f2_XX{IVHb?WCc}Yo&v*yM zO@(&89_QH`#Eu?5mdjleo#)xbE=cU10`wzDe9trI0z)}-?u?HEgCn!LV6cNSojJzQ z+pZ7I9fKBBM*t5Y07E625!G|pHM(+2xj5diJCv&viN&PIius7lCjd|b$ z_irD6f;#Pa)ZQOlC+YS59zUQgnPj8@f2Gt7M^`*RbJQ9&TTEHaRx+at8e>fpI`Rxda)| zqKzBX@kbe(O71%5{jmC6_C4gD*P5AKHqcF!EAsfs&P<#^nV)xNVl!okUif6NGUouR zZ`rW=8#0a?RxiQFWsUu7-jh6xE4bnbL~=&;fYo;DaMpt-gVnvHk^BW#+UK#4Ra;)A zzNYCmuDp1YEq5S8ukaf+4>@PMdd?XK$df+J&XW=9%9Bo>WaL|^ zh%6buCUBo=s;k#7&6xgq=Wrx#n7p!T=X>HeI`W-`hqFHK4&k`^Huf~% zV=wardztO}-bJ~`%d#sfz)li4f1Q4boFVprWx(69@e}(uY?fGusTE>R=g0Qe_=+uO z{>iJh{F1R)OI|-X{vk4y@UlFwsr9%+>kBCBdh&h9JpLwoknP?FhqiRS71CvQeGzAM zMP?c5RSkJBOl!^Nz6ZJY<^${wf5@NM4t|X7U`?K7D>^M6dt~7`8>kPR%kiV!Z6L$5IUjlRq{d)e&Y25$AUCaR?D2X39-R+AT)ao9VIvm4VdTt|CF_j(88 z<&?{rU#r|2%H{6eE%Cfdc_C+<+?sdD4ey4f|Ez5+irl2F1 zbChzI?Lnn5owe@n$vK;M#U*|rZK&qVj?C*{K_BF{Ej-%K(WiX&-LmlVJ-~5BF76}O zPj8z-xfSS&<-G@k`h*Y38@`TT>Y62W(Qdabyu$iE{38fm8jhC)*vci8qDPWp5|b$!>at0x~Ye1Y~KW1k@O?xx4S(*3EA zbWR=S@R-HkEt&1ialaNBBp(@*c69a&U1R$_?1kbs)Q-0IbPo?yTjYLqf%BjE^Keec zDX(Uz%$w}LgTK-@cfb0YBLrV$K6v2kfwl|Lzf_{*ou&c}??D$$BLciFVlJzP2R)6v zv=aT<32?g|TuU{EEE_F4Ji?Oq0rW0%R{TA5f}%f@crPw@=sqRoDKnBY1zeN)WQboi zqz>au68_Zw-ZnFtF$0dyxf-#Z*bB@WA64AX)wSQ}+~wC3K2G23&XT!=`JH|TG|W_5 z7t9*ra{{wZDBBH}zHnUZJN>CTFF5@qc?DKgoTrg{KqEr$XWBSq$>r2r%iginU5EZu z@J#NZ6#2dhy}=p4LhKgf`)9U|CN2-XmI8k9BLDN&@F3!u+=%DBU-pNDx4lQa)Ma2x z**LVTEq`acn^Np>@|}UUN09d-+$mI{=~2wf`(Z@Op5)+)CfFg z`g4N*h<%m;->lKL7w+~?)^Y!C`@i}Bp#5&Vbof?Z^kr&0j6sak^I9(dfqtiC$|t@g z!QEQu?3dtcEqngYu>bw^kJXkA4{z3iV-{{b2t8}uYSClyfom+@gC1M3IqJf#A>GDe z2xD>7H5Nxm{{dt1Htv5KS9i3_T~WPhwkKcAeb4T@)j#-^(2e*F=*Z1e{VKJat&=nF zq}^!C>$k%*AC&P%H&T0pEss3~ECXM*zyBS7Cx1BZvv{qucPVQMhj-^wPhWh%w%ai3 zg%6KFSE@d-XuPK5qd2qwNjyB5d-(<_)m{fbG<}Lb;b**{t1Y!7)Xo9WbmK=| z`MGbTGymV5{N$?x4kqPrZkd&jkN^0yczhpn zhup6yYZ@7gCT%N`t!*pvwA?P^vS0J+=h<(OIVPVmNLAe3Ec}*zaXF82SY&c|B4>mx z89N@EAlCAh+^XP-l70uguODM3e!t|!o;sZ|G5Icg>S23aUJWxYx6B+O+}dkr%>{j4iOv05_NGkM-L2;%(_Xi%Z7Fk!tmPxpe!gGE_apfI z7B2V3gUcve?*6@k?*gMK#@#~)?cluI*}TsUe-F^d{X^N0@B%k$ZyVbq)&WiQ?Z@DR zJuln#F6cR?NV?}q_Zl#j_qQedL&73MH4_#blQ^-(ki2ogrEsrp8{}RCLLXPlKIRLw zJ(6kbK7U3Y$6nXM)sd|E_{--0Scisd4q|)%3+{J50QNCH8S?i zT1K;BS}x4 zFKGL#r{4Cz&=#8)esk6=~!<6Z;z$#e@pUMV>Yn< zk5)O!^$+1X`u?=14a>%22XQh6S>N;Y()Xu{9aXotdu&@^*-u4Q{ALhb5uW=#{(NK; z+4r~mW!tPjVcO?v++~>1X*%Uf+l3y(@VodJ-rAzfY@tE%LxXFfJ&U%%qh!);(|r&* zgMB*YqAt7m%+qXV5E-gxTO+!yheZ}X#Xh_HTGmHjrH^Ylvk`>1&w}rZY$kGJ7#T7Q z|DQ!zc-Ue1-^)K@U)JV3TZHep``4HJVZU{u;G3%cX)WVdjZjTX>1^{1<`m z2Kpp(fvj8Q?gZia65dI^7ir7;@T7O4@%NEqZTWO?{WIj_&Z9lDei6N=%!L;*26EQ6 zhHqw)BiqZplk%3ykb0BxPZNHD-_0`}`Mx_`PaQUQeggl((bt9BmXa<#9(yqC#Kz!;NiR5( zPaBpB-O-1o&>ei&iVH)B0uL##nexX3#jeh1&1c;)78)K)ITzr5mvWvb{%`E7Z@BJ) zwz0HrEahzA`&imHma^wjw-wG0%orO~Gg6hoyc>B49r6^$Vb9&tHt;5kZ=(Ckz@I=H z=TUY)>U{*9%}3Ys1h&-iq{-v&O4?V<_j$VfyQyy;d5X1rkJYXOt6dvum-OvQz9kT! zsuGZ+BM)U+yoP%~ssBpq>BrkH{fJvexR~(E?B8RnGsCt^RITf1!x&)llB*q({z@sE zJWF-mi9OmNFs`AU0?!&rOB)gh%UC#VY2ln*KjNkCrPN)|n+ge(Ep3}ecoS`Nw6 zX}6S}P1&+$9Zi`6hd$d$S@G0=O6{bqQ*I~aj;5^%Db={nNVevSF0`7XP^2JKEChMjqWYLNDb z{!h}$U)D-w-5vJ2o;M&GUcA%JlkVQ5=I(ju^H}<~y6&FOUGMBs&(eF;YYrY^?|CPC zlp>Ru6E{2*uRgsuL4AC0_dV)02a(U8Qtz%gIF$Cw+EaLr+@bw>chBEQ`kIK{zMgy3 zzRvOJI-lgW#ctGZk{pbYJ>Bl|x4`hw8oS&Y?p2U^R0%(ZhvYG@*Fwu?8hecNOLTr2 z0zc9;iwzetTJ35(uiR}=LfK9k0rWyAD?`>E@TFr?W-WD%NmH*1zn6KSA9cxG_y~0e zs5=q(FSF|JXWhA({jHhI>!jsd7Gv@QaMF!q`(t{avH9dSY(4K_@0&4ixr(&`<=64n zA8TaM`%gs%X-IvNH5&3j^IgUTe;Q)joJ#ui5IFK3aD;bwM6kXxzv>8}On`OVe;{{uXzlZSEf>C<8fcI^I9b;W zQQ8LMa0UH9CbQ@VeSwu0*#FO$ZQfKTGVzm{op;tt{xGt=q)P(_D*0}ot+siB=sF7M zi+iuzu^kq882m|H&EBr`*OFewEgiS7HG!o6zp3-rdLT>ZKaDnY>ip3GrS_rgp9t(v zrt5e3Nz+2#VznP!2`o7`jX#CH&iU4o!?&OC%@vm=aWC3&pJj{Vl+m;RT--@|twZp0 zj%EBC%w@6v(u(R?ohJtT}5`@ z`b}&qwy_?pvS^m~3@O8=-LAVidfL&*9QGa3U4$KR@3T@}Z}Tb6^!|i&mOhWW%1o2_ zV70L`z1Y@)uqJ4K>-X&4!{-mp_w0NV+i}@HkaHEC@STJ1wSj#uLs@gN*o4UaZjOzM zoOQ}){QN1B*QlR+7&~3)w{II_`>hpuKT!6uWo?_rJXMSS{KvFI#w@bXrf(Uu%NR3r zR8Rgps2BhB18*7AM)+$7_aa{jA4ab}`UverHf_jT0UzUA#tQaQxrbSJwxsJv+y|t4 zZIaru?NXc0P3Y15F87?quDt*~+66BR&b+{}Cl%R3@a(m6-f?3*Mb9X6XJDT(LEt6w zf8;sa@1b9A+LyVFzYtKb7#!%0~h3OKf(FV@s&F<;A?_&(l^-ytleuYkngWTNA7jL zql0tuwoCyxp0dyJo=i58et|nvoIF{R?fUYOIifkV5s^r?t+@tS_c9_l|qzaO$c*BAXto3c(q!(RlZJ!$walw;FyZ`tFIUX?8L z`xI%I@3;P|`ly#FM`Xv~>FCDTqskX~6*}M7*+yH>wpW+eT^9X+rw@67H^~HM4_NK$ zt`BjyNpz!(GuCtEI>~HHvuP09MG91%e zH`>?y`x!d9h8NF8USb_s4{p8)efH4FS$poMt&`(!x<#~6>*N~DVPb0 zCtthuo^!AV(0A8lq5ElsM>%)H8r)qYZ63r}iM%9l%M1PPWItZ$SKe9Q0q+XKlO&yc zUa{6jjAK6VwD6WRXXx?7mZqD|T<{_N<247f*vk?-e*dvG2V+Ug8t9~V(H!cdj8oO; zF8&Poxbbz}IW`Y-*0#;}*lWv$$KUN-+x~@i7*4t#Yg;G1%ssy+-MXQ=yw6DI=$3zF z-M?b+R=t58t_Pdu-sfgyUpAe4v}(9VYpqAET8mww%mHCwj(%~~T3~MS)^j{>JtvG6 zIa}^;jXV^_o(y}q;~Tl3?tYKC@qOm&YmxEWu=i?bE&3t;+xXkyku&k}^%>sj7pBLb zb5^S1U154387g*PWBLy}YwbGkild&pho*aLhK?C9{H(S6y(_Zt_cP)XmU{0VioRyb zCTyN-1_h>vLqjKvPU;HozFr5;NIONZCi2#XPxGc{#0)*_GQ+c?mT%nU(=8moCTZaY z_L^JHQL9838Bd=0{j&xnsO>qUuS%GFl=%3__MG_h)Z`3#ioOz{4`}O%4Im2|av3O74 zHPFtO2tJ#POPFyvLLJh_BE}@c8~@UUpJd+mEOg{Q16w=n-mdM)yl<~(I^&nzS_5r` zV^cO_gV@@F9F)meq^p#du={Bh9X7U4xh)>!C6AG^QQH1z?mc-6eiDPc`d9S&o8)X7 z^`O&D4lfDpjE}L)@^8ugkacoyQ37pf58RuEK0AYQFQeQ$SKX+`|u=*759kOvLcTLKDbVbmRHC`fTt;(pDb~e&K zGiLC{4POXUgJadg2Q9uwo-FRPtN`W}v4gF4^o2tX{>Z-SPTC{*;odK8B2LEhL0rMH z&!TyG6V{=5u}OSW(|nUn^D|hh^rHD2Tr__r_d*Xzg4V(R-!dQH8fR{7@t#v3e_o(^ z^qPc)dB0UFb}%mCxWKC01|oCwer@V`s@yuif9}0GN1(M2zKGu4ID1mdWopL#&>H78 zlP~+kSRr_DWU`v^5p*v1oicAECs5buL2B}4pQNrZDK}$H>_TXLlB7F2%}%?BvCTHj@C_tPKQ zCl-B-d^_|gcd>!*2KbxK)_|nrTzzhxMMKGq*I;NU85&B~G&HDwA!Be5SjyT!+}j!J z2>l9jcEGO&ZG4jNb@*ST9Yx?vlg5`O;J$Wg`t(%qFl&FQ1^5<`E&<+0|EE8K?W*9+ zTJO--J5K!npVzDqnE?3wZ{szbojEODBkOQkSDh}e*~a?Tp<{>Fyhh#sn|RIFUHp)_ z$ht@OyTl2v`6}*by@@M*JI52b_oI$~{4?w|pdC-^pP3`tv1@-HyY@Eh+CQ-7Jfl7g zEy!Fa=Uaq#R)H7k-pIWz9dBEAE{37GES0=*!-s1Rrp6?~v32J^#G=D5@g z)bSh8F@G_p?U{V$i@RtW>$&~W!`7SCYXmC~9o z<;SILG-J-*SkL_VBDUfg#*mk;fM>h%Joy-T9$~&h9?g|?^-}7&)q_nD^OC)<-&=3< zap_O3_htlU7m*&_UpLuR)->oTyRB)~)f)EsPF%?smOS)F{7dl58dC0?a@I6E{*Nk? zwG3-vYfaPiZKIdHhkW1sE$?FGv2}1|F8>0Te}c=OfJZxypC>cf0(XUH&qce}T(C!R1eK z`Hwy5D&OVb?ecGS`O94X1up*tmp{qnKeo+PzRSPc<=^b`m%024T>c3zf0E08?3=Fg zUH;uJ|7MrJ%;jI;@=tL2lU)8|54g&A`FFegn_d1gmw$oFKf&csa`}(l?<(Kr-|g~m zcKOR({sk`o1nr-Azt>u$9lQK_>%F51cN!M$EKn*%Z0Qw0@yk8}Hlmha>})1!zu4Jb zq5XfuU!eU*@!zifV$1uS_P>Q+HU^~3!}zb)e(vfUf;?r#{~rH-?SCEr0GOqu{~!F^ zp=kMkjsI!w=S=Mo6UC&Yc^QAc_P>aKkM{o*zmLU~qvAZ8qs{P-?|6jU~PvHNRE~gHEj85|%{C8;oqxkRB{zvfd z(*B3>|492E#Q(DPKY;&_+AsHAzN7t{@qeQI+=DYD5d$e{^WFG|Y5!gL$7=t2{9n}m zb@(~UWTpQq{>9pV8~&TLzZ(BK?dLr75ca68^yT=U(Ed{V&uV`${ui~s2>)-j|0euL zw7&p!wf{o=*fyz-?dKW8)Wcxs!$#shkE%1a z;cxVquXv0m5866H^6S{1W~8V>r3w>CP&QW5o4X9-al@6Sg8+}13`?q3W10LqwhuQ3 zsf(4m*jJ_kQ-5n^c~wTFh*1+H=0I` z@i;tSSInq7Q@s-N2E1yQY3?(}8+tkWantGvD$VCw%FT#~2UC^z7#sR1Ia-7)jK>P3nKcNIYSv z7MM$4O|f9}1>kRu0md|S20ZF5BQfGp#~^rB1FSs8W_R;t9Fx>5WC07XwRpo2{?>b} zzo5!sQ={0KdEGGCuVGBtDSg>9n|;o$UWs|w8xTw(?>HJK4NTnSBOU!lAGq5GOcLvS zYO^)TCLRTq}o^pJ4v{I(&kujvr?&A zPf{dS?e-AcNFgyW5WLNvq~;iP%rlA#yh*RbsK>o<_(pG1BMH2cz?-z21mcbOl4@hr zW*^>KpJ2ysA06Bpv(4BOYwU{cKHgJ}3lxn^j~KLfA1La9J`?G|A>-op5Q@iaVMx8^ z%U)x**YA)7eLBy|mi)L^U7WPZtL7z>r`m*(?S?l&7P~#dM)-AX7hIjL)b!cgXqGWy zYmA^&T?{CdNSjX>WB0|-?aI9v19*ilxA}aJgVR296DVwT=2(omHP&d0>1=?M+hGjZ zW0;6=`wU^OZ+LvWy#T7%s z-h3xsHTFw-r=RgkzphpZPWjUlp@JzwMEi_UTRp1Tp!3_{6&|D3MFky#2e%ubisH{a z(4V$9k*Ur%3jZ51zCFamXLK`HztxWEIdP(FYVZB)RWr4#b+9O!acCx!F{2#U>*`Y>hKXUK=OL z>*5}!FzKVk-{|)gAosX23jWw6sMzQHxZEhTWsEwmFMtg-8HFfgU-p>0W0@goz{j3s z@p@B`&1-zgkH@N4d`TEiMq$0{|}m!&4a>E@X?8o6DZs}GpRUu=R;v#spb z_@1rumCE<;;(UiOK_*JG(J=NhR=N>34$#zMv(`|RBmuGZ7{;!yB$OlV2q+aW^Hmn@ zC^RdL;?5#;J&ToET>O@Spae#>7-pMc9P27X>KUx&iQHSQZuG18b=BPR9(m*)4YTg^!6AtWyvl zZG7t%3yiuCVx?dKUiEI3Kp*NmxpdHs;CT= zhYI~mR{1MRmxoGALjF*3MQEIIB`+#24&59q_6JJ}{RP32lF~~5l90cuq$_*3Ur|+7R$5+3@sdt0UNG;f9NmxE<-uEKQOuHH!7?>|QAMb{ zV*C=)mlQ184P5j~qQdTpp@iSWq4cl`M3c+Zi*nw5p`A;_~9sCBb5=5WZv<7hhFcQUp*= z6vs%IACUm3c#sHCv;7Avjo&91n-s%R#_3l&)Ls4RUiLLPeV4A|JIl|mxTdJ0 zXi0HMl~z^yFS*2D8P?ss;L?@)iwtIG#a$UB+5yLc(z3Ep;g_l^ty-Pf?2=y1C=aeI zs_fD8oDc|FRC4pYqUA-E72VstpcE2dp!j?hh}r#PZc!x-mv(gaCnt2%EIq89O?JiQ z2A73EyCtQ;^1`{L1yy!!S;30lku%Gw)9y)b>D=a zXQ-l*xkc5XLc2Hqv`hTLef+Ce`}@u&Uo+hOvPf%IaZ$mtp3Shn(2`#51MYyKqM~Pp zSykl~rR6!=F9}sw+F8R+zOE=K&6Uso;4VX|wDJ{I}Hx+i`!I>^-0E}647gh@4P!!-7s}t1^rN01Z$^JP3@hsEVTH<5w~Z!|7!1U7ok3 zs;Iayk12%8F(DB#1fPFpQE9P-g-8j-#S%lI>E~5kbY5Xb0u`uhIujtM*xwK<&a2?- zcpG39YHp~qAS`)xg#V_}a=%JQP)>ry7c7wJUlj-Gd$4?*Ee&W#>978qii>UzS0Y?2 zucA$*Us_3j~wB%9a7g!^eSx9Nh?Vnd__sWjD$Zz4xxSPru@mosEg=Jn_ zR0vsAxZ>0e^S_k0VBVt3v*+h!&;GKyL3ooBfj@Kp93p2zSaxsx*|Yt{rML8o3)6Ta z)t9OEhN_ZfB}ii8Ur-zhR)okLEC`7>R_-qe-Qtv0R3h`E4pjiR;zAM6vi-Lp`pKsf zM8#ryh2&W5B;&i53vWW0s45TnEtD<`R#YIHRhIgt2lhlU*G{0aOJFc1NRl=|_=6Rz zN(%fdszOy%9xAa=VF~kfS7W4`2&_dVD}%*Fh2zwCs4cJh!YSjGJp}lK{;c6}Jd16( zFGSpxdD|MKg_Wgcj^A#R6Vj8E6U+$}go;*%u7Y<5Zw{$zgXJ@6qMPBA^pn6i ze|n~0BeuWvCK^m5^}x8~YXMoPa2!Y~C=n`@V$xN{IB;@qu&CIIps3tV*aPO95aTTH zRY?0qE-w#JtF*#D!GBYE>2iN(pGZLAuob@)Ld7>xs3qWo8^J=EjQz9WkOEV_E-$L6 zkYWV9?lLT*6Pda1!gRK=ei7`0R)G*!L1|TSp%uki!0xEOka1+-gCqYra)azU`Dyr4XIQ>8Niu!oy0=vr+lfN(3UE_bF|9xACCm%xb2%3*n_ zjCM&?c4cU}|CS)bXd`g2#4n;FgIgXfxf!U+cLa)1^*AdhbEuPTzOeGs$T}+=Dp=-Z z{+Ba?-%Qn~Snb7`8c3IFPF0~Ufd4u)4_*q|7Obc$63)!vmLTO9OYbwY{SM%OnIwZ1 zz)L}s~A31s1^K<9q%*~uNrz<|2m4d^Em{zI^gmd2-vUtA?u)TztYw`4Xr7!^} zaamaSp-iDCPdmQ~b|*8E5XZ@rWmbY4Ww5PMU?cbhmFQWdm@2zU=v);$6k@ZCamrOf zML{@JSOwvpZW)VgW^aL253-CF99$Of#a*j?8Mz=synMMV=x-^i4BHGB-cwX9^WJ!s zZSf18)$W(ADR5=9_>+`nm0)LcCIn$a7HGTA2EqkJuP~SIw(kqG6d-fj%T9dndEpTJDw?yXR715(D6)jJkuS|497Ft@r-di z7dRdnC9C%FYVJfecaoYrS^lY$E90mTqQ0!oS6@^&sg*P{q?2+>mn>x<#`>9r zY_By7b<&n=E*__l+B;bS)6w!EB4Q^Y%M$WSR$&!NQ;$=kh>pTO7L~}O|bk+E2mwl~fUhcJdH!EeHecq(&u2XZa z%$azhv={tCdMRI(goN;ap%LesO&Uc9$uQhDyv*>P8Zwkycl2vh|h{-b?(h zdky8skm?Zbge%#Gz)iV|uHA=r6gM5$KVPXV+{balxMRP>Ru1lN+&Wy*k2c{puH!g+;aolCb$>hNPW2JU#88t z`CmazE#LFl_`)sAXB!xIb|ISwxGf>25+5*>uNs>c+(-?3Ah@sG!_GDC=5Nqf3ExNi zaEl+n2=<#i&hsGU%?yw(GF7C^? zn{ji0N`Blx6Pjz>c|T|S88_=!z@0+_dtRmexYY;wj=LE{2Cw)?ZEY)N=0xhPmmvXLL2bLJ@z5x;5Kzo5AFdlqZ#*Q2K)qWVt-)4R!zzo zv=w)35@q3@;LuSn?!$iS!fhGF7~?jc&sa)00~p~(MpGW{fpO&f7W-4<*~!8^G?_o# zho?~%?mN?g;kWrd0~q2qUd)aVZgHle7ULe9X{gn>;aTLtEu2jn+{7;#>Mh*1tLf7t zhFWkPu)|$_J$~HRZ(z)Et8WHYxREe8ggdr~KH|3EHshXHNgcSpwH%8;?*LLIw#SijAW0BJ%B6QWTU*wi*Q+^1Lw)JRh%O6DN{?qVi=;g$|}t z-i5$xh8ntlhVp$pLwRnzh&EiRd?zlI%QTdyGN2NQXDXk67A9S@m2qH>N?3onGV9Pu8hF#Dy8~PWi;KXhM0GOJ9lATcbD=eZcx6u4dBW~6~F%LDt5tU6(4v2 zyx{e$)!zmVk0|qvTIG3p2Y9$c`4S&fhVOA;^d031{2ygJUdNd3RGzW*Dt5{f@Xsfd z5#FWZ=Y3BZb>CC{M(tMSfhU!5=t(vBt?#S&wjU^C-X7&KpHarXXOwr(US;gvs}dR; z=;yQa^I7HD_AL1DL*=RYq3T!M2tG9`Pw|hLTYjR<#GfkD-=xgIi^?N>ZT3sbSnv{j z=_S?g;$Hx}UjnmV5%-Gnq`#`-=KY#6IH+J0@aRLz)AAc|_H|`!eqDJV{;e`{e+N$e zUiEw94dos62Nkp656aW@2k7mO%80=KcE72NJ#Q*+ZL{)Sd{`NUhn44z!^&IvCzY`G zugd%K+bUsmEAvgOik1M`2V{(KKS##8hGFXrG~Ysvv#!scld06yYi-dNFP2_ z-Wxws0~UX*Vp~2|p531?v3{!J8atHXr<-AA#EtU6M?Hq&_Zk?i!25j0nXfZL7seWA zs5qnlJEq~ujfY>x8{R1iMofN!5jQMREG*&m{SBkAzY%u`UcK*3Bkov|Vay(2cn=LQ zd}U`DUNz8&89NZZH_(Vr=F)+&gAGqDZqr~R#y`X`rVKIEdfeI}MoilfOzTpNn544} z&*F0oU*$07fZ>Mct>K{1xrV1W)rhV18(x2!;eCU@Q6r3)1tZ{(BMo0IbHRyGMojK` z@YnOO-pnv!Ue7>Q7;D7c$b)-X>_Ti7an{je<}&NCrT~<+gEvg zq<rONM)u)+0%}I~@Fa69SJ6qF_ zZFf(T?LK}MkmPp=8nWDrZ1?qY+ugIycK?p$i2P!{YrE%Y*NWud-bOpV5&j}S2M@op zr+fHH9j?>qt;GE688-EYYo4_8bN<)*M){*^;@CCejTpX;WQoo zstzN5Sii67@JJortiy;U)^Dp0pQpnQ>hKqI_}e;sz7Fru;dCATFC9j#v3|RBc(e}x zK!?ZZaDxsb_E^9DI(&f+|6GR=hpgYLIy_#7U)SLYI{XJ6Mr^WvZ|d+Q9X_nXlXdvd zIy^;(|DwZ)Th{Mw9Y*Z3en)h8nhv+>@N^yin-0&=;eY6GrVbz1;h8%8t_~xvS-hMQ8e7O#PqQhA_+@ZtSI&6I3#Trw>&(q;J9llD3 z<8_#2r}gWn!(YaYpu;(KPz}`Kg*rS)hY>}s-w+)}B(;8L>+m%? ze2xxZtHZ-}c(D$r>hN_soTkIq>+nb&&e!4dbU3KP<8*k54o}nJ0v!(MaG?%o>o8)l z^~=%Wn{@aF9llwI3w1cG!^?G8vop0)hnMQ_Yjt>;4%g@~BDM9~qQfOR{E!YKYFod@ zbhu21cj@p79sX|}F4y7j>u`k*Kc&N!I=okht91B>I*izE{eGmwx9ISG9j?~l13HX2 zZ~cCz!?)`2OFDd;4*yDrSL^UW9bTiuztQ2Z>hSM%c&!ecj<744)4}s?+kDXz}9cr z=LBoDyGy%!wR=FjuV}ZC=LY2Wh7PxA_k?z>r;7NVsMDorca(M~X!m06W@$H9yZPEJ z)^4?Stx8@0Ue@vJwfnkuH*5D{?bc~`k9ObE?lJ9ttX*@9-LGWr`n5Y&yVJEhTe}Oi zd!u&4+O5=XM7x``yG^@~Yj?MH_i49DyN9&ftlf9C+ooOLz4~0Ic86&*p`5oH(gCRC04=I4@LQPKt?hR;tJ=&e?Edv!u$+ z?wL&4@z>0sI3X{upt?G^q-f>DiPP{G2P-P_Dp!?-@`_4sDxISu+l>6AzEV#jXGKvT z8O+++GjxVt)kf-$>82U^b{h(d7pzp}bw+Jl_coW@vRw6uqoKjPva0e>-pZo#%Bob$a0c|~bSu(+slRo==8Dzf`ir>4z=0770xWw2mbUO{+S-py6P@h>5H|wE13DmA$VOl*q)kdpw#R$%tn-eMy1uH^ovnn^Oh=rBq zMI|@SDh~xKL)R8nhG*Fkk|4>I;PO!A%vF`43W-nY9zV|-bot=7J}kfDl4)J=FA~(M$o}liI_93pmcdzusk$p`SJx<7A%(* z1-cb0c(gK90Cwk5ekhOh%S%hL=Pj8yXO4WU440SQlIO;8Fq~4dx|cFBPqKG5@05#K z&`C!Vi%V}NzePr~Ce5L>Qq5xL`@ar?siAT@1^}eI{C~f^3xj24p^`$Uh2j5biB==a z{u4!3R21D@;xw}Q-!E}SUf#`u3QJZ2O8E&mBgTKA;IgWUFxXSDY>qYLHUEJ!XHA@w zbLGORdD6zs|AF#?3%knO)~&p<;!`C>q0SyeoSTGTDyw> zkG=N+kE5#h|0jQ1iUcT7pg@5DRSVQ>QVJABP1~eRY?_89g^HDAlifB;x4U6?Q&I#C zSfN0?My(R1V$doT3KXqaG)Ta5iBh0q(IALbtMo#ZBE3?z>i6?GpZ9xnGEGZF?(^K= z^ZcgW$-d^C*PJtF&YU^(ck8kjWMk=N@uW0UZll|j=h{-)N5s`EHi9qOUBw;rGFWA1sc<6B^Kw?-nkbYLo3Nty5O%lt@!5 z?Q-0uq}4>)yJpuwcDpH8#nLH_-J{f;NM&NtxYO6^glHlXjXK<5=wfL6O~$#5^%y-Qis$Fg=Sx5}O&yI7<5IFxk|i$oii#IhM# zf$_z0m(V&tY-wyoL$lj6skXrn%ES_GUYmwa95Syy4bw!Bjeal}YO8W)Fkb_Xvk|vK zw;QCf#5;+$#JhpA>(Q+31twWOg*xYKI>`b8r<+^c+U^2N6xF*Gmk;Iy9gVz(U{sL5 zu(o<`aBjn;Q_gE>(C-&ZHzq2ZO1&$;y2#>Kc7^PZ>Pi~o!6PRI$IJ}w%qtK6kyjNw zn?FAmJW?=AcHF^Dg|lNpa!Ox(d{P`2A%rmr@~ZlOMWc)*%9f;mBD@E;+aTOA{MNg5ELe}GgJNy zewtq{airhj68zh7)0a!z5^uJg-f;ZfNNaUug>1B+JH9Y*FQdxO1i#Hs2K$Z;Mp+(a z#I(m{GfhZS(pyj-$wubK7SB$lqQRF&T_Q!8y0R)cD=l$?&mUczXp>f{BB@!52K!E$ zC4DvNdvd~>lM4g)HmgyQs3lOF%EVoZx3X|aTzX*X;8%wxf?rM0Ek?_xN;+l1z$x)$ zJi9=e&rEG1l8gm^I8Dkz-!3%<*$G}Pw4{UkPMRK1H>V?uv#w}2o;)j_&SYyM%csYq z^A^`jA3f+gwK@`-^o3I`MzH48x)sZsQinLTI~v_*++SRgh_p&OTCc6xk50chc;t-gNK!iPOJc!26N3U-bHUF? z$Af!L9kgc6t*ekKvm$u<)L^u%S1q7SuvcRJWAx(S(}zZbTMu0x+;M1A@Y6%3%)g|| z*e&B=bS!x2ke1-CqUPYC@$qGC30YWf3Bg}ZZ;eHkqI>?&(<94Wp=l2~xc=>0JkK7I zjLwy9MzU6)!kX(kIXJXD_~957z|W7gg_qSJM;f+>eaFmBM_OB?3fD<%6bt_Amf#@hQ;9rvu&@usiqc>6ab-XZ0|kKV>@mCKf?Xb*l>Bqdyzj4xg++sVsC zRzAV4N6Uunj*6rfxa#=N(`F^&OIotksZ=Zd;F;4=p(~|QCu9aMObqg+N=$EVmKBjo z2QR)&8jD=?pB72}?$BH(gPRX))rQq=ds?v5lTmk|wC#kTAT8Yxx82@%SVj(O+=>pK zC`zOv(RodmO9v#_^Y&nLd2mC~eoGYm&R?EaxjeTYJxuOj4Cj7FDED74@^k;J zntNvHv7)xDG*wBfY?v;PMI_~?8&P#T= zvRnJq;e&^YFP{9_^l_IBCuUd+qGoUT7Yvizdx zqp`U>dPG%HdS^-LW9>dxc26e{7Gm%m3ojU$Ses5Y#ezu&0=W2KRi9ZJx9lq|rX^75rX?jC#b{NRscgHf}CRbvOEb{r*p z>CYa;J%sFt=BA>tV8c=M@vO}0{-c6?rtsyl>Bw?9hY@tjT-W`No9nlAu6xE72CHA! zJazs>@|178t4#3Iv8i+-TA$K#PXwPB7v$Hbr2iV7*Om=-j;%_HdcDkQ+h0}P{x==( z*{9=G|IqQ4f9kmN+I$&zUzaa4&cv^h3|7aN$uWI!=TUAEACWn9eL~}`TB+lmZoKJ} z`n}_NwPbVldKx>9!tOHog6t=^xEOlYz}9em%677!K3Wz6yOk-?V9POu!I~R%mi;&C zxbJ=)Z+$>!UuX?PCU^$>2{XE-;a^~xAc3_@vxb?#QuDebRe9tSA_yud-bVHbX^8_jf+HsmnNo` zwzXQrlL`JRHL~+Mi8s1F9Z6;qZOyS{wmgzvIwRE{{LeV-pZ+$^_Rhhz$1>N!i>FDO z8r*z3=k!OJQ;*E4FxcqE{W{kI>GPD!zBZYWEjJTvJa(|B5v)8FJ64zN9j6us&pRa+ zJaeqfx%YV8>Sre6%}ZU2efM~2sWQ@0K%QPYR=S0^O0QzKOK#8gF6kS!jBF#Xi)FcC z1YbT*x=_;jm1gK`(yHzFv_@k)_wD1N!B?dRGw>Om#oo_pzWrX|{|xOFUYqL`dXX~0 zr=*A2xmxGY<;JVsxZ91_$T%3%)4cz9=@9GrtC@0i6>|%C$9O3~jd+OLQ%UFW*72_M zc}YBxm=PxYHEF+= z8TD(_g5^?UT&z!@kPP}yY}cdMtafC$5B!3Z?G`uhmAC4=UF2__p#4_%dY_c_xN0!4 z-vtIcPLU#&sZykFyxNVsHQp#Ulj~2^y}h)_OJl(&&zKS1d`5-zMz>6yr)~VxlI$9d zo9}wu!R;reV~aCxul%a)leim~uAmf5Cg?rU)x&2e$XameY;&$Va`^3ua^_O|s%U+r zVK_M`z?S?8cHx7sp3J^guvfC)b+;xiYhY$uIxU4{@m;s;u9HxUH%cZ~ZIgHfvr_4* z+MxfW87qQK6Ed!6evh*u0B5eGFM&7Vn zqel?iS-xlWpqnC#bj&ya@pHPv?ikB$fS>UiT{biCxeVr`wcX z(Fpz_D`3~%g?a8QI1W>uKE>vK=P8`~Uu5pjZ_v5xp#~17GQpNpa=qOR#ggA|x!i5i z@$Lt7yz%=w-qKr`XT9t{NooTR>a?9d&~fL(I^M8F$D7@Fz>RmgamN!neYG2Jkg>E_ ztwa0RTTV^8Q`akk*QEqEyO;xRyvvO{o^*4Nagfi$lg}3K*Q2dUN-MBjcHe(EU5ZE# zk=7PhN2Jr64DKwJeTTCAO< zdO61wi6<9+=+dBD4q9a2(5mOOZayv7S^JExzNa;_&%5z%H{SVEozn4)jt73Fvu@7D zm&dqonJEW*+2EPec$DgPkk84S*1V|3HaFh-l78RxvX1xe((#5r>$vYPI^McZ$GiTn z^R8-6>CyMHI%&_c!Pif(jx@;*_b%CJI{u-t)^&`M@uq8ayv2>TyYU`3?)-vI?{VYx zZrpu~PTA4z#$VL&?ln4I|1}+Nyi>>hZv4EAW#i3erNGymp=Tq5|B_C*I~NjcID?mO z?w57E+X>t6R(aojs@b(DY2f4twmBWQv!1^@LynQ%zI2_m99`ei=v&=*-$s=NH-IiV zI+xX-ls&~7iQ0L;M&0Db1K-u}J-u#<8?S#*zxTQE`XA``u7`BI-i^0Btlv9+q~l&U zUi)MHzTpW?QV;gsacjrhaX9k}=?ZlG#Q9I_xO1nDcfO?KZM$^5=~XrB(`|BWTOM07 z7k&BQ$+z>Xo30UpZ8EoQ5?|)v#`|6!l{Y=JBH0}5)Go&!4cYiVZr-o!c=caK=~8%BX4EiD)(8J*PX}D%ECn@o5vJ)=1p+_8wc{_ z|Dxyf`ty79Ydb`$oZOkWHm|k5y1Sq~x+AZ?y1h5A-u>;)tM6A{pI2YoQd?UuR9)Sl zzd3K=>iqiN{9So_^ZN5T^H$5h&3S$Dt-Zamwz9f*on&G|UcJmG+AUxA7HrJhmcKQ> zuV8I{c4OY&{Hwe2*XM1|TQ{mJe@*`8{OU!C`o{Y9)}FjY{dv6wy`w58_ZCd8Z1hKs zQ!9H5I`gJhwoH1ypeL`swXktZVMqR&yh(+Hg?)wN$G4VMPVUNUZyYx`l$7kqySk(= zzdtXL=qgxLIeB7F{y2$l!&v#VX*6m4_`dwYlC1@6@-`QAkKR(S`>^%-T}Slf^%d;S zE0Uorzp+~uc7rTvXI^dLgb9o4YpXZNj92AXSGN>REZkABXkUI$!Pu^RDVs$r^Skn^ zWl{4ASLIhujz*`|?>JP-S_)uyerNvb!k+xDysN9PE-5PMEm&J1mt^w>^48|}t+r@_H$Rf*pmc3U?H4%C8K9GfxbHQ{*UalYG}FgpUVb11<)C8N3zz0C*Sp8Q~*j{$u9Y{1%>Mycv8ixU1U2TPIlf!i$Z+1>SP0 z@e|-(;Qt1yxDlSu$I?maAmP^dDOy_;7;(3!s>4Vf9o{N zFJ|%YIo)_C`1v!87cRE&XC~VG*Mo0*yM^xs{|wyKV)4&>hs7TgH~yforeAxx@y+11 z;77r`!G-U%_!AQre>!;4GUMyP8^D{v`@n}xGQTKg@hicTT8&qMuLeI1?g#%9yz2^! z|K2lgeq-8j)NcyzD8Kn-v@pW;T@|i{%^qTHyMwetn&+k$u}FHBdmT$r}5_a{`257-(~65f6l_Igf+db;L8!deYJ((2JZa4@$=xs z7mWW29`{A#Q~tx|Kk-Y(<&Haom1~Tz7S{A8f7$q6gm;5q0$1N=;b+PZS7?3h0WWqO z1S@+i{EOh~+l}u>{4rlMt}M3nHh7E@m9p21}-YG^!D6g;T7OX>x@4GZUz4e zycK+Esrj9ETKq-eKJa?*n7b_eAK(`71yjtQc(;XL0bU611^0jtJ;&k)_gMVd;NE+U zZvju(VEi<=7F;~l{BH22;QDV_{BMA_gMSGg_iYP*=egCBs%F_&i*_`fm#jo>jC+Wgl(Ve!uZ_kyPj>++0y%EGyP_r|*rKIui{ zg7@3}cJ4Gj89eac#_t91051UV24}$gz@Gw-f7$$RfZM@81Xusj!ncDby<+@#@MQ3b zAF%vYg3kv>!5;+ofg8c&cH8_`fH#1@0B(HM!tVob0Y3pQd(Fakf;+*5WtN`-@QL7s zf42Bj!Q200Tn{eXXPgF)`=@a?xF7tW}*6J>bM3=1yef?L4@;O~Q1 zzQ^JpJ_pMWK1*2Z->&yscnf&ig~s0mcY=QpUim%?KfBue0dNxB^L`7zS6It?>j#V< zcj0n;Io8m{Po}taP3@+{}6aB_^;r- z;PWrC{1?r$_#XoAtu77;}5s{vqRS2;X*@@k_#5AIchxFR3$b0Y4zD^|7$g!cVEU<)08S zelIxM4Bv4_usde_7{c3^7_&Tf#*JAXC6^ojH~dB5uP(6k*MeUJ7cRBM@ecCU#^Wxt{A|C*crm#6 zW5$O!Sa>U#>!n#3+X7jgx!gyTN!lzzu{7J_h!G)`guZdawo|}xhJOeiyb9v;;6@yC45;vWy51U?g73BC~A0-gt61#SYb1Gj&^6T5BxtPcypTpugJtKfHmZw2>&Ss(itAM0x?nCUP2qNT_B zyc&Er=GO=2{KkLD;$3y=5Yk%>ej2&gcq){^h?1Lz+Au6z}!CS!L0vsCBfyt9KPNzsRPS%1DNHr70mM4 z4rcjGlN&8{;PxH`bNk)~=K9|QX8Pl9GoST+BADxQDwzI4@FmFq)nIPVYrvd;ADH>w z0cLwr@)b*;%U1^G`mP1DJ!%AV`|bj>K5PPCj{I!_UjyC_X8qg^=JJf~vHY<8DF(AW zmJ2Jaxk}_Mc}VW_$i}1f;k&4{`bI_fu97ogLmot4wLgyeHK5sT>Qg2f-dlQ z@H+5h@Fs9Mcq@3Ju+DEMIDzo~$87#LfwzO#Y5c>3pg2F@E#G%FTzC@rNrX=Z??reC z_>iUMPX(VOto}6c8Q=@SCEzmfg~~?+K_z$&xElNsa4k3uUI_jqxDotWa69;`;4bie z;C0|f!F}MTzysiC!MnkQ3Cr)80xPdla4}f!J8;W04ZI9o2F`*j!Jh!vf>(nVg4cjs z!S{eyfqww*0{t(@|^%43!VfX5553g46X)G z0$&C$0k?uH!PkKs!Cl}EuwGZv{B?u-!9Cz@;7#D)gZscmN%IH5#o+DW^T0d7^T`u! z`6J-q?Z#>Fc<@Sa3HUSMO7Pdfjo|x)r3;xGei`DIgck>S!Jf=%O&UqJT0PZJRB6h> zR1oN?4zh+%luxwcKx{&n!l^e2UUpVjY#{}uRT`jbPx z&+7Af_jlow>DTKQ8T3z$jC@v~*T6p8gtqGW{_!4;_@%_gQ^j ze?P3%)*qSv24@fYKC92`^=HE;)1MIXeO8~>_h-W=zmeZ8@!#Pcue5=AymEtZG1AsQ zw}trb5I+>+Z6VhDM0JEAyuG|A@%`;*ukdi&3-4dJ{0b{?GMCq{pSr$$*77QuV;T4Z zd@}vj$e*(MKC93BCH?`QOn*(t_gVeMYKyQSZTTnD_v@#o@3Z;|_?N>c)7Lt$gR=TQ ztIzv8u7OXcf3>p*eV^4Ynrji>pRxRt>HGQB^nF%;Jp4NNWcsT@>HDmH4}5uK(Y2Rk z`W+$PXZ4F~EJ6xCnf}U<@3Z=A;a>xvOyAFMjZE}e{mJtzft%rz>HF!a@3ZvwERA6`rF~(51&lGJLLPUe!HBP)ZtP1Wcq%3ntz|wFP8I+ zI&6barthbxzR&9Gc}*RD3!hBiPj9&N8|%z}6+W51pWblk?}h(Q_+0KR-gB$JqVvne?rLjS$*EmHUOVY-%qbbCi<*C?|<6^ zpG@CRPko=&=lya=w%Ph8)A!RGE`8o#cQ$-7{l?Jp`>g5ne!MyG$@B+8zR&9O{=KE} z$@Km7H2*%U-zevub+{QmnZBQ%`aY}A`vdQSPo}@fW}mBnKC93B34aWqO#k_i@3Z=? zjTYg*;gjj(@>4E-pVi+KG5@dd$@DMOFEZ$#8X5VlKJRxNzuf8%S>sQX51RL!@3Z>6 zKl1nR$@Dv99y%y%`W*@~D67x=DWAF0(kE-Urr#kS9h8UjdH?0R+RZ1^uXOgH@3W@Q z`!(y}lj%^x==1Po`fV@_kmH_osgEYV*nTt3$re>hpfq)HUXl>Em>CZuxyypZC9hA3mAB ztQI#Y*T~3c^?ASS5g)Vk$@HTkpZso#ug6Qgels0B2G>*Sz>~l+a3#1M+ycHCyb639 zcpdmYa6fo6nAdN94(9cnm%zM!^LH?>-;DjZ<)7DY&H(fJ&3Ry6zo`QA`pqIRuivD= zynb^XnAdMU59alobzok<`97G}Z=MA6`pvJwyneGsxESk3|KxSZ@*FvMerqh4=eJG+ z^ZZr`nCG{2eIM+2bh^anx|gWIJmKMvM-y_MSBD>TSbZY1KJ9R!gYA*eS|548_5ge` zeSiDY`s}m%yubT|Yb|{;eSiB?-)HrCKX@H{GJSvhQQv3vTjV^d4xfcjrr&G9x$W6! z^?CpKJ@Co&{pHp4eOA9cVF|nppG@B`Z}ojvpZB{LU1#M-rthaWT>88}{v!Bf`hIz< z@3W@Q`{_RopG@B`Z}ojvUtYN7hNt0^>34_9-)HrC|Nd+6$@Jf7`5WcDnGRDwVdY1r z-*3UW_3yK$&*ufI;gjjVQTlwopc6iszF*#2em-mZd>-LZ_+n%99{64GC=O0dnPp1Dy%U>qvadh|)(+AV{`)`_mpEdn1#81E{({Hia=ko8f z`g`Hu0G~|XPj9&NE9E#?hi||qkJRsm|1f+q{WmJVUGRSnpFC2(ENl6H4L+H^U*C24 zeb(~h^Dd)4Y4wLp->Z~nkC_giJW{_$jw5uq5g5jl;Z#$ZiY{$ zzuAIw^~Y!R`8>~U@X7QShJ2sZFT@7g)>Yt0`A zpG+T{N3Q&RR=*4WS@6jt^~XrRL5JD!$@Cjt=-~4Etm(JFkHII?f1~}!CipAhlj&E6 z()U@@4`jcu!+*jj)33JRT>1H|zV=&m_!@jN{Wr@08u$;uC(~bNv(KgPv!>7I9e)C! zOn+s__gVdZOgL_p)ju-*4I$rW_4$0|+3?Bq->CiM^O#BaWcq%6tF?DqGUy-meO8~(tKI>htnnwxXQO;{pzpK#e7^M=_+7Po}T;Wcc~_S$#gAn}$!O zpEW&~f1lOo^SqyhPp0peca5g!%};$k|N9;IWcuy;MF#z&zR&9OdEr08Cu@9N|L7j% ze4o|l^TkKpjPn1SNHWmJ<4QT-XZ86!^1I=a>94oh<$Ryj@BF+)XogRwzdhvptUjN2 zz8yZ9{&M{kBtrtdGW`aY}A=c#`SpG<#(evv`{sPD7-Ww*NE;859a zv~H3$zOKJ={UU?@QQv3v`TX|D@W~oq{c8E>K;LKex30191@OuA7g=!5_gQ^DFTNB$ znSLVV`>Z~nFTV{wnSOo9_gVd2U$zL(!Y9*j4Ea8*&*#}+hEJyNr&l8reO8~(zn}Ff zTYqHw{{BvVpVc4#70cif_+Oo)%RI_z8~OO_+x`h35^Mexb={pHp4eO90EL--VYGX1Hc z^nF&J?@#zI_+ieud-!JiT_+`u_5&@3Z=RKgLb)$@Kl@Ro`dz z`96()_+9KHnemPU-h)|AVaYwf*#$SACz==le!3gHNXKFR%LKbrN5% z$MSiu?}Pa~*OOpA&-H6CpXb^G=JQ;KthV{_d9D+|e4guFU_Q@P2IlizbznZvwOILZ z>EGb_f-d1=DGv@kA-*@nKMe5`A^y3rUjHn{4Pq~Wd4Il^UsOjJ!uQ+mllV~v%HJcU zA3falO}_u-6B4fLm#nka_1l7ZDC_$1S=TS$7xOH9GW|&*-)HstewlZD!O|zwe_p@H zpno)dpVjC4Xu9B&HNNJ*M?N~x?{Q?TKHpz+CwwyfdN01F@3Z=R-_4KVlj*mHe4o|l z`*B`?Po^)MfE$!GeV^6m`*dD|Pp02!dT#lBR-fH_2;wZpYK1~1D{NPe5m|=R-f-nn)O91 zfAUCuzF(;uKAFD1y=eLStm*T8Opm}P(=Q9<-)Hst{-)RAlj&E6e4o|l`<_nzk}W@( zzTcnM{QImv-w!nnKAC=3D1D#R=li4{hfk*89`b!wzp~FFoGa%Ubo(LGZw&e5TP41` zUkcAN-wo#T%nyP2JoD3FKF|C+FrR1E^bWQ^+bi*-$cz3tL>dC!pS>1(-fCT+MY>YL zb$Q5Ko^ckOYfpUE^5}*CDfr}(`di`mz$cH?-vPfDK6#}6Uie$!lSk?oJsh~<1^DEV z`o-{f!zYi_p9;T7&fDnvBahUtgg*g3d8Ga#_w~N9yl@|IXX2{K)iogwpp})93r_8sU@a zUmfzvAD8&W2-81zhWO_p*7+T*ybqJ}W`22}C_G$w^L=|aNx0S*GV|+~Z;ed!S(i8a zL(BAI@X7Sc^otDoM}42w-?-TY2hYJLYy64w>9^pV@3Z=RKj3coWcrDa@3Z=RpWxv= zw*2Ig`h5T3+3?BqyY!0;`bU@FXH9>{V=g$T>Op-2YkXb)MHZa%eOA8=1=0kcOusVZ z`>g&d_^aTP>HGV8&A-p;^L>h6gHNWf%bib@aAC)*93T_{M|2lx>O-Z=cce2i3^H!{1WY9mFU!Qe(_x{KQ2iMbO0Lq$wpEdt0pRn*J;gjk6%RAiiuY&&q zeDX;BPWZdvlSk@z!T%?G@<{#F@W*}4wjc6H{ciXr@W~_f*TA0(pFC2(2mWR7$s_gG z!oM0mnZAF1K-a&|T7P=s-vXaJQhyu#@4zS1FVinF=pRj={Jg~1<5j*7>lNW*jfmkN zAs)SUX!zkF*7+Z7e>y?pM>%u(d#3Pk{YSnZ`4$P+{V7@JKT$q~n1}Lk+Y{fXycIr~ zzTe+e-)CJPl}}j$e}zw`zg54;pnuf&S$)2*dBWE%|74A?`ClU+9q9Y4KHu-0flsEt zS-*I`&+7Ai(2v6>(;r_j)c0BauAf=>tMJM6x9Arc^iPe9d{&?DpDy@@Ek9Y~>+a0SSA9BsGX2T=#q)hupYOL`0-sEO>>)#apVjC4upfj^rr%?FF8@BO&-Z6P z1D{O4Prt~Ze`;jpv-*7B_AdBjjql1&Wf|!2Hgv2$-_Jez4l92${UR^Erth=*e4qD3 z_~eoLeE;|R;gd(|^L^oq;FCw{k9o-!a5;Q3{jvH*2K}SU@3SsH-%tK|_+*W*<=-eD z9q2bYGFG4OGrtEunSQqyU(@$l{js|&!sGDC^l`Y6OW$Yp2jFjqPo}>il)lgEulj>U z_$z!e{mmiYXZ891_LJ6G{Ug)w4Ea90{QuD+OoKlFre7QKeO90Ei=PXhOusPX`>a0S zFMm0FGW`i5-)HqJU$F=`z$cH?=lko|!Y9*T6iVM`O`q?(|1Nwo{rZsav-*5L{uA)Y z^!@U#k%>O5AKh&U{GRy-)2|Mt@3Z=RAOAl1WcnLIzR&9O{rx9=)9N3Yej?=itUllO zKNUWCr2e!&Spv22$@ItQ7a81Vt_4#`QAA?UGsn6dp z_!4|F{T9iC4$7Lo&o2LaTyU^~`3KW4vf!NWv-;JD{~&xaeJukWlr?>y)o+FW6nrv$ ze|uNoXZ5r2e+{2Ze}{gNLI0@lv-t9@O@B#Q_jj#S#3(omItIyxJm=B+v z^Yx1i`bX0b?|*my)ddG>_+5G zeO7-X{0HEZ=@;r38T60(KC8d!?=Coa3O-rmyYkmBGUy-m!{yii4;LK#20od--(INi zv!>7AANdP>GX0G<`&{}ytKa`mi*V{)R)5L#Q9X0M&+7NN5IHXdpG?0nl)lgE^Y>7a z@X7T3_O?bQ`m8>GKcyc&nSNy`eV^6m@2&h1KAHaHkngkl{C$=~*IW6K=|@Ap&+7B{ zTs{b&JW`*(|8g6AGW}_x^nG^uFVL9slc{$j|6uz5_EsYkeO8~pFLOD3GW{J`;mYd! ztUiB_=I8Lq^gA?jGSKgEWUM}azh>$^mVa{2*Do^Ue2-oFZ?g$shtJ=?(Ww*lZ~HALoR7EsRXRHRSuOK7UWA3qF~CQONgMeg6K=+oWTqc_Y&wm#<4dxcok=&)@6$ z6nrxMV*TRzKC92)_qhW;nSPh)x$^f}ef}QM@%LH&$@H%d`97=9-w(PBKAC=X$oE(ccK}!~5mefcZZ9d%=7k{Ucz$kNz1j-$%a_%=gj% z4b1n^AMx!VD0U@lqj!Y(J;LueOt$|%EB~5M_~H;>72?l^_#47{KP%q{{=HE6;~IXX z9PiQseXe&zj4qWz{WE_KAFC49e>JtUiA~>kshB^!@aPOTQE8AO9W8 zKbd~7evv`{sPD6;UwN!Wco%%KPSyOcwcwoZv--P^vk32lPo}?J=AnbKroUZ524(g6 zdtn#BCu_K-@3&9t`>g(=@ftG-u7yvgKj1l7S|@bSKbpSJ>gRsn z3_e-oYyQjhiwycleV^6m@1gC6PuBSAXXT>SQk3D{(M%Szn8ZS zKAFDXKhgAkR-eDG_bPlc{Y|0teO8~p$9MF1ZT*o)>ht&eroboD->P3^&_9}gpEZ5{ z-d{C*vc{h%AOHA5eV^6m?*pdclj%>EdFY_5zR&9O_XIx$pG?2q*@M2%>ht#pe+HjS ze^JOM|4HI&e}}&>GfGyBGJjuYJea>PbGEYVKYOr0Js-^9OQ-_(Av^`9~ZwY+`S@+yaaB7E{l{e|$~1)n@p zKLNiIK6#{m2mB`Z-ousuX82!%Padg10DmKV z@<{z%@VCMzkJJy|sWF4#CHUl#`s3h_{+`ue@<{zj@K1tI9;tsJ{1W)&k@~gpXTv9t z)Q`fy6h3*Remnd&_~eoJ2Wx*iWqyA9^F`s|`uqHS*F(N<>yOOzOG4X^&$|8a_h4(_ zlj%zn>;`4setcHH56gcid@}uAA>U{9`TMhd@X7SognXaXuRK#@2Ep;Yw)|xJZ?yd{ zg8y##9>dS@3ZEAC;Sh?C)4i^`97=PahArEel>hDegFOQH8Rm>_4#|h zH^3*;_s^%R@3Z;?@79<>@Ctk~{mr5KOMF&;%{k`hKWOWZOn;i2`(S^=XZ5$iKLtLS z{?#`7Tz|)B^=r?y2vgyc>9>T^_gVc-@aMoM)9(xUKC9n;p2iGuXUk=%kQ)L z{C(yOd@}u&A>U{9`FqZ{!6(!A)2oq*KC92)e|`);nSNs^eV^6m??wLxKAC=3$oE-& z{=W3z;gjhXg?yjY=kHOU_5-VbWcu|X-)Hst`_(tXC)4-)=QT3XXZ87e*Z0CF)1Mql z-)Hst``AB*Pp01<@_kmHzo&ibL$>^6`s+i!&+7B{w=aiJrtjC68ky*``rF>4F=aml zpG<#ID1Gv?5?_xG`1_JCgZcZCe+TpTC6Da0`22mz)4}|G$#cQ{eaT8Ne_!&$VE(>j z63pM1yjHk47#wa4@fSk;)ezqq;@%Kzc^s_2utnlWB@Tz5^&Q}N<-Jzk(;v3=T>{pr z6Xhe#xEqvpefg~Gi@&G7;9>L08ejctXAiblKC92)U;i9@GJSvh()4{+pTF0>4L+Iv z)KL09tKWB_#+2*nk68Z6^f!lmpVjB@!@mPQnZBRj;quSllV1v-OyA!=)%RJ`uYJG9 zl-GX1C)4-0FZF#^pTA%KID9gFe|@R%v--P`e$fxH{=xLeh04!o^@9)SCN9woC)R;kV2YfR9eWCPy*7T$0=5K{h zrtjC+8ky*``g`F24L+HEe<*#Q)$gs)m{PAFwelm=_sd(;_gVe1v&>%zpG?2kf&=}d zzR&7!nQale;gfahMENwzM+ar~8x>?wR)2D(ev|Vh@X0z=eZPOEzR&7s;lJmRL1DL;`{X^kmq@{nJ3bE$rVEvunOZ=$kzb-u7`Prg5 zI;S9r_uKN4xxC{r4`nScpS8S-;a>xvOus1P`>g(C_@9AKrk@D;KC9mi|33I+`ddQ2 z&+133HD(Yz2A@p7!-WpkH=ott0smL<$@KmF*2qMk)vukaF=hTgvhvTdOw;YHUIS&& zSnB(%{#y8D@W~o~B>rCbAB9h*@3-%ozR#L|t4@?*6MQoLH7;~8|30fg)nT8r>^<{wPIC6vC;>Nj3w{>eYK@+Z@;4*5Q-zaIVq_~eoLd*LVGlj&E6 z()U@@FPpD1<@a^qlj%bZ1mwzh!yWo@Qj|=%e zt6vHKVff^c`itN{4WB$xzZL#Y_+QA-cobR*x`xaV+^Wc-|`{k|a`>g)h51C&DpG?0@@}PsV`eh0- zD63x!e+hiDhHL)){;m2xtG^xoRq)C5{q|aYpVhzmQjHk|KY>rC@259h`b8f$|F`hT z^e4Ny4=%sYn*KES|A0@X-xKnER(}BgaZg(PA=9tSw;3pF{(V-z_%aQV?G!#)r)v3+ z*FYJR)%RKbY4E4RC)3Y5d(ih;{q^wY!za`C>zk(Uv-*ATo8gm3>TiReg-@oxFqD6v zHT}sA8Z!uPf={OJ=XbdLm%;xMd@}t>q4a&$^jqK`@|3NA@<{zI_;L7T`V&Iw`>g4& zhkq4(GJU_iboqT&zpznb%6UKdWcvM~^nF%;3;b8%lj+xne4o{y5Yd=YKet->UUr#{2usZ`WMPPbWqmxeOA90{v7yZ`Yp~L z^nF%;VoYPo&lbZc)0f?v8<|nrP$n^c^J=FJE{f-v%&w@{;zux6;u>5>he{$UX3*nRL_lA6*)!zxf20od7 zWytqg{gTTyrkuBcPo_UPHDmH;Zltm z1fPOWreEzs2g~1Q^=sk3_otRVnSNQw_gVce_@9SQre7cOeO7-5{Ny%EpG?0$=m{pvI3lj-~E)yPDj)en}L|7G}O`i(ks8I;v;RFFYg{YLn&z$a_CwqL8|ql2>g zKC8b6e#_4+|77}I1y0ZTKC8d-3XLhhj|iVkztM#brth=*JK%rt=O}+L{hpBTvr9j1 z=^sB}{z@=?zr1T?qR;9NApYOrlj&~^rB6QjSv!6!`-;Yt`~AVS;2GdX@B(lbxCOik z{88{0@PC50gKt+pOxl}1OYb|v#V%zVJ*44BN;r-WpCeDS4&+PV;O)kL1CIymTn~0U zdH64e9#5VuJly%b&Wz=+Q^NIllB`p;K9*Q^bM?t*T_3&hAB9h*KPlwKA1-rrcltoaLWPe~|^}^6#^z-_m9gqVUP|cZKrrv-g&R_&38R z(=W8y=ko8f`g^am2Gy@w_gVc-_yMQU&s+JC=}!pxKC8bCeldJ9{c$1RXZ3f& ze-C`}Nd0~A>*15>Yn|3X|J2CHXHCEODvJ<>Pu8hg|5wRJ2W9nrR(~D*74XUQi<~{^ z`>g&(_-o;l=@;u48T5~)@3Z>bK57xZ1D~u@HUE9`(Lq`LJ_Q++)n9$Jev|WA@X0z= zeSdwa@3Z>r;QxZl52im&zsR6})c0Ba?bld@xBb%A4OypZ`epLbL0SDW1sRmpFaDT* zlYSL^vQAaMRs&^FR^Mm!Tj3YHVCj?TuXgsJ@3Z=aAJ>>ckcLmDUm5a!R=*m4H+(Yv z$sylo_1ocp8$OwSf5`V){jv^?DZfYmD_edt{rZsav-+#yKM9{qe^to$S^WvuYE0>u zZMXEv^vhl7VEOy3ek1(d@X7T3{MN`spVi+8|B+u?`egc@q4deWk@$K(csKU6cVSnIui68aSzfX9$`=86M zv-}tT7WDzFQzy!&%Yp;_qvh$dmgm+_ScK2OC+k%8qxmwDL0NsD)t`F3hRE;#?y&U9 zI#vBKA>U{9FI;8*U*VJK`{@mre$P$j|LJ#@KAFDXeyQ)Xray4A`Q^VipG?0}7fuFc z^?g>qxKl%d;Bxq6ovO?4Z~y9(KPmCGK2Gj2{}ymL_?zHGV2u^EsPawTCm^3Ag?Yd8 zv0y&0c_x_84{E+OKA%U6fP4Goiws%$X!x2>ICRg&Df9iEYY^U8ZQ=KU`F_pKU_S3B zhZ}Bwe17j0FrUX9E%Vm-^LYh*Y*U%%$Ib@xdV$_HqTxLM{}C|HXX#;ku z^@`PCo0sV} zxB$%Obz@-mkC%h_`|_*6{Jr)yV7@PQJ(%x%dmPO3zt4l&fBQ3-{lT$vT&l~%>z(fe z^Znr$f_eYoMPNR!+XQC+JPYRU!`}er{pPoU`F^PTzv7!6Tb$YEY~S@ zI7YTD&HqBI-?PBHKm9^5@4vek%=_V5z?Bc%{My0n@7)NVitsOji^1Ok^L;h_U_Ouf zJecp3{3Dp}rx`WM^3V70jsx@h$7C>{51#?%`RO`v$sEgn6wK%2J`U#dZeIlR`L%C? z`M#%zz=JS(xffu1ZJp$(QRnLO?yw)Btf4}pPF_vFmFB%W#@!}M4 zH_E#bybBx!m+i6gxB|@Q6IX)yyyh)nKEJa8%-EHIDXF9!2?d?~mH_4gVuk5{|E6Mt;^ z?E&-t>U+VwKld>(-v|F2Fz-M96PWh{k1Dd|;r+$OgIkfGv%q}6_%txz_dOTP_rFKL ze4l?ixCr_GPcYxNe>a%V<2?%I^K~zPdH(4&a3|K^VTW7(+Y?qklfk_HR0-Z&XW>oY zMBMmlFz>fp1Lp5TZvZ!@EPg+j_tXCl%;&NG2Ili^M;u}Kjm?9x2M64D39&n4QT)W2wq!b^Vy)YJ;twr`96*@ zV=cdY-t-jkx~nYyx!}&LjcdT!j~OokkH6OV8t@jhSDy!uL3{OWaPSF>-w*DB|2uFC z;{OG_>SBvO<|xZAf6wD&Fz;tN2h97E%E5*0=6@K>^JUAx*`$U4Cz#hq*Ms*hKz_k3 zOO1Dcc|YgqqfwvrKu3lN;Ib=>&jYtM8qWsv{r=71&JGK21J`4J&sJ_YhA zl#lk&M$6|A`HYdzq4If~e2V0AxO|R~&yn&OE1#p}bF_Spk1d$miYiDUna9e5T0f9Qm9p zpY!B%zI?QAc!7N0BcJ!m=R*0sPd@LL&j;jFCZFl@nIWH<@+p^3g?whoXSRGQLix#SX=p1QI=H7lJ;W-aQ>$g)^EQkhCEB_}UQ$Fs5WNH#J*wipvzV$Dl6YhFA~ z8qDoXe^OmGl8wPm#3JeGi3FDo3p`UN&zf6Tk<6x7Af_$djM$QRa_E${Y&MmwO~*2n z5z|edACp;Sn3{!Du#iwInzy=m548C$yTRQtw_{Otx9IH zk-@yVX>%j3)sYo3taG!qjD4>*ooeC&ImxPkAH}9rv}0OZI+IEdmR5PJscp&ZSaxPx zIvwLO)JUbV=q^~wQ7RWFESVcwl8j~J&Go7B*pm8mTP~^tH5Q3-Xzkd-G~pN=FmiMD20+2xV+(itgKjEbZd)-0*D z(yG|}Z4x(Yf0|!-70EVjVzP9RcExf@VXy!y+Oz3Mb9Po-R!A~h8_BlV{ANj$#S$2- z+&Xp0wxbh`_)<;0AW{Fel;!BcV ziRi2?Na|EoZFnx3p-WJ=Vp&rP>uPo^=?V$Wwyic4m27_6d`bnB7Jh~_F44^FM5-y0 zQ}+v=S7%9wH{7b^;?!WsisnSjuOAW{WvGQUn7B@C%4tg2sX)M90u&z-bNSG~S>oRn!zNP`&NZ*~=lNNXk*t&g+WlGuzi zq)5CPlUs^el7(_HlNrhBU`A%w)@hr9CCJ4dI(e|tNs6{d7?NIfB)Oz5vIG@V;;>=7 zIFgRLqRGv8ZmKO4t4=i^WNN5V%w17cp3|*b4@ta6dI)}Pm*i`*ExC;?6=geO0hay2 z8D?Ajtz6@{rpEd-^{GnfrX&Uz%;L_BBoa-L=B2VGq~#neObZ>7J835uX9hPqnSWh# zIu=U~TmLPnE`HTuf^{o0(vKQ418iHlMUbX$@#1(h+TCIDaB(a>bfsS$PiNaA3E8pB zx^GU$TebG)=4U&X*|F5JSguPW`5rpi+cbv;Ts%KCqpHls@l0GA-OzODmPwXvVr3*V zq)8T*%r&JV>FBIfa~n#yN?MM1Bq7CP3%TE9Y|q@)*2S{5sf;*GrYd9opcye)Z78oq zj8+D%#_UuoHwn42T|{oGB_En-#ZaaDGxkbl8C+*?aQ{%9ins<|cM!JdI>q*8VV<5@ zk!9hvU> zUzfxai5anS>4aukBoZWj58cyRHiYXWBeA&>1^qRdv>@3!B$9MuW#8)Wkad4CSO!Yk z-5yeYu3ea!h&L}Cj93$kMKk+%S=?mZ=MU+%xT#zgFBFwTw&&*9f=nzuUAw-mQVO<6 z-t?iZlIwKU$I|IYJh|{gms;%kQgBv;+;D84}xe!@c&XO6i1P42t!-xB=9p@&svMw24yqK$y)1~lS{gKUOa2?E-O(mYy zg3Gujk;%J56>B7OlcXjO*)ZjRMkdusA1ua0qxrFAspV3C{KLb#$Z~g_Hn>gHNvAT} zCf&5qL4>rAsYK!u=`1D&b6Dq&H!~U8|J0`}ean$-{?nVY@#Qh@3)}(CU>J^o<__*5 z#PB)^AZ$$_^aDWX27uT}AbO#LyIAh9bNP_|d+RX!dznc^I-N=nU9U2gGZ@^>coVB5 za?FKBRVU{Pkh7_hj!1er`&<%bb~@79B8LRtk*-X&dLy;9X-LmNLb&b*51wSAs~;@p z+>#C5F&tnrcO){Gq4BvR84O5AmdCR=#?DO*?Ot-zxq(U}p=&sly1(2^;^dJ$Wo0G z-qS5e>Xzg078WGa2Wn$%)`Jm-YhwmO_itsqu>IPZ!La?SQaD||tr_&ft<8dDW@zy( zXpKraxu!(x)R4m_>{ByUN!A8VsZGg=rs%vjG~;g1SfA1+Tn;B1E}e2-gF8cYv2+)7 z_Vq1t+8|mNSscr*sGZYXSJEIG=ge8TQ!X=S*;=t3s5?c))x;p#dCpjo)#C|oN_8x` zM33=i&RQ_PdSvU;icxhW=>u9oQ8(d(kV@m zOuV@vRHuXQ6bYVkgllqrsX(ICRCi?oLZ*Gsg4Gl|l%{Q%(BGcjDF18C=+cGUuSDKera5caAa+_INF@H|oxefnz zt|E2&&8Rgo((Ot&wa^w>-%wxDP+!_mA#0)TyavhS1um0y*$ZSBD+h+s?6?i6zA9YJ zby?~!t|^tRuDQKE(iC4_T6(^GPed}AhOC^lXo$-hj*4NT>4ut#A0Xy%$wU*iE)&Ts zb-gx70;rF}JO(zDqO($X|bb7zyJtxYtv zC1dTa(yZt)gH2v6$G7{>tyPW*8kXCECu6!MN5QoV`ejLbdqb=AHB(7xxU(x7mY3*M zIceOyw4u3WX~W`3T-$eVikx^zyQH(JHrZOGPaSD;y?d>HdNNL0)uyXrX*prkoJh&( zlek2QCL+MP)RhC zO0;ET4Ow?~#!b_&uBp|vsqs{mzp-V_%jC4U{%w`+jQrJ3anPV?xa_sciRi5KG+U*B zWVh9@B$mxc8OP-)e{kZ`*op=@l_0fja9Spo@U)Dt>5SaW<%{Jb!(^m*Wiez&bNvf7ID8$ipcx-QcA+zl%Yi=nRKa22g9YB zl>T~E-At(?6%`3B8(pQy?|IgRsj8jg%Gh~{>e@?yiy>MJ&1?SeCe>5=S zj#Nc+Li=IT@L6{W+jaE;4nYodq#)hG!65Bj{-3W^Q>5f$%j8r~b4)r-@hhYq)m?Zb zy+rm6=Qn(C{v55A*e^&my+Es?uCpq)$JoD3euEX)Wb3ZHb)NK7{TB59dWF?SLF;To z>|Jv@Tw5izYKoL-ZqM4_S~r=!oHDRR?;@*d6y66X+$r~^J!R!$h!NF!RqGE7|Z*u1N&6dCc{5M|s z1BfGB?gQ8(T4c9@+1c&TQV+?s9oh0M`0Td$3^~mai`Lo(I-IZdyt>pKNK@l6;K8Mu z;Wmx~XY=1&%F@!gauNhLbsl^pIdC3E+&Ua&7W-}GR^+%$XBVvpPZ<1bWmI~BYrW>j zmdiP=*pRm59Cu)aRB+BhZXU3UO5t-D)l;U*IiZGSdNWN!Ybw*QIF)X=Qu<7(D-Ti= zYU6dKdfh|LkGS(ENNnh(cR9|)LGd~6NHdh9R0cPIhO;!q)iA^kU!upsRMAPIj4fD~tK??^k3_t8v^ZS5o!-q&FWNHCsi;EZp)+9Cyp3 z9g$D*3xB`c4(z~t%6W46F?aW5IQLUZc7#*pm$WnG@~qhZFm<Rd+8$f2Kfn-(4CNkCIo&v1!+x-S%}9#mVE!8v%fVDTulcVP%|Ykq0{`{m zIY9SkBqehI^$iN;0M?r+j|0u>O%{c#ingJ0YePe}Uuo=DYY*&No&48V%z@|l1_gXz zaRg=TijEtY9n}rr?7eZ34DY?!;uwBzZ%`D&OK(^VrKNH%N3NR537uqfZL^-_JHYK7 zBfN5AU4nD!>Z_&mgu7M_GS}fQ$N0zVdecb7<=Wzvp2OMIr)2K6bM*2wC&^L%0kS=1 zxD=)wAPLu_lq(YD)z$K3fo>VGwC%K9P0NMo9lUx5O!`~a-6(b2r@MQ$TC(QO83@jdYho7yadW zgiPE23RmfV3tS_oxT|n+&+Slf1`^k=+)1Q2bpqX8LUb1sE4&*m+$nXp8r|-Hx?bX~ zudZ`_HM<-sg)0->-5oYTF5Tz^^yggtmNK5va=q#rFi)Ofz z*{@(OPh9S9(X!PyFChm33+iW0`#0xmHCRs?>CEa=GT*mgj;Qsl5G_N`b+zD3*D$Mh zn3#GYNiIgYyS3!*q+z7Dq)zCaZ<#CQ!dI#-+t4icxXNvaX`IHZkRoZ&E51X{?MYpl z?=BB{S=ukso6no1Dc8KM!rFPkX+zGnhO_h5q?GH{4&ChHGI#H6Wn9)^=rk(Vb?8!Z z)Q`DeC%San5;+`ibx%g>9UyWOX{Mrf)^fSmP>;E5=S1}y_Rv$I3+k&8^*@?h<#v$$ zFL9Ti+uoX3re|>7LzC`a0x$DJuWs8JQ$G3-I!$2*bPSZkGJOaxcM@Z0Xy}k(Xr^@o z<818gtzCzg2R5d=TZ`;@nY1+=?v%hRxn;+~v^D3wm-{Vk=@dJVv2N1P)g(pe6~CRl z&?a8)71dqB^ybCpYCEn4SzUULPM;OQxr%>x|0r9B?LyrC%S##ewhv9+)`S;pXmF@a zdE@0C+RB%@jR#9OFNqUG|Lzjn2^u>~XnRy-+O5dy(sOY~GSjnOh${{Y$*lt?SdEe$ zjGh6|vl?=S(rp}`C!zAZhwOd55c9Mf5b~@(vHReAUQM$Z>GPzy?!c5O?$O@;9{Y7x zP3g3{TuSVwOB3ZXIecL0K>~A4&TzA3D^u!r&$78x=pD9}dDoB8#~9o+)ZtQh+9)?w z9&KPh#_g%AQ%h`dFNvg+(%itZtu4lj7uhW8q+;3913&ugf?^5fwiGwmdC10 zZsmKcSI?qpZvlM=%Ys`bdn^QL@U|@rXW`(nD+cLzSKj;zJ}Ab{@d?A8*l}qV6Wqx*0?Ee{%DJcUyMV8@C6!dWJ6f zdFWKgDPY_hKD6~5I!9?pd4Efl>_Oy$Q3 zbGyz^eaaqnuMN+|_IKfqqDxAy87|YyBKsxfielKV;$X6t9CvUBNY;+a^;v6OEc6|) zW7cQk`2b+8Jge*W_tt5%jz0t4OLP+PT8rRvJ~V>$HSBI}yX95Y(6PsXS7)d!-l$&e zzf#?@4ZBXIirHOwda9>N4&vmd9CxTC2aBQVr+0K8==f2hzR43L{w@>GL!IN5|M1Vt z#cP{w!#&6KCatigBR$;P46J%tSJ6Fpx8DJw>kj_E_PztGsibR|-kXYILn2sEDG41F zkSdX?6a`BN5HPf05)doJirB@qBZ@9IY=8xIZHRrX*gIHIQ2`s)f996tCN}{@*M0Z< z>2qf0%$ZY>Eb$ew!f9}cUI#o7G7jezN_g2zg{=4rBA`Xt1tNN)I70f-RYFnQ zFKLR*$RTep1a`b8^qUZ7B(S(fOz-ixha_32bU~Dq+AR`aHr2f-BU}O(zp2VCmVh?d z2uThq5empw1W>@O)|&z&rdN-{Okf8A?;dndgDgbykE{qmg@E{a0%g#Xg?EWPyIM26 z7DK9;X_9r5tPy587^?>dnT&{M2gvooSiZ<>OjwLCXUH{=0Zv6Ql!BlGVL_k{AmaN8 zDUB9Ii6>BUJ<^sUZ3)Tseo7!Kgb225&Fo4k zLul@ZVQesx1qP-+*HET9zoG%IKjD!ST4`!vK@6zAVbvQKkh zAa51IzJ+3ZxM3OW#N=i-E%J(#%tVu7vnO$r!o4rHNzvob#MIfq;t4q)U=QO{h9Y#t z4yvgsJ3rF>KJHL4bEK;*x}cT5Hh}=p;%pO>0Sun1>SpRx8}%3o#lK+G{rlT*Asj zUO!?t#6^5_{h+1LzkVRZfeWyQG|>KAhqeXFc1oGBJob{0?FcIs2?BF8w6vWjiRYv0Jfdp}mo`6!q zc~1zSB@tl6MgcJfdqM4a*}%LGQiFn~QThl|A0ScqD3keD_KQ$F821b98+9%Q2p%YB zfRYEkJ>qcE-OUr2`(x&D(uy`MEXB8IGhlAw<^@IuE!_0552@?Y0-D2KNNf@44ydpM z4dw-+Qc0v1u+f%6cQiBc=J5fWd@~{-k&FtO>8`2knhh>%xa9>~75qWIs+$;2bGLLe zWBXYY0{00dXI!CM2O^df2xywa5AIfUIA?H=jt8C)ksFjAh^kh32E)za$UV*R?**|!ses;+P zB&;_h$Q!OX`PRVjDt>3s9Dp`4;IA-J_%RFz2A>1GMf|M76p&X?8Fb*?2grzkn;qow z4c+Y!mq|?i16=`$stzL+iBA&Pf*nfV(*v5H&u;S&qnZ=Qf0L}hdI7&^Ec$cF>tC-?&gJ@h~yFi7x11OLIp zCjw}&&H&O5(g58;Xh4-!0BA(-8g+RHE>=Woop9QJ63}oGU~L?K1Ehu6!LxZt!yN!e z=7A}aldxRt=1q3^H`v`BbJ)fJF7gvtHge)A_M{XVDaC=5;z&xNQOQZsI7hlUtGiEb^diB$OhLz?NLf zmb{bf$xyZ@57deb1}pLmt;svdn%tu`M2^8hC_kR4<%p#t>I8T?nkJ3Zhq*x8I382U zgf4o43tZ^GQcCMUgAwuFfvIRBW$9ANhLX#|zJSRw>?auFBDAljMi-2E3n9N~KwZQm zA>ikyB7PEMF-2gYlnP_iplUd<2VZO3SZETCn(P4q1PkbwMtcCS&WKNXs8j3)eP+f2 z(;-604g@r@M0I3PBw#%7cMg6dIsk|-Y4G94Oha`7z~3MY0op$jdjJna;E@76nt+EG zC?GmYFJL(a69GiHOspnwuLhEYuI#`E6yM?!aIiwL1os*66SpfT7C~nVb5WCNWMTa! zSU2zpwhb&EgB{I7=^Ro~E2>ygNV-ZbY%f+gkqsQY^MIol5E=$_fEeh*(FGxHEir{> z)G`UCVqW4=ePWP+s0M@I!+_%`;K2>*oTGus0K{PvP>~CeL7)T>P$QCY*fCk=J^w%tn90DJ=v8G-txl9$`#k50Dmm>y+lD7Cm?p0yok{L-Rl!`k(e@ z3nvPVoX~3|7+#U+ImZ%#9tbP~?WaHy>ckhBoiKa^+z5!ihma5gBgQ<` zkg~w=K^CH8L&^iyWIlaC+z8~113(FU`a+0{gzNz7lBmiAMgvI^UPxyz{vs5Huxz9# zQOKP9Vj^9f%M2YGlSK+J5%AAtPJZDgho}lVOo!XE^{%6vlC=QFsdQhiGAF-4jMIdZ zQkj!q5Dh}+jWN98mBitIp?-6-I5 zwT=&l+_-=nmB5_vyO=DH`31YfxGaL_3xRElylhbp32v-_nqZ(DZ9>T(wJeahH+q#n8+}`DR|aNf*E3-AztA};nq|m&BLy#+D*ex zeB20!@rS1=9gu)IFNnb^1%8O)3W16Lqo9*gzj>%hsn|5YT0bE&kicUcxQqosvPC0d zBS{kDW&^%>E5phozJPsO9F80j6tIMhdx<*&F_uBg-~t6~?L=UYT0x-Y=)9JB@`h)T zI0ihtFbv_&DX*Mm!U6O$ziN*rh-k(1fhXx!UND+1{!2W0w5ReN) zwll(iqyKo+XyGT~xJi0MNPGQ|ER-dzkhHqZ*cD5w)*3T+scj*{ZN{~Lgef6O;%^g- zxNHeXnyTLnSemNZ8qhS^9+LUv;F0ojX$fScRBZ+*QfjpZ9@3g>B`BoRMkHt;MR9%y zbj~2XE_y_Nd|{-w*bIQBS8M@{5zyfiLm4@e(Qfk~kzB8};E>!}GoX-MscA5XGhVI9 znyCN7`o2(^uElzp1m+xI*0fstv3c!0cmo6fvd}V-X941T|2F<5u}?%XNETZFwFE)K z7a%TW0BIzPEzo)m3xex8QCEU?MB}<&tMvtR5)m>9F!5v|3ot9?)n#iBQ93%rxfigAV^)iWZ^uq7mg1BtdlsJB%28W^8!TCoM?vwN9zr2 zQhwJ$BYk0b4|-%~GZWYov5+4a3JDsU!UthrlTh0SED>>J3h@;X^guBOwyMO~sb~^X z5N9Y6OOn%&qPXD{p>3>74~~R9v=iLI3K}Xw2;v1r{F35B#52X6jAB(`#9PE9PdHd0 zdKLsIMN0vz5G)=k`YjfK6ixI@1xQ@j3Ti4N{DyW+!Y{<1wP+Ijg5J2%qkv6KvU6s% zL&(TYNdzI&0};EUU=Hd^78^3^M^M-!D2*;DE<+AR!wSJ&+3J`(kWhjvfQRoyZRvuT zF)Tg^RRm+8u}LQb*i?&~JvM2W2iq68O#jF4FhXyVkfEsic+m?Dal<9>$b(Vd_?6bg z<=1@tp`W7SrCG;7Wc2TaHG*(PcRFrlgKu3t7j+kjBA{9g(+kl3MN<4$V&os z1|*o1Xr82~Ot5{hY5XS8J@ES`1&_RiUEuI~!lOx}WrVxJZ2}DCgzPYc%?4=!(cn(7 z17i6gc5D(8zQzPQ2A!916N!X@LZ*v2J{C#F13&@Su;^MOMf(9SxXf4<9>fBvh>)g0 z*F{3uC|FIHgEm9Q3kr51EQNkxO`rumlTx6~J)ec80!ZO!?EhLAs#a6kxIZcJkWnqT zdGW~OC`X7Ui(@4WlquN-uPlxg;-?9C6o49=;HE+xK_L#Q(2!iRI99SaRvd0L8tjEA zvcSpu=CM*Mc**~@I9B4k4>F6G>}-MT=!ooysI^8sNsEAPEGsHrw48t)2TKy9 zKqw6_EDNZ0jQ1>zW+yr{5ocZ~j~ivn;f?&pFn2#sgNsL86JKocC~Js&dngZ11f(a} zgk+XE1Oq(6;&%p(jQ%BgN3=n9_CMib3NE8RGnE~Sc<%aL40%G2LSBd$o6F;a99K5B zwc%45$RdeJ5UCK#1;jwFFX*O+SYm z!>k=y(OBLDVGfY(u)*6LNFhb@0H;GrEtn&%7U&CaMmQ=^p~*yFCf^q~TtSc)URp59 z!GS@9E``7X-HB!)GHH~f{<}5-)|;fO2HY%CLmZ0TI=?A+Bs?czIS~J6__aj1(psl! zB8^84I|I;(V!`fQ`JlgK5U?0sR6;tGt)s3EVFhFh3x@`i;6~?<#nYfQ6eg8-jT)E2 z<^l;A>e!ETGXog6Zbsl?37x(pi$Yd?f@8uQy5U{JBmh^}C_eBMiH{U>@`vZKxlvqZ z44*K5Of>3B_u`;pAQU!GoQAi7rVL}TfxHh{HKa$lWdF@5puZ{1_piS^n>x$l7wP|% zaHZncJo#zX+D9JQ=L3!WqLbuvnfw+7TFfo*vf5H_pzyE)q4V#$JYZKC>43cnFkhqy zQkG-`gQ&6NVsTsyA<3dxq8(#XwM9*Jp%_Mj%6wA|2vyc06!G`S&rGPr22@QAOOhEC z?!o{75`jA)e^6n&lxa5;p;F9j4YcZ+2E3$V1Q^8UAc+n<*+MZ~&{!4=+=B3>jW>(9 zpCv@0Mc{|l@?}Qi*BxjBxHFAoMPYX+_zp=*7E1{NI%^;*H;Ai+ULBwiyg$LkJJuWc z07X3B0%0xQGor_VbWc>`K!Wd~QYBDd7UY&Iu74s6a?9dzQn*npS&&-{5Io?p3~0=N zcqAz5CfQNpCl1FqVz|3G>ml*Gn0ygRx-Q8#wxkdR;9cIl6Ksf+0Q$kA)BdgtlF*~@ ziR}rTPxDyOKnF@FPBzXM{-FLD(X=mH(|6#RM8cI6&lV zp%UVsAn_#;Hj*LMLR&!L0P!_O2$CN+jg&kJAz=kK8VR#VuJmKJfRfy)*#Wd5oEgGC z_9gpqhwCI7nD4i!`3bv}#Cegbum?vQ#7;~}0D2s_swj5yK?LY{qSijfpN77SfIFRd z4Ao$%Xb1pA(-cD|C^s8T$G8K?@j*;^JtRb!hC@O1Td)XKXhVQn3uSZpDa-`WGa#a) zxa?#hdj#YLO#smh5^)ure?+?w4h{4KrWeCQJHk>xzzaZra<~%+oN}1una1ZbqxfFz z1ePmM9z)cF#H&D;^+3rMBZ`Fz%tAJ4D2q!lhX4ccWhTX@0R0{mGKjJpzCyU6m}q=% z*eB$m22Dte%3LfV7oNs3nux8Sdi*Nsn4M0A4hNLDNxc>e(y0>zJlfRVp$ z5Q0eAa2!~-o=}2=Yky*CqDuWB6FCD|rbviyLPG%{(j9h`U;qvlRvb;jFLNvreUX3{ zj_7QEAm%9=3=%SR5|BXZQ1&4`9=piIg`@y^G?+JRO#Ktj2Riq_)i@jIdcyfab!g~c z7#zPQQqE%05iT%;fka_s@PVL(F7ar>9RZ3GY@D#zf=zgV zmPIK~Oa^}9=}p4nmxXwgMJb2Aeu1I@675}DXl~SyK~fY{3>&m0rZ`PJkT%k)v{2eD zX|ee*x1b9NUg?D);0f4X7NwlUrxT(6%aK6+#N~XE2M)WwMh-goO(!aSS5jl(_iY0M~>?a0!w0K>!2k zA(TD_=H5t9W0)Wo#9k0g9u672+5DKXNg%dPR49|nCdl5&UTS}aKM`1NpfP{e`9fI~>}kfa1ajEi=`iBCxu6at$!7JnE^H9U1(p#U4)6!fRy^nqn@rq*08~i8ok$Sv z#3z{HksJ_A712}2D7I$C_Ok>w90eEwDWJ3fIW&tw-K~&U7L5U-Lo$<*SmN|R5ZoTN z8w^9-JF=3XZ5o3e(~`L5U?g}5avqmv$L2AB=#JS!HL1(*q-Z!C;COt*nAKTiS;+49**cYGr~t`%G|K@X`A0zx~Lmb@$N z;S2@)(KnI?W`imv*+Z!Q?2=@9L)QP75S$o-*Dd+$NPk?O;VEBFwUn1oX$T^lMp*ZXcFL#1n~#MNa4pY92k5KgJw6( z=cjnLosT290q=*qpEhJ9ZM#*aI&N zESCZF37Bq79;+pXH<)mCtsNMQ1a>5VIRl%2EQ`+r&sSDj6br;J!4EJ!$Wc%WY;N$H zLC^&~hMt(5Kt?TyjTfA;JA)qR0|p7Iga6>XMF0&>34pYNG(fiy8W^BKI70kk0f^oEG>S|Hs1rApMpTH$9g>6{r3I6(1pBq^L9TA3$anH(453L zGk#s^l;Xd(e?Hnlh*G)boNg1A0k{OU;J% zA-QSO?pS($n(}PE{*$2}lH5F|tW;Zju-N06|_~>vUgVKIww}!i=#X~HEK51yYKU~NQT=~bh z`YXPlCUfR2DmK-+b#R8x-QFIVkLur#m^nOU|Gvq+8gGZGeR)GEO&s=g!0pm}zd^=h zzYQOs<#z0r!oCZ&m3?2n{nY-$v747wLl@6t?22Axms^(nKBwsTm#zC5x~Df!x1N%$ zy}9q}DE<_KM|wuS4{u(4?q)5OyFPmB3Et*lxyDaPXTIe1ZU5*}W!7bbvnx6e{HVLo zVDV=DSK~AN1`ip2)??A*%5m|plRKp;#u;}E(9+pZ_qC;aLsB_6>;7| zs9SAacHqHZlFGF-t>XeauX#H4jm*?MYMahQx3=X)eU&@1k5 zD!BaD;XyHvIxe^{IjlzQ!)4cZwuescD1P@eeqtk@C zpyL+?ZTmE_mcR9?bI_{t^!omp&r)qC#aq{y?YEl!cE65I&msf4c*@@AYf1}?hJRkb z@wujw*Sr1DP=AfEr*E$wj#_n~CVZKb7W?L!#2tP5AMmYyWtp#?UiEnaJ^qB!%geWd zH>jyLcxY-r)v&x0vHpF<#7Ae-BmDZjtv6(}RnggOQJ;Ly?&`py2cC@_{f@o+K*fR5 zDwggckG>4McQ3P1ptGnOUdArep>s>A8rBuD&kUNC2yWn{C(WQA_yI#+$JUt+_r{U&?Az@|JZ{C?I zGdpFoVt2{Ux#rNRcZK_EYDP)!>x26kch%cpJRH}^rYck29^VpA0HdZ~Iuhm@H)(FYDU&igXOQLXA^x3xv?=`~-! zElsEcxEdnWa_|FxD}o<=kOqFq?F2tCO$GbW1-~KwR)XvT@LLu9=zt&iPowWl@0lN> zqE+P8(FE{+ydEqA+YyvefH~+ta(!()OHLE}OM{mZ2^Bjn0z!}!q%8vamqYIxwTp!N z297-f{0QzFio&nEZ(h`;4l7N6v(ba)7@s_0*j&+`9JLu7d zH4huKPBa$xbieOVYn#`lBJofC&su|$R8$v?ub5X8{yyipN!mDf&%mOi1>2NeY?cqd zbttx%U5lY>hq*U)>9Ef9 z8TY7qt=3Yj)VU89TBa4$4R{k)JvqMLhodk5^7|U(qhww*>cDCPH^Z@ur%K0bA+O#T zT`HOE=lOEkgXAwu)G2wD@77V*d{ut$a?)kq<1Ft(3!bDY?Wq5D+%`V$6Gd%Oz{>-* zkBUELoOGHQ+^~PW^|7um7DavbswtxzRrP$n@yw9N4tCv3m9D>U@4Rb{OK#~D<2%)} z)_zl@ZD%EK_o_1)N;_2hwRFJuw&x5xPI)qL-s?Zy=109KX?xUVMWNDhP4*O*%WV&T zRr>PqsY{>D_0MNIM2yM426U;pEs#eUwKzZD}+x;xouSLyxnfl8rOH<(%< zpW1Hz&N#JsWramCduz%bmbhPOH!$#9)|HvwYV|4_T8dBge6^-o@~Z|K>hw7u`MELF zC%n(C+O7B8Oy~F9r+A1G9>RFwTIizNF?Un--k!CTq`l^cV(eHG%DQp(&g(7bkhA4r z(6;1?{(t1ri(b@CHqSj+RdAf8r3ywBe&#l( zD3jb{r^DBj-)`LTdF_?O42@Ouz0T!6kL}v7r-%O0H;ebLD#=|L)@YERSMENWbJnJT zsn=n2-TXj#@w!2ea1@tTa-rav+XxmAXc|Uu;nydd}wN|m>=a+}qa&tEX zhFImY&KZyDb|qqYc2antR_C3oo2&n``36VpCT4$`5;iJhW{rAuz{Fz_-IG(bRXg_Z zGtjMw-~_%%PFff-;`ImHqA?ns`|pTysFC~9r+h+j$f+@RXNIp`X0#-v*JJ+|^U{^m zcYdnu^(An3@=JQ?!SwazHP=7H@b29FtKG6Wi@aV8kBqG7>(Jl0sBn4lle(TOqEv&| zn3v5n^Y?jFHhk2ZCf#`5ld&si_h{Yy8LTTGjD-lMdt z=eHMIM@&pI^wde{f7Q%E_vzOzxiik%^ecY+GIM|4XMEyS;xI6Xc`NwF?4s#Qu4}Jbeq`9={VMX^ z`vmxWOOG0Iy8Hg*9F4iU8j9~~w~gET?JuppCjHi%RmS9hw6B7m$JCyoem!Ddr&s# z*E=xs9~hq;ZSmK}Ma#F^J`3~Q)??5~XSda}QXW}9o^oqzN*jw8FQdKZ*&gzdAH-Hq zx&|IR#m2*@taw6osM<7MNBexl;5Xdq)IK`zT0mt4Lwt#?&kV5Gf?;WxuS>pvadw>(KFzAR(A*ORkDl%BSu zKULZheR$Hq6w}%>Hb!#YzQ`@g8M;Ab#b>1*%wtPF-+iWGG&J+9uK&7+pH6;}n;NvH zwBMTx4be)y6YJylYzYf8Ur~E~)*HPUg_I1Vp|zd!eC_U5y$rm0>`}r4?V(HJ_7B#K zeX#YC1N-XvC;jh^kjr$_-rDtAhdaI7ym6cQxbBKV>bBDhBMMGVIsf@mU9tOz19SB1 z2b{ehUAul;&i#|zO(%kb659OnI{bsjLW4A?wkkzo^D7ow)=w>Z^=ZX1E#9ZToYyJ$ z>ZT+l)|{HQZm5^3X;t27RtMu%pYCY_8pmWHHA6)mp{umzRTc6xs2K|K@-$tlwu*Yh zOmBIXqLPBVvK+AxsFk0k<4Mg@Qle%lyv$crkXKMp>o{@qrel9}*Mb$X=HxX&#Ymba zRb53fL`kKcLP!v;9kmVo&}gRtJT4@#DD2dpo43>!5{rMRZ> z$8xxA{sdYFsy-~I*iIWQH;lvKQ`}vt-3+v8R#Yo0&B}^qMY9bz(6+KCd{QUS%&Gm5 znp!CUSkXPhyL^XQu3 zT)wlHk>SfpJI3V4ISt-CqAksZl4_c0*mdVI|2FJiIcKk3Y?F1`U$-ulfAOZ8PfXhS zt=kG8UG|+7c3MGEUQWIs^G|AK0o4#Jk)e)K2POUC2DR%i+?l+5o!)~lf6X#CtFJN$ zrs~4%cJlJym6WN9;1|^hCYUI7q;|;A?{|?sI5$=O+uQhg7K8r$FxW3$Z4A`{7BEuk zP3=iF$?u+TG}CY_pP$^{(lUyhV8Mj@&mxMGXvqcJ$O0r$bzpg2*n<+-)HA7iDumaB z65ultmlAAlu$1z0ZjSu;b$2Q@EU@o8x7bj_ zJoxKhjxLRXV<=8Q`xmi+Z<)tqEj)|w7go%IZ|%{QI@s+Bf^u4S5T{Yq|P zmy*SyS{`%WQ(Qi+|C{lN{BjGEp|4hMROCdw-RNDYa_m6( zBO@a(&#BeR-u2eoOEKnhxVI_-Q%*SbTrj#ou4b*>TyMt(#RHx%%&=IxGU9F8-*0s^ zf}GcX3b@g2`}C#rtPY0yW!I#2e6Ve$TiHafF4Na%|E>RQ_N5Uy@3)7Rn<@A8+@X2X zXS0H?&9>PmnIYL8r+f2MUu8Y^f0qpKzyWHOVgZT=#c^}~HbUgmVlzSroJ@J@BB zF;(GNN9T`$>Q~ZTH!W|xbS7qXkN7qh3l3Cw>3iI0Y2HMw4TEz=UhQCSeYRZJ?{9tf zrPH0b??&rXrZZO6_f#wkS>QKXyDr++q`go3FvH^95ARp!T?i~YIwCN3fm#XW!`W?S z6i)IU7kTR3z3vxu*Eluwqnma<_3iJ{{W>?tbiH=gskDF5TU{Nw#hSaicd+1B4%EIK z*fq%GWm-8bv^`^PbvYwNOBFk6D&)g0LS?&+La3=9X@Od#Z>aFQtev1}eCN^onjD3KE=%%lkvpqj}CfAM(0ZzYey zjDjK;v`!4D!-79a6xav2>ws95!UMU{Ol~v>HO5wy%fVXWk zk&co%pf2nTloa$2N>h@dH2@n753~u46`adN9IbnHLV(SU_0ElH-{ViIzMSGX zEhmU_#i4xH;gtaz@!$J>2`f}qpKLHFv`shumAyG80|pmVa(X;^acOVzeO=Foz0cGo zrqw$mkTeb1H9Df4QixYQHljr8_lC8SF@< zNQ{hW6TSETo(GoiiJ*dH%)dxNKOga(Qf=*Q?ICqzMRl;EVxQE^RkY63jw%}J zi+g1+sW*$3m)Ft|GOlQYsLtRZC@E^$i;zB$g2E`Q{uEzkB5*;&rGVgUz++X^Sc<8z zfj&6RrYX{FC#nH#Rzpiqys`+v2aa9S1kk0mx>4*sx%;AC-b{M7-Y_%UJ!nV4*xC*U zkM7y`gnvJ%tBd*Eq~d~#^PEe$*SF{GtWe#$aL%6-E>A6Uy->IFz0QI~^-~u1FOA(+ zeNH}&*@bV=cW&j4Yj?UCuG=F2r)kcvl=a!}GYsy`&#PPD>l&8B(NgZDHS^oXoDB&_ zx9(bzwr0B)ToD= z@{eEbRJfx*r^I&V9=7joegAEgii=B^Dg}R?-1o#xe(Lk;!ah#7LtRoW7k({wDY?Dn z{Hsf`f7E#|NwPk1pjiH7Z#B2mJ*Lw=SDD(39dqM6Z{mbRcN{G~1dzH5mI^~j^72Y> zg)Q)Js{Bl2jCkQh@sbHB3VxbLvr^g7R2qSVx_hpAU4sgZb!GJMBfW$58G8@uS5UPe zN<>H~1*)6~{Unj%%92MYB8Wqk!SDdm{3e1z-%w5Q@c|Ut6&s&K3@VO5wf>t3RD?oQ z&7gLG0PP7WMlGra4huy^YC9q2D6b8(r4Wy1F`KmJ=ik0?1PGJscmA)X-S^$J(l}?iF=Mj-Prmb6vsN z^v+Mz^fLOSFRNIinNw|75dK+lSJ`dG+lmG8_*ja~nsg?nYo<~K;-Pz;b-d%2AW!s47o5n3YI&7JCqu$uR+s5}>G$i|7r*&K8 zdb{a7ee|c^7XAqH&&ENV9Jy=pUNHUN=;l_PT^SXE_;d}4oc}gs(y%l{IE*DBJ=lO)oEG!Mbs?)%?faH&G;9w ztb!U5^Alda`B@4*0d~dTwCaj9O~Hq%JhiLfLtUAsi=bv}stuq$ZEdLGR7+v563tkN za$)AHv0G|8hpg2*(k--Z%VP6Rbra78wOOvveT3<;XWO%>Be4om(dr5`e{h_Y`{^hu zbXL+ImOp99gX!wi=yxYt&o_6z*5`|_E!CXxMpvS+DKuZU-{$eIN7@zMXqV2~*f%JB z_Yl`7PUm(MQ5}5z!3icbFHg&o_XP*rd!S2NVge-?DU^j}RwV z&Jr&usKE?!O$#2J;6H9ewA*;MfFvt7f6H)Y$hZ(|2ay^BEwSD}8_1XjS|THM))1o@ z0BGfsDdC%Ev9qm?zvFeZDhWKeZo~<9?}}+_^{rhR-c`?A)7^DjBXp7VJ!{r;=>W}4^EUwvS8uG>cc@#9i? z2Ta|MeF=z9H?n=uS9{2kj`vJHrj1P9o62?S;C}1jgV8D_OQv5`e5+yL85F&3@2I-h zH+xXe=B%hG8dqpT@4U;kSN4mbE#3BZ`?NgNN1<}P(aypo?|l26Yi{Ml-8;Nuqv_hZ zJqI7&r&4;~zp`(-oj!eCmfi(wmfl$vO^hR?uBV_w%hD?YiF*V`18|+P^a?>zfr30Z zU4UDJZhAmH<=1*sT0Bu*4--7=%@=gMpjh9VFgcqc?Gq;M`&Yd*W23U zXK7yqw4nlc+CIlSP+cs1X{gH*yvz&@Td@yAzXt1BVHahhQF7 zRyJ1F;L&T1l7}`_d*st9oa#z5q;^3^r!O2Aj0XUCV1BMNoV?R$JrnCxai2hI$9npf z{h`yiuPW4bbZFCV#`=Wg7uMWiYP}ETMLYkQ(XVhs{8QuCJ#(3h8d+`1A5V`+V11f0 z!2WWv$r2;Ic|~C*m5CX3y@#%Cqf&Nwhlfqg8SdbFRkzD`Y4bKb@mun7Oyj|egF3q~ zN;Qt~zl8^$+O?bi*(y~1a|vI&U3dRYuXdLtSb2KuW!Nz5M>)6YnVh)z^D(k!5qfr~mnT_A?yTjp+5U@ll_9^<9^MDl#HV^pz@^s8XX^Lt@KF$&A{U zYMS3GzlVS#7G>x0@xzDk^n`qb8_`SqF*{$#c1cq|;b*3@H9KtSMNvKkAm~K7*T@Sw z+G$_4!_=_U5gltb+nhR;-FeK%4|49hZ38Yi)w-KGe9O7b+@o2mG4O@j@w*OwiIdyf zT#wq^C;0uI9dgddch2P<%Yw>@Ah1|$?kt7 ziCxZGzQM8H0=$k@0i*vlh6Shi4v$*f@Mf0+U$hFK&<2r)bRC*YOK)kmaHB8-XW!pZd1XCOKcb-M~X? z{wtSo9PMxAvEG$LyUo;aFv#qq0p+1vgNe-B|tE3fc+aLcxw)v;Sehk~}u5{q|l zvbE>laeA+EfittGullhrr*zV0&pT?oudI8!RcBt!$-6sgwOKDQou(f9kI*r~IzdRxD(M!I$hw}rbv#RG*o0MM5 z2dzrUJ4LPaIXr#=iYCQ*{SuMlzsu`am-bwf>DZYff%Mmz5P6&R={vCFl6))$h*Ey%QJL|L%+6DYg3X z4cDBPoJyP+%&2#tuXizZ)G9eGL;o`a&wqOI;g~ab@4kD_Y__z|-##jKlh(FX-B`s{ zx>Prtn(bHQuN2;OONy-gx;O)y)Vbdp0@VnoL=57e`UH~nf*BleC|Iur?Y#<@=McXyna;R*xX5%@%o`u zPsZz)@%sO#c>T021s6cc3_!R|v;SRcK|xLMoD@EI^E2mCI}0AhfY+og@&Imz+hiiF zsYC-(bfsdgJ(o7}b*=Y|Sa7cE`Oc4hWBveo5QN9L7Og84$PTEWa6|uziXZy!^YXk` z+jV?R@62mM|6ETb@qp$6WN9qFy4bt;m|V)q?{TXepRCiLpIzv=NTtoz&#tA);e)() z|245}c>lk3J~M`-nCw=XX%O=~+(HwpUE%Vmb4OZe427LPiq*xJ`e9eAlS z#QM0Z(U`o_@%kz?S;yO%HBQQA7Qe7OxY^=$ps(wUoPNF;B`!x*qF6?6rY+zuJ$iU3 zqr_ougx2_~O^nZ{mqb4eb}x+ZSpPC2&TM%10oOy9&vicW$;JP0&4OuXwlwCr)-Tze zzBcsC=kj?M5AEia<(BrdRdVOOnah9RoVoP&-z7DtyUeM4bD_(Cw2~{Ed{XSZc5Zq; z*E%+?uBO0T~2j5RgGY1_2oaWDt-+Kn4LB1Y{79K|lrp83beykU>BO0T~2j5RgGY M1_2oa{^Jn%e@Hx9#Q*>R literal 650652 zcmeFaeSB5Lwa0xD4iGh(piw|kqoxXqN-R}EKmj=ckziB;T19-rS5yi)1-%5Jn^d;j ztyZ+P)_Q$wi!E(!v6PD1fS8b8s^CS%7H!(1-N!>KDn+!`Jm25U-sdF=YWwu_JogX% z7|z}^Yu2o_X3d&4Gizr5=Hn-yiN#_)`0H(dOL;qF6wk#4QCg27q|L2U8h`uqw|A`9 zV9Tmqj<;ByIlE`iS_@VNv&m%!%|_*?>?OW<<}d@h0is}gwr z!@qtUPW)rNAhLwN@}gL*Db^>({6AJ!7>iAxJ~?sT4R2?^viNlq*Hr^Ak(K`e&fu`v+&)ON9|1c+`6+RROfX!NB~ziOur&|{bgNf zD5CCi3g|Z%M?`~gO`m=}ZE2fyR>SNrI0jO71aSJz#i4ebDg^vDefrExJ_*O=l)Vr! z=rh9^Ddh)t6_S>C6{)V>5`WU zVv7dEV*1UcBNrF#a!JD_*_6&Wir+1WjU`*Zd&Y6u4cA?F!}SrC&N%8Qds~>9ivtm5 z{+mAi(m8W7Z<0^GJlerA@CXZ#E00_pdLG8#^yw4Nm~>`h>=}{GDyPMY zUVZ(X6VI!gSbKu$TXS!ieXV(o9TMU!o3iP+lRv!wm4(-AZaH!3?D&zf*h0Dp{}sjt z^Y37OMc%}MLPNvl{FbA%i!m&B?q_YJXe;Yq7%QT4Up28Xw&nR)jDBgl96zyt!lM3` z^ZXckGhK;$_^;uN!r0T@$?O|X ztdR*3n{!S){f5~yYHmngj}l#d!}U1=m@;Gb98%_-IJy%IXjM-nZ&Qzvdch~vbJnaG z*N>anJ${=P;+@5BhW^;mynQ0x(X(dFy!tXj{JAq`fAwmbwEIfB0W^FJ&8=@Q_3+-Y z6O(ghpE&dCOZ7LW;quFlJMM&&Pr&?LeW~R=uT1PzS_>L;%BWY*IiWHt(zTw#M$1=D z8QVlBjEM?K#xl2ASq!#iKDjMFSqN(F2m)-M|M$5BK9|7f5{M*F@4nIY?46(b?-XZy znU^f`62;7(GN`?rrH1e9{N4|AvO3`FJyi$3h=VCr@E+VLfKH!t4kCU?7y zA2nR(I~TrD5Q79i`4>ZlxB7{-1u@^b=E#CrD|M(a+3x&`qG03@K&fOdmH5t)VS5K{rF34m}&pch00lLxxoteoxEAw=22571Us?KDc zmU%io12j%gUHGUHAD^n7xfDBP*Q}wW9 z@y}>iKl!G#tIg=pfInxo>wDlKM=JUZncnKb%~H|*%e$)ReaE9_&Is~bol;OxvZK{0 zKcGkgz5vm=O7bT}XS+#~Qv@Ux350OP% zlX-eBd}>+LrYFfY-&X!eSpOv(^GR*vYauydmZ`r>G-Ei!e^v|x}$OQ zNp`)UaHuDEdS?gsA5 z2JWH|&iES6x^Cc30&Wl1q2T|Bem4Cd(a#?LN9b5YqkqdrR9 z!+GA4x3*B%#EN2X$?Gf4Q_=b7J$r>6Jo zsg9EnUnT<4!WIP2mU(5`ko0#oZEmsI^{Tl-wEw#Xv)oSEb_HJ9A8 zwyCY;9;OQoMV_;aG`GO!fhd=j3a=i3v!T%|^2hXJZqm;mQ^rr3KcZ|RYu^2LTR zp7SPfeq*~k!cO-7bP3C!jqS09!#(FPfLf_dthUB0#II=RFr_IF^gvXtj%w0>tp*nj z)RErbZBhQ8FQf!YK9X5Y&R`G!XkUmi7(s!yXEU;8W>&Rm5Ga%TwkC>%xh>V-fMn%w zV0z}m{2jfst>J7xFEe*zriMVC5gKpx)|X+rqh#?ez10`NwO3p06?*lhZepER;MJD7 ziS>H#=O#AjeSn+TsP}R=vDqtd6I;AO$tkfF?+;vRiQs1!hXNboIi-*!fq~yh%1^Ar zE$&!aMtW1TyEd6W>B1uafOP|BLA*3M-m5A0>WkL|h3Htd zyXLss((2kWzrM^*>@2BW>(=h{Vxl-vwx+$%n_@JZuIQKD>P|+vnbp@HAvVi0)@mx~ zhj@)eUb57=IbL4U^h-ntK*0_-v8{Ss@dEXnxHrzs=tof49mfK}Hg{YxKt1M0H6THM zuDVq`cu#^HSL!zgZej;?(W-s|Z0+e2y~GY!R!a+T<3(!VAl9&tSHHuf|IwoRt9g2U zITmvgJBq!UxSQCCkPQimcG16@6^_Nt$zMc0;nnkP^L_DfS(70bO*d8`;tH0EN}ARh zmP&gh%KV{CQjzMp#S0G9q$=d=a!7XP7K^oUMeuJ?KLdAPM>L<2 zyHfyF+kGl`Wqac83@F|ccO8V#=eFIUA$M~R?aEz!(Yqz3iDLRsyrgNN8gNXJKU-S$ zZb=_r&~d9=?MAt}h<^?ivRm;lV>>ffx!SFAZIg0c)QQ0Pz)Jit56BRxS&r2%)42;v znxs*dxc5Xc6u$SFDBOhM>6XG?pFrVLeey;4yD65!p?jpTprmP0hC-~G)V2uu`L#RT z+HDyrc2?gn?uojqs4>&Plt+Er-D2CL59>tTh>*H(;;o0B(^^K&LmEHA>@bFemM2-Q zF=JeDQ(Hr&yJpZkUF;f0Eyv!_dDUWHhj036w1j7|XDw#Yf52iMWvj@sm>GX(gy%fQ zX1BlMA^uGt?A4Vqd{j>;PWEmcBR{l5B+h{OsvXHcc}x2XHqq`kZu65{82Q}#t$zJh zw|--KidVmt@o*Gcy(N9D8D5I2#up_IvdX#Di#g4uLN*iwk?!F%GYV`q!zSt8s5pxN zaTFCZ6x>HB3!QAWlh_*foI|P7tKW$AW$eP5318q_5YJgR;sO~=tJCK?+b3f9th+@k zjP#t5FIX2w7M$wVrK{vr@yKA}X<;hZ++PE5vY$r6`eJWL)s%R0zouQu6Dpfiw@U32 zTb*XCI0O4=kQq8f%Q_YAY3cY;`o&=Wxxm(!`U^@ChgXlku*FYobn7>JQ_8$a8d!?V z2v%GXT#1qiVGTgrd~7Eyg$N&D*LZPrgCi2dL8b>?dX*dlXWc}@tm(gQ3)~J4S#5Uf zw>4bkE&bc`5ZIco^CuKnJwJP#`gFY6kFTj}nKRto@nqHQe;zhyy}Rc9KdpHy?w7r| z=1)DUHYJb7dN(yU9Kj-$iic`hO*47*+uXu*k+*--i^=7c%nt^;yCVuR8WeA8_Ln}w zk)wtKDqjpPMrHh^Kj#&cg&vFcad)FU(aIN%XNUKN|6s|s4p?x!w5+uWkKYrP{k^%x z!HMU@VpS~-{d{LNX>Ot@>zky$H5q?$oKenfs?h-TN%h7eFgNXLxY(;Hf{OFKni2e* zgX7^h?uev%ASP;IxTFovL0+xL$M`DE?~tEy^|5psWGNQQghr*L00 zuxr~tirRjLwjXG@Uw2lP`&B%P`~9g_BrW5;3-`mU<{Os-^~c3Xw9^Ns*gkNUS5pB= za=vr=K%a=DG8Jp5j0{nz`4y^aq{s-luMElX$~tpDKJ0bVcG`}IxXY>SOjBEC`uGS2 z(o7$Z^J=V~ms7=S)7A&COp3)`ORSGtdp)n>_ed%d5vzEA^>3ft*Ry;M=*s6HQ!{~`l05X_*{*J$mg>kRlEwHZ`Z;|md|!x#piG; z5)m7f{V9B&;~Bj^)0P? z7H^@H@BF z6vvcfly_O)sFD;{*cAI#GPcDv$wUT}Q?;#!I{dQcQGUaw;-+2h=%NO-NN_REhWs-# z{;qSATm9tb4riorA`n4r-XAu5rrr|gYAodZb|0R}`fjO_OX$>zyz5AbWO6glsb8pm zeR*c^K%{ zRhWmtZrwohFvP7JY#xTXbwkXZkANbD8iE@i{(;&jrSMo(4y^6!I_`j<~MF>O|3If!`i=gS7d?0P`)T>zmB~$O1V3Cr zd6A*nK8uU=-u4*)+`x7Wq!jN7xOQub)PvQLZBvkb|Gqgrh<3aeW9WN5-e&PU+3qwJ zm;27#_wa&iA9WMU8ZIKGD0!s6^i=?S?>7^ba9e&rIBHL7VlHKEz)-4Me{4 zDrnsLbr}FR(d;E2WnF22SKExO>*v+qjbe^Mv~;FrWU$JmIaQgotf68A8R-0SnJhJn z%%h#w(;FWrliv9RKlIjB{Lp)!;-_3)4EH~{SbKxC&4e1YIm2GEU-~pDDQPF0v|B-3(gs{OYhipV z9?2}|w6FFI{sMk2*a490%iPD#Eeu3`ef@zzJO_jy9~A+;%PTg46$5Nmk@`>4tYQvY z>-^~>7K`nG7kokUs2$lDDz-^f>kohU!@a@zl?Z1KQ}F{9XNWI$Tw&Xq-Gx^-{|IP} zwo1oR7FU;QAERVtv*BY8srAKEw4S^1xI~eV>=2T4KX1%VCsjO&1?Vxm-O+Jx%ty{! z#f%3{yKdfgk-I*WlBVjW_@Is1vIkN&w;-jQHO0cvXqA|0-Kz*5Z)f!v5*I4RXGwkD%v6KwL zhXHq6)_h#Z9?b0yx}hbB!s^~7O}q3mCSE-bv#gnTIOi9&EBeP z25e<-Y@f$g)%)+4|BH5T)q6`a_oNLKU-e4GVE%0yk_AcHkha#c zu7&|C)3rv8!rqfDZ@t$~EV(`^slB}Hnj=e%)Uv~8=wS(|b9MEE*RYUukbo4;Xl&Cq zar6i|&JFQm77udPFJKA3yEk2x-K@fF|EpE9Nu%A|F>xBy9b;w~#6Rl@z(rO~So@L9w;;bumcZB-T zmiod=VXRMTM)YJXSX+ugFeeH~RQ>z$uD1W9EVGKVfY?eCrH_&6`G}beqBG+YG@g$~ z-qbv=H#2qj{d5nx5-qGhzEs_~)BU*N5RE?%!-j1^<7OOVO5E7POYW4S8^$zF*j9_E z?!|1$7_i^StfeiL+H-w(la;BjII8b@QdQr*`SpdXTZl7ROeYA*Mymrw zg7`INZTT+tqoXPA@R07UJ>VWbjt$?R0wz*?WM=gVWjdObdn;ojG{q09r?Wp8>e5_N z-1nP0k}so8S=*BBk?b&rOSX>!8qsk#21NW!79HB9G@-hwMw0E=eqM-y)stixdgx7! zS5GZ!IM*Mu6O!z@F)Xdn3ps%U9HL+g4Qv;2># z@~y}g7H#+i(+N?5IlCynE?5hJ?z;5R@L(Th_Kv#8j|$EF(e3Nu$ek7U>fv>rA3w*BFVc2uPBd!hWhIN))~&87YUnQp z5xfXS@IeX}(y56Trw{0qQHD<20mS$j(NNrD(eS zWH*fYIhry#aR5n$9h#oUF9wVzh1W0bgl8%V4??sCyEU?41<*&p{c&a@5Zo@TC(B8o z%u&w^#5e-K(OCh^!4LTj+VsMFe>J~h{=*;JYIgiq+B?ME9ohcSv&A{r!lFMnZW`^jQ2@b~z>PZ|41M8Gx_kH(ehSnDs zH#4%bNm*1qub7=b%H)S2(-_6+({rHt>FC>%P>3#?+OMc_N;(nO%MPh_!8>Shhq8;ZHLz`mXz?QqJiRSyxpMS<^XIE7FA1o23o<(UFE{Mm%_#EvJ zlq}ZzMAd@Qk~<#Zp?X2T68}CP5NB0QS;_6UE3sxk$!%tyQ8P@;X3h++kNSyB8z+*(oGZx}DC zszDle8pe^vEhbUYSa36vn12)7iuqEg9Ue+yvS;?(Y9$5J|0AB|BqKPn?zT1@9}+&T zZ-%k+zQi)jDH+z!;8m`#Pml$2EtL%nVK(5P7crwpd;zu>O8g!W+jjQ(-{L8{N-nLLz<@J}ck?)jU<(@3;z zpDo)qqT&i7@PeZ#l`_+IN2p9t9+(@vQQ4+3#eY65q-~(LRFK{n>1Sx4w0;7Sm^@3} zIfJjL+!Yej`bFg0(Ia_8`ardcLAHW4waUI9uncG_hS;37;=G<)LAU;ihWm!$p40a> z_2In9Xf&A6hY4uY8%wWdtvy@-s5HZxLP$-kx~xdCA7|=Ze<0QD<<*rFmOxwyD|PQlbcUXQnJ`52ML#`-NEqu zN#^w?&j64yg^Zl&*+(%SW?S%NZ>dlqb@n$=urWq&RZr9`{KoZemDn2Ffl}C?RFb$t zrK8!!{YpVCcI^UF)>T!jX}pNeGPy~@1PCVHy4+|*pXyn|lEqP!?cVCs&K8?>S`}Gn zP5jo+pfx=#k<2`HN(BGFzs^Qy+lUV-c(97e4if35@w0A3CK|-#-A|sp0d@h&ayO!J zwj|VdZUNTvf|&-F+tM)58(*$K>b1n}>hNVlS@nuTU?R(ywAfuxo+pZg|uVDLNj|rq_9CWAmjq}reg1=Ff9!>F|SZ8Z^ICF-g_z*suwW`#LkxC zfHs!#%nDaO8;6_h2Mn(Rgsm{+-Q@PPi3Ae4wHtirS3i{Qua}5-un*Rn&>kN;Xm<+J zGi6AVmsc(5mz>U6g`rGNbs9GmB>P5+q(~zQ-*Tc+(cyYEo`H{$AnlP5yTC*BibG*NP3~Z#aKv@OKS=ck%Zq ze=GQVjz7ug@BH-!pU0 z4z}QxFWT3`a!Rk-TL2$WmqB1(|7l+h`c)+Y*pdM-uUm5guvoFwFEaq5EZKtMr=s8~%gp%$!~q1T~SfaY1joVEooS5|+UWuD73SyzaWv08U%NfSAV3av6pl_VL* zAU~=;-%}opr;H7*5RSp`ig9;dX)yFSo@&bE9@JoJO5G{!JeRQ<_vQfBH*ifP6VTm+v_SO)vW^qwCHpYT@X9 zYfUj^Ft{i`Gn(E@Vr4Tf@7>J|s%8r-^zv*^CIZp&P%a*>Ld=$jS;yw{z$%ldpTeOD zGfGbq^@oXis5aC?wV^(b>en+=o8nNd-|nbZdWPzgK9%YbW{xubds4j((z|c7K`U2l zgH~#Zgr88ope%WMWwW#TN`SN z!0W+&%>c`NneiMMmPGF%D3#aP&v+X(I4-ys;exgLZq|`!7ln!Xu@74=|A6c&UrhI| zdY4V0*chDZzfc`mOS&J+qfRPdZ`%~NICC}8qqQ$F@x`C-nQL&WtEUbHq>aJg>T31jjTwi0v zoxG%rxL+F-@>%`q;zn5|pVSBP!^4%8lukc~!v6z9pJDkf)32O$7e-MMn!DIF)EuW# z=kxA@L+7+1B~30544$L-3EqB7G;6B>ePO!wZq3l(89XAlW|%i_a5(0;H5`q&^}kU{h8_LV2pTNi9eKm0 za?)L+{Bn9(MC1fZBz`bNYH(+Whdfq+A&(&*^3WIvtMC$r$V5eJ%@EjQY#yo~NDlgj zWF`jYlDYW-OQwE9GDW1jBQvTiC+yDoKFEL^A7oidVw4Z^_>rnE@r4CB=5n@W>)>KJ4Caabi$T0Le!auo2@W6G1mDx1x+fU|lU1$7oTZj{ju zrb6_gylGFl#31%*aW3JhAT+VxW1R_*K5j_g1Z9AT&cBK7GJJNop z9kcCsGX)e=RiriyWhw-$6JVy4i|WyS4o^}0{n)nOLvWMdemOMD7o(316wOClni<3z zAS)PTh%I$@FEP5PIYLc8f_y{oY4DrWjPZ=7tai6!KB?(_jln89FNkn4HG zO8BNwo~1C@sP0}Pj1kc)7$Y)~F$){Z*p$Xpmo^-*@Fr&SUu+o@FYtP~Z1o;hG-(U7sH}0Bh6*6Ozn4z=KBY+diYw)xMJBw>#=cC`TsJ$aF4RyDhu1D z?64hRoRiTgS^)wia-=dnwCW@T+Y4zT($KA3^j^@2B(C0vRuucmKbJVcj%Q zG@vat`cLeXF;<$GzhdKGOY_VeM=P?yfn(II>79L>*5DPM(ih>)RBFw%UhZ4CJ$yPeX|%yM<4F^X!d((t_^b>LCC6>` zopCSo3${yGMbiX8+FsAI@6;*hedQ&1cX#J3iW)8l5~c>Nm|csZHyBygHG9x)srO)3 z(r8QlJ$zcUeV9DOE=#nABWL-Xh|lB2SBo~bJ6Q0Xo2dfhT&yg^^0q&STm#fF*>4Ki zw*;`5&3m)&-O(GsrfrHffkN^090mAwTY|^*^sXto_{E04o&l501X)%QTtFpxhcGg2 zYPRZ2t()n^CRNSa`PBiM=nF4}gTGR;C4NdKSjYzNxNP-u)n2M+CrM5UJ@iG}MQ(OI zHi{|qe{l}Yl+oDGTHZqqS19&>asi5zc$j=M(SXNN(@Nlq%J6G72rABu$_=2L=e$oa zz6>yAH;tkisbVQ0txaQj1BX%VhRH^B8HiP{8TMQQ6gQVEo&2x%bSvs7}I#5bZsbR$x{Cf;e5*5nt1Hf6Q=&UaK4(0vz^ z#hSe&T)?yMJR0V_=g?yd+41rXX>D}Qa8Dw66t0b=Wu!rW2hT5QsgTeGakm!*b&fNC z?4o_8lZN71jcW_@Yl2m@2tH;Es^c5Uj0+{NDZ1+3IgN0nYr;Q z2_l#eKA)Lp{W5u^TpMD}-^7Dikmo0~tU|%9ZsQYP{S&Q;$8+l;kNLocOm!MssQ_wJ zm8s)#e&Rtt>ZnSrYhcyjkQbqgED9Bk1{r6~6I-hjTN;k_oraveG35EqF*b!G6#ME4 zsr8{j{l>r0R-Eh#DnTsgOWUcYX1d)5Q>AZo-`)gTRuNnZprkiXzqI|wzgNL!!gwHz zI_u`!lQxOvf;tB%Id;nh`oDmh7te?&ctd@TEQ&563p+w9Ion6zw9%KX0Z?#a{T8jc zaL5OrQYXPVcD|Y6Y~D@`@)x~PI}!JIL+V>#aT>Q2lsr?~zu9U3yVE?JAV{tf+1ir$ zbAeaL9;eRK^Ag&VW!IZ7ROD$rJov@$!Y=b)$kg~aob(~XcsWQpSOq|9Vw+k{DqXVp z6m>+V1`PenBwH1mS+_EbS4fcj_!S@*J)*;lOeN&kGy>9BZgE zbb7OP>QbRw1)RfW+;F)upUZ|ToyLs?5!aH2bPdUh=JW)MZ~RW2-BWXMDOUyaC3Z+y zb||?m7hDF=i?SvvO!o5vsC#dH_{5=b`-U4@xhTu%-m{APi)@=z5`Za~> z>RQjv#x23;15y42<@+Nrw|>)d;q-MCpVqyamgvEI7N^2@u6Q2#+;f`&P)x7ebSM9M zO-k|ZQ4!AMIyA?{rTDj(9;nH0nkh8Pjs;XDZ*g$Z{ zCTm}QBvQDxkDF(WO_JFQzHbxh1G#~@ka;)+gtkkRQn1Hx4oPJ0cj{In&J*O6cxCf( z2c-)}Rjp0_Lj;^est78BxKOzxZc26X@MA2IF+)$5koByFEd0MmdLC@ zh3gG6wK8>TNJ#;je?SG1&!E^ejuTp!Q!qMPWkS>h`5dAn==q57c7a}@h~oTmAJXNl z9XHckH>c0buizYtX{0pD!ol-W*b^B+Y9lgk@kgnUEdpsq$HLIW9h5XYA%~R!lbkc1 zK?6b!O_tfo_7YqpHLU6|3~GTRI8wTkWK)t*JB;^7Sdg|5xw6m4woGjPyPK%LSs9pQm;;*DDMa)md^9~3#L^jZ!NNj+@ z;34I-26yX+_FwPA0+Ul3#H|7MpU<_`w482d006WHz}+imy`z4 zaNZK^c+ezxV{~m+IQNPN3!pCwec23z^zwE2X3)7#B^csn!Lv~-thRV6w5SHkOKYVq>`Q>+TgNaP$*?O~93Qi+O)QD9pxjN*;wOIt8XiB8<~? z{^gAIB*N)(;B>xeBS4w+O#;fCf616iOoKgv3A=ykS;`X{+ncT$Z7qO zaC;TuM2DOl4IH&B(#aQ{1gN-`0)@S)0NVWeH&8ye{wdg01wlD*{#kMNUBdlf8Horp z#fs!NN@)j!mXT4@^yc*0n%nEllL=``JrI(KFka!=14mz0gH;;*Dt$SnC97wY&Ec4m zrf(yJ)cqP4gz_oz^$?kw@2(4Xf`9Z|a-q&|d{aW5Z&0r{3MYPGZ(pG$>q=!MaE6m5 zX=c9bly z@n(}|J(d3v)ZR*=?T=$Qmlcbah9jg&50RJYn(B^2%^eWM!QMZY+L_Vup@UJd3-?83 zrtMs{KZHkq4b*efLE!8MFR42Yh*q($4A1>KjiqK4qHvU(C~Zp(f1#s;62y!sT!O0% z*`lDi$nRz3IsC5VPw}e3F>}Ke1TxZQvd$bV7Tsor$QEBk ze_krkC%@0q#A2Sf+^NfH(prH z+#D0Iu1yxYWO1vsr*+W#f~1V~F3cL}{Xn!V9;qZV77RQBhL2#yFSS(lYRe@FrRKreT}5xfmxKlwQKofJC(mSr~HE| zKQf)rVkK%+dnm6HIuZU>&x{~vW{b)l2ri+x1j)^GnIj2%@hppeSxa~{D#sbLeP_<2 zQ7>v58TH83Bci8Nb@X)E)adEEQ=+GruGf<>vgeywySwP5`31}YZ4y1wTXeWdP+j!P zoSc?L|D=Z%guaW;7nnlf@eY4Q3%UM+jN{!)gET#)zNqT`Yu9sG%0eb zs%174qjcox1Uru4u+Pd-19N2th4wCb+9X%(OxU~?b3g{`puI9gd!m1%uij(~{uK$#E%1TaYS9kfNYd4A;xS(n zycO+)&qEJauWjZ@HNAr9X^Q=$n)g-B_~hIImfgDfL>}+3IBWdXPKeX7IEO|!e^oAS zbW!6GQPTI7RKG1#2P@Owc=-mIlu(<8*|`;*pj1}A-dt9><{juey;YxGt1C5C&gNp( zXR$Q-0y&kTK=p=lJC3TI=Am9)5m%+VQ;XbrxrgDcz|d4Z`fxXeaq=6Z0MbCcRD(f(DSV>^!$X;!dvmkJku1%`AfgW6BiC^ zZg2+Dr!@|;`G-qV?e64NgFDNnYx~9`q^oyAq1yL-xCLYXNbtuCU0nr3nz`Yq zQ+L~w-Yf%~zx21iL~mXQ=4~r)4V4^S>7miktAH6?emQ_0mEs~=1P-rKgSalhVOV_J2;8dh1Ij|-E3dWP}@ zkAo9APz6GSm1zAU`xUB4U;Gslg)`I?gYyB4v$Lj@`p)Gmts%G_UO2L`V%ArUhOm)% zIZvUYA4B^g)dQt>G8V|<%M5Pb*j1fPrzAQxH};z|yKA7vU%iQcHOUH%&A}>PH-f;9 z5#9vd^4*L3nYew5e^F^-l!{x&6vg<@bJ{4`IwmeDa9fVnNtP;!aIW;vB6Rz z3BYw;gQB1h-hdS2_jtDYopG^!|Iz*SeRY+6zvNu|`}89=J$VQ3VO0gHO3^w85Ol>p zA=E52$S-~-3$*nRfQ(Ll_&O-UqAjGhibVz;dzH6o4YRMB495vwlciHg{_4{RpHXL> zKuc7$lsE^I8ey6briJqc#*$Y@Dc7jRQHmO`$&t}hXiWq$9*FRnb`Gj|?Wm&w4OVgw z!xw^b&ZN%tfp)GO65R*5mQe#W#Wtf*0q?51;S$xOM6_*kPCe~RPi#}4yoaU^8(J-H zR7hnLcSn8uwXe zCXOL9&dSp%x&6B^;IEzu5|wN)B}<%J#CIs#@AnTyo0M`M{Ty}h`_{MZ@A$K`kn@40 zQ8FcG^6rh&ZNS5GTICtmpd#E8fauV@p0x5jG14beUcCj6tOh~e*xp%!cM#H&Bf$$* zqmiJt9mUaBWcn!*yiz!<1YZm#I8&waC79XsHSq?_N;iAXX_QnX?8Y%k;w!$WH`MM# z3XeybiK}Z#U+=Fr>7g*s?;_pPXeGmlpl z(tQU`^H_N^gh}#U8RDs4P>__2mC6JwekCJhg1xN`vScIia3%dI05s9p!kVF`U4sL- z_kwq+j390U|T)bexj z?79&7R#}!v?YU5AIL)31MoxTCFL#l2V(p2%QsE9sKhZIUQqeI?qoFx>Cyek{7hH!< zm8pe{);td$FBTmBz9s%_T8t)X_nkw5#+?;g?9ns`*5 zO)~KlOWgWWZ1zmV{}ZZQ;h=?-6~(Kq?EPr}Xa*f+-Ur;x{d1+0cJ_p>ppr zZWIHNLE2QOG?rxUiDVI{wLK$+%3ZC7f5Qh7IU1E4?>6ZYIkTu1R!8?xb(8wQE&W^l zlGhhld($f5?UeTJQ5kosgz0V!UVjf#oxZ$e@taPfB$f4$G3zI4Hs1bnzAzZ|E7bcd zy!%cn%x&XM8ob7&z8|Kp;LR9!FVk=*gEVzG%+*-#7=44uENoZpD7ob%h55WEt@SKO+zMzr(NB zWOOTM19i0O8kDW;biGFm-eV{O$7;%^-W8V_3MOYLFq^7>RV`4^gYv4)<=uA%{+Kt& zeQqjP56RZ@8o5y|K&KzbRiAqS_MOVG=&ihEYaL6i{;ZCa`Ld_;r4Z%{!Q?356ocWk zFn7FijW*}$aBH~`8?%?~M9_K`Au_2;w2E&Uz;;{-@|&iB(FDNeJuWImfl*^|`G+a_ zWW2z;?>HeDYm{s16KrZDe$AJfI!xgPE*Oe}ZP7Yo@3a1n{St(A z9kf`14`2qWxRx4di^~kD<;!Rb`i4@DCxtWEyMv$O2;+RZEjqoZgI=chl$!#Ba|(R) z)3CrI3gBgj-$ywRK(+d{WD9Rkz2^pY=X#ZkwyU2o^y)UureT^d#4B2zxid5n;g+lw z5|ACXNPT^k+f-*kr02okNhA}uG}yk-JO;b?^%Kk8Cf$q-Dg*ah3m3F1v*|o?*!~uJ zw@J4kN%TKqCha@-{eU#t{-z5BWIzoZ5C=nv?>wA=xHv3XXwp|@(yt2B-};F(Y|a?$ zWz$U3gr~J>R^~}j6iQ=bbfHcLv^LETQ(6)W3*4r8ym^*BQRG~UNJQy;EMn*^d6B?^ zMk@22O(7B4^z%*npOsG0b0@2)F*4(M^qmjFjN!_#qQwXBosS|!7WfW11Ll@^9Jf`% z^gqn5!dgTe9#PYH=vCIHpaSSEv7!E>87MgO0MCCH+V?~K|$S~I-u(}!- ze@fT3G92L^hUIhyKr@}D5h3JJKniR%U>P(~=HEzU{l96lfC2iZ-e*`n;45Imdn_Ox zP$N~xU0Y~;vvgsJ2&!@Myi6@GsNg{sQ8x8gCN)d-V|wosL5UZ0s9)Xgc4hTUv9?9r z%|;sTDfyvB*iv!KXUI?gmlcLn(qv8pM*S=3`I@LPz0Ih^4{?l4Ija)$331C;iBfpcZ}%aNjv0Y!2m!YvtTw zaz^Il++lK(H|FZ*mTc2qPdyyL$Y?~=YA31wNF$=eqm*dcBUsLANwyJ&lF_wk4pXXv z#ey>XWOab|xZX!)8ey|%Pxa(A!rgQ+HNv)!Ra4ZLe)GfJnxfPvOloKw=yChg8ME{Z z4x9C({z~;CLm1ptnhO=0$KZ04nr%0Y;OSwJLPf24s#0+Pq}5sDG8j5=9>V(O(@xpE zQt}q9lWotL-(+Us^JVR6$k{5BI|JY1CXCDdYcc?kWuI&xg8}~~D}fR}NbfObeHSUh zvg0OloM{h73VLs3-I2|Cl%`b@j|y-vUQ(|ajTDmLh~G(xA4ILOc`F}?${R=WJA^T3ic~ryxzV!t>Lw#`k-egni0>E@++z4xueL;W6W|Db1MK52m z%G_*D_uOq|biX+GEq;>JxK@gicwF9QVgoB=e0|w)cuWe{BC!E$^n_$4mJ;p3I3{w; zieC-MS=d_)8Ua4HFSS)cQJ6J@EX8K=Zt}mUeEV+n=GzQh9`r-X_U{`p>CquII^oo5 zEof%ArWF|IoHZ@vzf5JnL|J5m!Un$qMq;{)q1i_@X#KG1XWnQv@e1WQzyELG)VmYQ zxT226Gps*PX=&mULUA)MDb{cxR!D+xF*(`N9D~>-G>Mp`*9X9HVeA;fK0*3 z2wWQWzR|E5su_T5CJMlmp3bB1{8yN9w#k6>%^Gg86_KQ&yzuqgJNN#o!Ejr}S)`)iWjCw+{ulnc#^~q_^rF z)!^MU%?Eu}xSQe&UMXIxIX0)zPgjX+U%vqktU2btUoljE*H7IZ3{gr5yb|blNTGb40>5EJ2o2^6v+9uleb_oxx@u2$q2es$ZP)s^1Su? zHWR0DE^FEWL~-jeUmS7vh8wL2@+F$M`4WxY(&J+^?5FmMGQ*R*3eF^g;Ow}*YIQcd z|2%W0WwFH^ep83G(U*JshZOe!;vbL1V%IiLHfLOp3n5IjygiGO zG>dwTa@%Jqp8^1WtH}g-k#VBOY4V7x_f;>Zhm$=M0He6eRY zy7|gZjB3nRcGwKiL73{^d{1FQ+*@MV7tLHZoe-gWbH z`QOFSAvk>(=TLnYXRqX!te`A@_VD1q#F0{qtXYpgim^e5UWx9F>ug zI35*mW47M8jq+QgyB3Y2<~x7W<^{S3<4(>uZ9e79&%K76P{*=0*>gOf?VM3q1AUAG zNt{aBnRg*^P_7y>=bO6u7EN2K|LiDg?EK8rU%z70x|}h2`9Zo#bjG9=F+`?v3cqEN^zkH}y2^Zo!L|uCCyM>KAL%q> zpU6{x-}zfS=uZVo&>l0~KWY)PDaJRC?O}0UuaSC}^qdxEu+qox^i>Ql1K2Uat=;Y> z0(T?drSOMxLErXGA6M1ySit47Km`7XpUHWGr(mqbf2dc#gFHX}4X-|6XmRVq^EoLO z09_SQyF)_OCrzNLfkdCfm%?AL(M|4Pb@D!0o3J%?IMD0m_6{#W^SLpPQm3jEyYlke zxIK@Q!6wDDl~3#+DF>Sr`p~A9^#UFp%SR-m)zs;*!B|4RB=}r_MhkA3K zSKkkmyOMLNce0QL{bhm^MUy+9>NO{ry756CGHRZc4F1P%>d2{p^Lmq=w*#=DaQwBl)AIeMA?bZ&kzQgpLR2I->A#aM*CjvOB%pmPoE~*< zOn`d>80P+!6PrR!?$^lebb@h+`Q~7|t=Iq^hkP}E_$}@)p^-STHGMvx0`MER zM?Gq|sU>4eUt#b&q9))oa+@|Ei$`CGH`P5<7r2G=wv=ht?YJ z;~VKSeLjeyBJi|COIcbS4sNFUx3oO8sEFk8}=ks%+aXrzn&+T;EaBXQZGubmk6NkX|Lw1q8 z_E%}-b=5cdMV^JccWRk(wG60@0vSW{Yk*}Q!^+n3nlH-)8LN$Y&^PRzfK?UGM$6aDex==Psop``^K+3I>z7pa-J_hKSf)OxfRIu0x7v& z%U@)eD-?w?m_oX{)_F^M5SsW+yNN?dv~zdYnm0+_>h9=)U`+jH6(kA4>UK=frN2gS z?Spn(2qVF7-Y+U-go!V2nsY?JFcL=HA zj)7q*v-%!G-!^^!GSSYV#ccP!0#q22;Yu>ZwyW~>q{>v7UIx9&i{_5O(}qq1w;VWY zR%8i;Ah`M+(YJB0;d8sv&x&qDKmxCz7HWNY6 z_PeJ|e=fOwt+AZjs`*+)|qBl8S;^{UtNu)J80HqacUAz8Bh;UvHr)qEbAb))tMGQ zJx>Bgcdhz`ieCWnIBUerno>rFPbq3V-DAwA-OlcUv_Q&9rpbcZDra$Ay zT1AiSGSPq;9|Y$ku|4!eyu@}%xdnpdf}lFqACVG}{u7gqO6}CwPE7^I3;U+h`Sc?x zp;w{{g8v<_#G)`R$*Zh%`88v4XXTj4J2jr&T9PGUQ}H0GNf+wX(06d=)v&P-uM*oO z--uRyWEoh#%Kg^cTQXfnOv3@ou9zs6+HP-Qqyh@rb^^s&QDbNiXtWA&;>3COPZ^k9+8RlD^p|3ZU?&`Em?&Ry8 zV&O!{q_@#FSUZfWLSL_cHg^cQId(W2f1=wFbl83) zuh8k6!Rqhkd#aKXEg?~b&fq(5nd0G15Z@Cs-QEQ8E#YT^Q1AvW>P{i z*(y<15&V~e)3CW=EARiVZGqjm&#BYsqQt*xV4zX7?veVK<$P7NH`*{#i_p3tVc;z! zqH-P#XyIoeK$!~?1Y|BqSm-4dDojy*6cmQIlh5)ltyRfz6OFoT2X=RMF2w%{yrRt{wq>5JXOVnQh?ryVe=T{{iR!db{uJbM;t zp_li0(QhI?iScehm>U$HMi8lHNyFf_IEC;lfN0ZLk|&l>WYbd9ZUd5P!rK(i5grrk zLSm+u4pA+%&k4%)B{L4y?4Ld?Y({d*guH(!Ptg9&V}oX2;WqUJAMx&4W+A2h)+j@? zZ@Dmsp!ArV~1X&f$ESj;CH) zbq8EoH^6MWoDU{%kvA$jH{1DC#SC&%aAcNSB#o0x;E737tg1Bm)lfZxBb3MhGFWUh zpomq8;yIb4KRryYH)=d9REI}J{cAM~vZAJ>}-EFWKqYCYc&5> zI-e#3^!GQRiA(GX8p^a6!3h^`ed)zS3=7`_pIEpW z&{ay0!l-GJsg)g36t&JgIIo?`?qy;_YBF&8B!&728n=wCXOSlvnK5&Q=;4fXX-N~G zkY=>9ps>>js02P%JGIB;qq!spjcLQfgoZ<8C5!(FT{&1z0g^ihZOdgpxG|YE2Xk!Y zh8);^Y>jne%@Kes(eD+9lo&2_kI@Fndn?HiFJ(%2h0RkfHV=uoeKG^VE({PIoV+0< z0nj5^#z=EJ^F}-s#BuSWi^;x#!G-DqkKMYRDQC4RZe<`IRyT2N*+?8H$ znnXuUqeC>2UU81bpEryZL>3TR6FU)5ES=HoZQIlUJLnzz;73<+rSO3r_U^Ud0#(>D z`=w{38`^x@5v`JheK~lpnZoP}tYr)P4gs|ch7DuhZ!>sHUDiqM?cf;;5ZsYd>U>kG zJSsIsrAjq~byIF?PPrrU%N^FWHhVIg1=Mi6mN8n#$n58p%iLOa^0x(XP`dA!<8S6` zyWY~%`m;Y>+aB)y?(g!E@!D-}W0~>Sin$pFpXAnsh|u0{Vo#;pDsu31OT@1&WGCjr;HQzma-txdOOdcY4-uPOXMG&QNOuv#@&n_>v|zn`7SU zj=nk$q=j{E7E*ty!4p8QDQ#wf>YH*QI__F1cn}nZ3jg~*8yPWA0;YA;Se5Y{;qyut z-4s6@oA6c8W)Un75uC*Nj|0@7_EHDrw`Y^V%wcv&m;azXc!Gq)+CncMuM{lKK4j7* z^|^aE6%;E}BM5EKqNi>c^PB?!ahivz_(-TDfZ8AN3(=KYZ-`UAcno1~`6Gp_bu+^7 z4DkkwXLble&eg6KITzRaoH8q`@Z%+>DGx5nW|jGMYT_vC5h6pPQssV~S~|+wmXkHu zuTzspS#3F4!~D8oIaxm;YZCX&ak|nSq7IgKs@5vG{c4*xcYLt^DK!rvkPwezbG)0i zB&W|@Np%}%d7bwUR7*vzt%-BFO}Jum?;8l0Pwyb->twLWbnn6nbJWeOYiP#A{r<~r*ad+p;VKfw<1W`Y7#_0w8J9>)t zt)9)*;?p((D6Wj$z2hd}>QZUktnoqHYO$X@S5Agj5;;?8_>DAkKckrx?6}M5WwITu zlxrT$k>c@t!`Em(v%W^iOGLxH=vz+UiM8RG7{C#lu`e+G{?qLk82Xg+Uu6=r7D3HI zopJ9qhKM!Y1KV-Ve7VGlEn#R;Fh`n;i4|-1+n&Fcj6+J;fFYPXv6WVh1>+5<5tCmt z*lCgGww$m*>5H?>dYvevqBvlsb1M!z}dwORf)~XSJV3&6zP2`2}<8AO4HkP z4sdrSZZab=-DhH~O*H@To!`iENjeM(wCjB|9)py=-fQfgPRT~+2U*?Y^Il)#E|inG zCZM@tEWKF>C4dMaILwsf94WyH1GtNCW%oz;>?uF|D_H%&jF8vu=CL*1J0zJ{rHPW` z^$Q`#T<-pW+8$rk+3NrlGPw=wV5U5qLx-ZHZXTaJsb@WCn?i`{%gn=AFS#wKRy8%_ zBaL5?z!MM<8k$7sMdE}Y+8OaR0(5b6b*G6&*~NV z5Pt<@1aW8xVZ0OuHMUW^jfOf4xZG%{PlG?a6TFru=y&GU-95$AbdI|*_klz={)n

Y1?-`;RfmXH(_$3 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
l=tw))A4NMlP8@r2z<;Bhc61y6 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
m5X5L^pP{gnKZz#+l? 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 GjsFjNt8Y#K diff --git a/XPSDK/Libraries/Mac/XPWidgets.framework/XPWidgets b/XPSDK/Libraries/Mac/XPWidgets.framework/XPWidgets index aba93db6a058120fe014641b395c679aa30a8827..16944beff370b45ab41c9307ee8826beddd70124 100644 GIT binary patch literal 195312 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�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�V403WGmiRHX5ue;jwMztd;Q);o%y(dtXYE50 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 diff --git a/XPSDK/Libraries/Win/XPLM.lib b/XPSDK/Libraries/Win/XPLM.lib deleted file mode 100644 index c7b00b10f0a9d20583e0f4c37081aa2545a04fa4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39362 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 a^q-$?)%vcS!TLX+gf&nA diff --git a/XPSDK/Libraries/Win/XPLM_64.lib b/XPSDK/Libraries/Win/XPLM_64.lib index 51fdf7011bde4bbc015cdef5159af7166eb6417f..cf5b4fb988a111a41cd034163cf8e4b5d07d58a8 100644 GIT binary patch literal 51320 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 E0YsuO1^@s6 diff --git a/XPSDK/Libraries/Win/XPWidgets.lib b/XPSDK/Libraries/Win/XPWidgets.lib deleted file mode 100644 index 1eac5bf707a8ee4a8adc9b8d671f9d24b338df27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10524 zcmcgxOKcQJ5G~u`XABsy@!wwm4I~a2ulXcO3^oP}+lFJ*Co}OWsH5sWqJ5|;F`cqY1UGDxd z<78KUs{KA8KZlPT8A~RQjvhZE^AGu-BO}Mg=+CRQ0B`|d&k{hxeSpSS0Nwj2wcQ0E z)c&4QM*)CP>r+ZCuK@_PPEkrc1|Zb&hEnef07A`sD7DvNKZI^m8mI>#)P0Xq&l&)s zwoXb-4*&>tf27p)41iGo5T&k3{6^|bQA!LWK2qN}rJlFgA5!lnN}V_sLQMmd`X6FH zNPRdTLd|z5wXER0keWYG8n}t$L>f9lY49Zgp`j;~2Hv3@Y48f6g@x%^^D0v!K}jXOc66?7`{(#BaUXQ~<^FKtX0sr-^vv=;Mb&{0T` zHm1}sYeZ?o$Y-*?*$@x2gh^{e!st(5Uqh%|u;vVgZ%0TY zZJf;ct~8O!=NB=E1*@eI3A-392!r9f7>ERYamhn1L?L>)V`f})V!i0vtE&I#WEjuP zqU+c7_Z-%$d1hCqe?$#lwcgWoB7|a!5k7oy;8|1y{#oVeHpbm9zBh_Q>aSz+A^Z0F}cR=xahNonHrZBM`RsI?kF-fi9B;nrl#hI zjE_bd?WTf~>a2oDPKyOWl;f%@{Bk1*=#mId9FmEy91?~cI;0`Fbx0bRcSsbtct|8T zx+IHmccvrW2pBJvZmR+w0GL3NN-~iqYh)sANC<>#GAl^v4(WD*$Aj=Ha#45{#hVj@ zQNsr3hccW%qRVrnK*Ck!aKhP2P`MRdf8dhgTt1Hp)aR;8$wPy7zr%y$5)5Rd5*{x~F_SL3?@vmo;9kR~+gseqeKT8z;%)VhwyvIAO9h}1N`8BkykZfWegMQFFHJNxk8#A3dZC6uzecqhOWk0=6`y>7?E zb)%m44+7Aw)~{QPrzP1^5rZV2CO(3vjWRyb`XR1gH>-A>1RexKNK%i_77-OY*1rx7xc<1skBXTntSo$i#^Wx@OO>x6Hp9E6= zT$BEdI-$(959eCrV}_GS8C3czWu6i1i`Qxl+1~n!xw{g!%SK}dpfW>ZsGBI7ocu}v z<*(@IalOToV6)lB6E3-xq8-(vVL1a2JZ~*Y4o}ndO0kaVv9OeaNF2+*2gqR3S1C5a zf~m4=3B=k)v6TCTgdp2Y33y`>appV3Bb6GwKE~Z!Wbm>hPMqg&=jh6Xs8US+|42Eq zcH@leIHq*dst|E30+H16c5uXqD_n)x$p~yR+nq8tyBk)D7!z4{aYXgfDT7L1C0KDX zA{t2Q!KR}BLkLiK`{}qMMh+Wo=OoT&Qy}Sw^GD#1?ekdwo%M* zX{u7pn5f%MF?BVsN>L*`g_IdO7^+fClOd(A5_~i6bm`=X8-2ROMcXa~_5X;r2?cYb zqHSFC>Gm;$e{e{9S9YZ1B_2(7-9xdII%tJ>F}B+4{s%vmUO4~& diff --git a/XPSDK/Libraries/Win/XPWidgets_64.lib b/XPSDK/Libraries/Win/XPWidgets_64.lib index 32c3ae4991a082681f66f655479e97b574cb4932..3985ce1f67bb16b69fd832d20dde76682a6d5f8a 100644 GIT binary patch literal 10830 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 R`@hf0uF^yieYJlT^Zz&9C?Nm< literal 10564 zcmcgxOLH7W5>Crcv<8G9dRrR3h4IQr)`)e)hF7*^fv_ZZ$TFV8hUL+8TbkI>v|^^U zU?03UPWuBK#B$@raf1T~g5W@KCicL=#|>hS`~VKHUv+g=*Q2}TW+XZy)#}Ww`s$IH zm6bE}=W?U6bEExgL4T&NU7ITw-;r(oLb9vRdyS}lx zc>CVM`m(cecYU+uJgBKE_#p4`?X-Py6e@ORlnXupVi$xz+|X|!rL_uZGy}WQgy-}HX7y1-!j{$XvD2o zy`WL8XoC*h2!6>~Y?MFbQ?rQ&SK;t`T;s$vG!lCbl6Ds=>~ZU)k3N!}lr{ zDf$bwa)1Pemz*&sn*=cQl!2u z3CFV*>?rC|8^bXqp|(?QVB3w6Kv&~q+&ezjoy|sesIW@TdsWvngDpcAmdd*6sx)=BjyNM!GS~v}V&uat; zGmw&S26wzCTYkCW>XwfQ=z@~7;x|2=CuVC)N{&-2S0eLZ&Qp!2YD<(+-~MP1Fs@u= z0U?*)R46$&-N;QA%C*`S0+L)ITcYflTm=Ck_e@F@ZDoxueMJV}ZFuFtTi9;~{;uI2 z2_nQMuNgG_Cx)ud6}=ityuXN9a_+0&aSSuq&|CHY9_`Gn*gAABw3ezLdG1R2iN7Cv zn8t+8J+J0fg5}3+p67b5Tz8WXO&k&|vI_f&RZRiYZIri-sj9sE`OS>XZ{9+JQ#eQT z@B+~%7m=w95k2iA`mvvA>k@dqL|^p~UBUY^WI;cG_hN+Tr!JzOp|=OU%i~1PS-WAP zGvEb~ox=ZL4ieoMBbvv1Wq@c3?bk=q7BUxod<)($okU+i=R5G-Zld>r^#bqb==0$u zbSH?u$GaWxXCNeFRG^FW8ja8xjnXUBPG{%>out>PgHF+DI!nDYNIld=ee?%9LFcHG z&eJ6tpjWA%hN+u|=nWdD%k&ma(geLp$EfYl`#g?}B+1)SLvqqVmgpa5UTN)Z9RZH7$lnt{v>8DCL}xfl~og;+br2 zB{a#Yq;|^N2WiX^hkVj8k#rca&}yee2?tVg3|6?xj1wbxoW&rtsMgekIazT@4?p-) z!yrDj*oki|0{+%~Uz{qo7YRvJE*J`*uS4vgmPqkZOJ@42rJ#DOC6rcdNu>8$lGukeQL-ls z6(vO%EHe!@`NFpa-%j_0#7^ymB+1)jnUQNM0=^{)>n?rWS~)4PR!+IT2nZu0NVb`l z#Daw6M2!(rQHvCkYs8D}TmDre)j6n=GyRUJ@H}c)%Lh|#tw!xvMZqUhI;gke^lYU0 zsNMbeIQ{!CpWp2~hMWgE345koZ)<;hl%*))vxL9@jQ$s|dFr?|Rdvfjd2~kbkb2R7 zK>v#v$MK%0x4((><{~yS8KM)w6MBq4Pla#V@a{q;#GVdwniF)s<1_@Q#)J>6X!U)1 zZnauz_)Y(DP?%hQv#_$fb|;c+ue11KqhSQ>@V^fHJsJLILSZx&e|HbV?)&s#^y{x` zJ2W6R&NdRWpC<}Oz9Tr{JULpVGs|?)h@?(2<}f}INBOYck#EXxhV@r`9aY6Cul39n zi;DHMh1T;m#>dB-0V>&bX5?wyu+qN3iamlUNh>t2Ea3bGF|J9)V`;Bs4wNOKGu zWijWK5Y4#3Sj(9gaW2IduL7|>M9jJzS@8L-Ck3CyK2}3YE`S)zoF7#r1jag#0QIau z)h>0d&vY&Y^N+xMRbZxE7+Xh|DNw?UU(?XVW%Lj*Ga~Nm0+VlLe9^UF^ICK9^sxQ`p(g7&W=j(lUD1>DLvaD>aaQ$DqL_O}Q_ggjj}M1vM$xu)8_KZT5sqlqgImYUxWSD^m~pAug3BLsGw#G= k98WD{TY$NDG2>1=&hfMgxdoVih8d^I1V=Qg?>6TD0S!6a{Qv*} diff --git a/XPSDK/README.txt b/XPSDK/README.txt index 2316eb5..e7090b5 100644 --- a/XPSDK/README.txt +++ b/XPSDK/README.txt @@ -5,24 +5,12 @@ This download contains the files necessary to build plugins for X-Plane. The X-Plane plugin website is: -http://www.xsquawkbox.net/xpsdk/ +http://https://developer.x-plane.com/sdk/ The website contains full documentation on the SDK including tech notes, sample plugins, sample code, contact information, and links to the latest versions of this SDK. -The X-Plane SDK authors can be reached at: - -xplanesdk@xsquawkbox.net - -Please do not email Austin or Laminar Research for SDK questions or support; -the SDK is a third party effort. - -the X-Plane developer mailing list is an unlisted yahoo group frequented by -many X-Plane developers. - -x-plane-dev@yahoogroups.com - ------------------------------------------------------------------------------- SDK FILES ------------------------------------------------------------------------------- @@ -32,25 +20,62 @@ README.txt This document CHeaders Header files for compiling C/C++ plugins Delphi Interfaces for compiling Pascal plugins Libraries Import libraries for linking on Windows - and frameworks for linking on Mac. + and frameworks for linking on Mac. Note: there are no import/link-time libraries for Linux; on Linux, plugins simply leave SDK symbols undefined and they are discovered at runtime. The SDK website explains this process in more detail. -Mac CFM plugins are not supported by the SDK versions 2.0 and higher; the -2.0 SDK requires X-Plane 9.0 or newer, and X-Plane 9 will not run on -Mac OS 9. Therefore CFM plugins are not useful (and are probably -counterproductive since they cannot support x86 code). If you have a CFM -plugin, continue to use the 1.0 SDK to build it. You will have to port to -Mach-O if you want to use 2.0 features. - ------------------------------------------------------------------------------- RELEASE NOTES ------------------------------------------------------------------------------- This section contains per-release notes for the history of the X-Plane SDK. +X-PLane SDK Release 4.0.0 beta 1 9/18/2022 + +The 4.0.0 SDK adds support for ARM64 Macs. The 4.0 SDK is supported by X-Plane +12. The new SDK adds support for drawing hooks that draw directly to the G1000 +and other avionic cockpit devices. + +X-Plane SDK Release 3.0.2 4/29/2020 + +The SDK 3.0.2 adds the modern 3-d drawing callback for interoperability with +Metal and Vulkan, and deprecates most older drawing callbacks. + +X-Plane SDK Release 3.0.1 3/5/2018 + +The SDK 3.0.1 API adds new messages and APIs to support VR. + +X-Plane SDK Release 3.0.0 11/2/7/2017 + +The SDK 3.0 API supports new features and new packaging for plugins. The 3.0 +SDK requires X-Plane 11.0 or newer. New features include: + + - Display APIs to match X-Plane 11's UI. + - New map APIs. Legacy 2-d map draw callbacks are deprecated. + - Aircraft-plugins get their own menu + - Aircraft placement by lat-lon-elevation. + - Magnetic variation queries + - Chinese language support + - New instancing API + +The 3.0 SDK supports a new plugin packaging schema: + + //.xpl + +where ABI is one of mac_x64, win_x64 or lin_x64. The new schema is preferred, +so you can pack a version of your plugin that requires 3.0 with this scheme +and include a legacy 2.x plugin using hte old scheme for X-Plane 10 +compatibility. + +Please use the new scheme where possible - having a unique file name for each +DLL makes crash reports easier to read and triage. + +The 3.0 SDK drops support for 32-bit plugins; if you need to ship a 32-bit +plugin for 32-bit X-Plane 10, shipping using two schemes and two binaries may +be the best option. + X-Plane SDK Release 2.1.3 11/14/13 Fixed XPC Wrappers to use int and intptr_t instead of long. This fixes diff --git a/ixwebsocket/CMakeLists.txt b/ixwebsocket/CMakeLists.txt index f22ac80..8edfa05 100644 --- a/ixwebsocket/CMakeLists.txt +++ b/ixwebsocket/CMakeLists.txt @@ -43,9 +43,11 @@ if(APPLE) ) target_compile_options(ixwebsocket PRIVATE "SHELL:-arch x86_64" + "SHELL:-arch arm64" ) target_link_options(ixwebsocket PRIVATE "SHELL:-arch x86_64" + "SHELL:-arch arm64" ) target_link_libraries(ixwebsocket PRIVATE "-framework Foundation"