Table of Contents

How to Create a Source Control Plug-in DLL

Creating a Wwise source control plug-in DLL requires the following steps:

Note.gif
Note: A DLL can contain more than one plug-in. For more information, refer to Establishing Exported Functions.

Beginning a New Project

When you begin a new project, you must create the project and establish the exported functions to be used in the project.

You should also familiarize yourself with the source control interfaces you will be using in your project.

Creating the Project

To create a project using Visual Studio, do the following:

  1. Create an MFC DLL C++ Project. In the MFC DLL Wizard dialog, the DLL type must be set to Regular DLL using shared MFC DLL.
  2. In the new project, open the Project Properties dialog and follow these steps:
  • In the General Property page, set the Character Set property to Use Unicode Character Set.
  • In the C/C++/General Property page, add the path to the SDK includes directory in the Additional Include Directories property.

The project is now created and configured to use the Wwise Source Control SDK. The next thing to do is to create the functions that Wwise will use to manage your plug-in DLL.

Tip.gif
Tip: Strictly speaking, you do not have to create an MFC DLL project. However, this does facilitate certain string and dialog manipulations. If you choose not to use an MFC DLL, make sure to include the oleauto.h header in the stdafx.h file to be able to use the SysAllocString function.

Establishing Exported Functions

Each plug-in DLL must export three functions:

  • AkSourceControlGetPluginIDList(): Lets Wwise access the list of plug-ins contained in the DLL by getting the list of all plug-in IDs.
  • AkSourceControlGetPluginInfo(): Lets Wwise access the AK::Wwise::ISourceControl::PluginInfo class associated with a given plug-in.
  • AkSourceControlCreatePlugin(): Creates an instance of your AK::Wwise::ISourceControl object.

Prototypes of these exported functions can be found in the following type definitions:

Here is an example of the exported functions for a plug-in DLL containing two plug-ins:

#include "AK/Wwise/SourceControl/ISourceControl.h"
#include "SamplePlugin.h"

namespace
{
    // FirstSamplePlugin ID = {BD47DF98-1700-4542-A33F-E44705C25AF0}
    static const GUID s_guidFirstSamplePluginID = 
    { 0xbd47df98, 0x1700, 0x4542, { 0xa3, 0x3f, 0xe4, 0x47, 0x5, 0xc2, 0x5a, 0xf0 } };
    
    // SecondSamplePlugin ID = {57168691-2354-4166-82BF-DD07A36C16C6}
    static const GUID s_guidSecondSamplePluginID = 
    { 0x57168691, 0x2354, 0x4166, { 0x82, 0xbf, 0xdd, 0x7, 0xa3, 0x6c, 0x16, 0xc6 } };
}

void __stdcall AkSourceControlGetPluginIDList ( AK::Wwise::ISourceControl::PluginIDList& out_rPluginIDList )
{
    out_rPluginIDList.AddTail( s_guidFirstSamplePluginID ); 
    out_rPluginIDList.AddTail( s_guidSecondSamplePluginID );

}

void __stdcall AkSourceControlGetPluginInfo ( const GUID& in_rguidPluginID, 
    AK::Wwise::ISourceControl::PluginInfo& out_rPluginInfo )
{
    if ( in_rguidPluginID == s_guidFirstSamplePluginID )
    {
        FirstSamplePlugin::GetPluginInfo( out_rPluginInfo );
    }
    else if ( in_rguidPluginID == s_guidSecondSamplePluginID )
    {
        SecondSamplePlugin::GetPluginInfo( out_rPluginInfo );
    }

}

AK::Wwise::ISourceControl* __stdcall AkSourceControlCreatePlugin ( const GUID& in_rguidPluginID )
{
    AK::Wwise::ISourceControl* pSourceControl = NULL;

    if ( in_rguidPluginID == s_guidFirstSamplePluginID )
    {
        pSourceControl =  new FirstSamplePlugin();
    }
    else if ( in_rguidPluginID == s_guidSecondSamplePluginID )
    {
        pSourceControl =  new SecondSamplePlugin();
    }

    return pSourceControl;
}
Warning.gif
Warning: You must change the plug-in GUID value to avoid ID conflicts with other plug-ins.

When you create a project with Visual Studio, you need to export these functions by adding the function names to the .def file of the project. If no module definition file exists, you must create one.

To create a module definition file, follow these steps:

  1. Click on the Add New Item button in the tool bar.
  2. In the template list, select the Module-Definition File (.def) template.

A typical module definition file looks like this:

LIBRARY      "SamplePlugin"

EXPORTS
    AkSourceControlGetPluginIDList
    AkSourceControlGetPluginInfo
    AkSourceControlCreatePlugin

Introducing Source Control Interfaces

Each Wwise source control plug-in must contain certain interfaces so that it may be integrated properly. These are summarized below, and described in detail later in this documentation.

AK::Wwise::ISourceControl

Your plug-in must implement this interface to perform source control operations.

For more information about this interface, refer to Building the Source Control Plug-in Interface.

AK::Wwise::ISourceControlUtilities

This interface is implemented by Wwise and is given to the plug-in at its creation. It exposes some useful utility functions to the plug-in.

For more information about this interface, refer to Using the Source Control Utilities Interface.

AK::Wwise::ISourceControlOperationProgress

This interface is implemented by Wwise and is given to the plug-in via the ISourceControlUtilities class. It exposes functions to manage a simple progress dialog.

For more information about this interface, refer to Implementing the Source Control Operation Progress Interface.

AK::Wwise::ISourceControlDialogBase

This is the interface that the plug-in must implement to create dialogs that have the Wwise UI look and feel.

For more information about this interface, refer to Defining the Source Control Plug-in Dialog.

Building the Source Control Plug-in Interface

When you implement the methods of AK::Wwise::ISourceControl, you define the behavior of your plug-in in response to various situations in Wwise. The methods allow the plug-in to react to the following situations:

  • The plug-in instance is initialized or terminated
  • The plug-in instance is destroyed
  • The Wwise user clicks the "Config…" button in the Project Settings dialog
  • Wwise refreshes the icons of the Project Explorer
  • The file lists of the File Manager's Work Units or Sources tab are refreshed
  • A contextual menu that contains source control operations is displayed
  • The Wwise user selects an operation from the contextual menu in the File Manager or in the Project Explorer
  • The files are updated
  • The Wwise user imports audio files, creates a new work unit, or saves the project.

Some of these situations are covered in the following sections, but you can refer directly to the AK::Wwise::ISourceControl reference for a complete description of the interface and the functions you need to implement.

Tip.gif
Tip: Many methods in this interface have the AK::Wwise::ISourceControl::OperationResult enumeration as return type. It is important to note that the OperationResult_Failed result must be used only when the operation fails globally; that is, when you don't want Wwise to consider data that is returned by the plug-in. Such failures include the following:
  • The connection has failed.
  • An internal plug-in error has occurred.

Sample Code

You must create a class derived from AK::Wwise::ISourceControl to implement all methods of this interface. This class manages everything related to UI and source control operations for your plug-in. The context in which these methods are called is indicated in the comments.

#include <AK/Wwise/ISourceControl.h>

class SamplePlugin
    : public AK::Wwise::ISourceControl
{
public:
    SamplePlugin();
    virtual ~SamplePlugin();

    // ISourceControl implementation
    virtual void Init(AK::Wwise::ISourceControlUtilities* in_pUtilities ); // Initializing and Terminating the 
        // Plug-in Instance
    virtual void Term(); // Initializing and Terminating the Plug-in Instance
    virtual void Destroy(); // Destroying the Plug-in Instance

    virtual bool ShowConfigDlg(); // Plug-in configuration
    virtual void GetOperationList( OperationMenuType in_menuType, const StringList& in_rFilenameList, 
        OperationList& out_rOperationList ); // Contextual Menu
    virtual DWORD GetOperationEffect(
                DWORD in_dwOperationID ); // Wwise needs to know the effect of an operation
    virtual LPCWSTR GetOperationName(
        DWORD in_dwOperationID ); // Get operation name
    virtual AK::Wwise::ISourceControlUtilities::OperationResult GetFileStatus( 
        const StringList& in_rFilenameList, 
        FilenameToStatusMap& out_rFileStatusMap ); // File Manager Dialog
    virtual AK::Wwise::ISourceControlUtilities::OperationResult GetFileStatusIcons( 
        const StringList& in_rFilenameList, 
        FilenameToIconMap& out_rFileIconsMap ); // Project Explorer Icons Refresh
    virtual AK::Wwise::ISourceControlUtilities::OperationResult GetMissingFilesInDirectories( 
        const StringList& in_rDirectoryList, StringList& out_rFilenameList ); // File Manager Dialog
    virtual void DoOperation( DWORD in_dwOperationID, const StringList& in_rFilenameList ); // Execution of a 
        // Source Control Operation
    virtual AK::Wwise::ISourceControlUtilities::OperationResult PreCreateOrModify( 
        const StringList& in_rFilenameList, 
        bool& out_rContinue ); // Creation or Modification of Files in Wwise
    virtual AK::Wwise::ISourceControlUtilities::OperationResult PostCreateOrModify( 
        const StringList& in_rFilenameList, 
        bool& out_rContinue ); // Creation or Modification of Files in Wwise
    
// A static method to get the plug-in information class, refer to Source Control Plug-in Information Class 
// for more information about this method.
    static void GetPluginInfo( PluginInfo& out_rPluginInfo );

private:

    // Members
    AK::Wwise::ISourceControlUtilities* m_pSourceControlUtilities;
};
Caution.gif
Caution: The string parameters and results exchanged between Wwise and the source control plug-in must be in unicode.

Establishing the Source Control Plug-in Information Class

When Wwise requires information about your plug-in, it calls the AkSourceControlGetPluginInfo function exported from your DLL. (For more information, refer to Establishing Exported Functions. ) The AK::Wwise::ISourceControl::PluginInfo class is composed of the following data:

  • The name of the plug-in displayed to the user
  • The version of the plug-in
  • A Boolean value that notifies Wwise that source control icons for work unit nodes can be displayed in the Project Explorer
  • A Boolean value that informs Wwise that it is possible to configure the plug-in
  • A Boolean value that informs Wwise that the Update All operation is available
  • The name of the Update All operation to be displayed to the user
Tip.gif

Tip: A simple way to obtain the plug-in information is to make the AkSourceControlGetPluginInfo (Establishing Exported Functions) call a static method created inside your implementation of the AK::Wwise::ISourceControl interface.

A simple implementation of this static method is:

void SamplePlugin::GetPluginInfo( PluginInfo& out_rPluginInfo )
{
    // Plug-in name and version
    out_rPluginInfo.m_bstrName = ::SysAllocString( L"Sample Source Control Plug-in" );
    out_rPluginInfo.m_uiVersion = 1;

    // Function availability
    out_rPluginInfo.m_bShowConfigDlgAvailable = false;
    out_rPluginInfo.m_dwUpdateCommandID = AK::Wwise::SourceControlConstant::s_dwInvalidOperationID;// Replace with your ID
    out_rPluginInfo.m_dwCommitCommandID = AK::Wwise::SourceControlConstant::s_dwInvalidOperationID;// Replace with your ID
    out_rPluginInfo.m_bStatusIconAvailable = false;
}
Warning.gif
Warning: The plug-in name and the Update All operation name must be allocated using the SysAllocString function, because Wwise is responsible for deleting this memory.

Initializing and Terminating the Plug-in Instance

When the plug-in instance is created, Wwise calls the AK::Wwise::ISourceControl::Init( ISourceControlUtilities* in_pUtilities ) method. The parameter of this function is a pointer to Wwise's implementation of the AK::Wwise::ISourceControlUtilities interface. You might want to copy this pointer to a member of your plug-in class to be able to create dialogs, show a progress dialog, display message boxes, or load and save plug-in configuration. For more information on this topic, refer to Using the Source Control Utilities Interface.

A typical implementation of AK::Wwise::ISourceControl::Init() is:

void SamplePlugin::Init( ISourceControlUtilities* in_pUtilities )
{
    m_pSourceControlUtilities = in_pUtilities;

    // Load the plug-in configuration from the registry
}

Just before the plug-in instance is destroyed, Wwise calls the AK::Wwise::ISourceControl::Term() method.

A typical implementation of AK::Wwise::ISourceControl::Term() is:

void SamplePlugin::Term()
{
    // Save the plug-in configuration to the registry
    m_pSourceControlUtilities = NULL;
}

For more information about loading/saving plug-in configuration to the registry, refer to Source Control Plug-in Sample Code.

For more information about when these functions are called, refer to Destroying the Plug-in Instance.

Destroying the Plug-in Instance

When Wwise needs to create an instance of your source control plug-in, it calls the AkSourceControlCreatePlugin() function in your DLL (Establishing Exported Functions) to create the new instance. This function returns an interface to your source control plug-in. When the plug-in instance is no longer needed, Wwise calls the AK::Wwise::ISourceControl::Destroy() method on that particular instance. This method releases any memory or other resources the object consumes, and then deletes the object itself.

If the instance was created with the operator New, a typical implementation of AK::Wwise::ISourceControl::Destroy() would be:

void SamplePlugin::Destroy()
{
    delete this;
}

An instance of the plug-in is created in the following situations:

  • The Wwise user selects it from the source control plug-in list in the Project Settings dialog and accepts the changes
  • The Wwise user loads a project in which she had already used the source control plug-in.

The instance of the plug-in is destroyed in the following situations:

  • The Wwise user selects another source control plug-in from the Project Settings dialog and accepts the changes;
  • The project is closed.

Using the Source Control Utilities Interface

This interface is given to the plug-in when the plug-in instance is initialized (see Initializing and Terminating the Plug-in Instance). Its functions help the plug-in create dialogs, display message boxes, show a progress dialog, and load and save the configuration, all with the Wwise UI look and feel.

This interface exposes the following methods:

Displaying Progress Dialogs

When performing source control operations, it can be useful to display a progress dialog with progress feedback messages. This can be done by calling the AK::Wwise::ISourceControlUtilities::GetProgressDialog() method. This method returns an AK::Wwise::ISourceControlOperationProgress interface. For more information on this interface, refer to Implementing the Source Control Operation Progress Interface.

Displaying Message Dialogs

A simple way to display message boxes with the Wwise UI look and feel is to call the AK::Wwise::ISourceControlUtilities::MessageBox() method. Use it the same way as a standard MessageBox Windows function call. You should use this method rather than the standard MessageBox calls to give your plug-in the Wwise UI look and feel.

Displaying Dialogs

To create dialogs that have the Wwise UI look and feel, you have to call the AK::Wwise::ISourceControlUtilities::CreateModalCustomDialog( ISourceControlDialogBase* in_pDialog ) method. This method works in the same way as the CDialog::DoModal() method except that it accepts an AK::Wwise::ISourceControlDialogBase interface as input. For more information on this, refer to Defining the Source Control Plug-in Dialog.

Displaying Progress Dialogs

AK::Wwise::ISourceControlUtilities offers a simple way to save or load the plug-in configuration in the registry. By calling the AK::Wwise::ISourceControlUtilities::GetRegistryPath() method, you obtain the path of a registry folder that is different for each project and each plug-in. To load or save the configuration, you should create a subfolder for the current version of the plug-in and create all plug-in keys there. You might want to load the configuration in the AK::Wwise::ISourceControl::Init() method and save the configuration in the AK::Wwise::ISourceControl::Term() method.

Warning.gif
Warning: You must use the HKEY_CURRENT_USER registry key to access this path. The project registry folder is created using this key and the source control plug-in configuration must be user-independent.

Implementing the Source Control Operation Progress Interface

The AK::Wwise::ISourceControlOperationProgress interface's implementation can be accessed via the AK::Wwise::ISourceControlUtilities interface given to the plug-in upon initialization. The former interface exposes these methods:

Creating the Progress Dialog

To create and display the progress dialog, use the AK::Wwise::ISourceControlOperationProgress::ShowProgress() non-blocking method. To add a message to the log message list, use the AK::Wwise::ISourceControlOperationProgress::AddLogMessage() method.

Warning.gif
Warning: The progress dialog doesn't consider escape characters (such as '\n' or '\t'). The text must be added line by line and tabulation must be replaced with blank spaces.

Enabling the OK Button

To enable the OK button, call the AK::Wwise::ISourceControlOperationProgress::OperationCompleted() method. The method will not return until the user presses the OK button. When the user does so, the dialog is closed and destroyed.

Enabling the Cancel Button

To know if the user has pressed the Cancel button, call the AK::Wwise::ISourceControlOperationProgress::IsCanceled() method. You can also cancel the operation by calling the AK::Wwise::ISourceControlOperationProgress::Cancel() method.

Note.gif
Note: Even if you programmatically cancel the dialog by calling the AK::Wwise::ISourceControlOperationProgress::Cancel() method, you still have to call AK::Wwise::ISourceControlOperationProgress::OperationCompleted() to close and destroy the dialog.

Implementing Source Control Actions

To integrate your source control plug-in into Wwise users' workflows, you must implement certain functionality as follows.

Enabling Plug-in Configuration

In the Project Settings dialog, the Wwise user can configure the plug-in by clicking the Config… button. This button is enabled only if the AK::Wwise::ISourceControl::PluginInfo::m_bShowConfigDlgAvailable has been set to True. When you click on this button, Wwise calls the AK::Wwise::ISourceControl::ShowConfigDlg() method. The return value of this function is a Boolean value. The meaning of the value is as follows:

  • True indicates that you accepted the configuration changes, so the Project Explorer icons will be refreshed.
  • False indicates that you rejected the configuration changes, so the Project Explorer icons will not be refreshed.

A typical implementation of this method is:

bool SamplePlugin::ShowConfigDlg()
{
    DlgConfiguration configurationDialog();

    // return True if the user presses 'OK'
    return m_pSourceControlUtilities->CreateModalCustomDialog( &configurationDialog ) == IDOK;
}

In this code sample, the DlgConfiguration class is an implementation of the AK::Wwise::ISourceControlDialogBase interface. For more information, refer to the Defining the Source Control Plug-in Dialog.

Enabling the File Manager Dialog

When the File Manager is refreshed, two methods are called:

When the file list is populated, Wwise searches for files that are on the disk. On some source control systems, however, files are removed from the disk when they are deleted. Despite this, these files must still be identified to confirm the delete operation on the server. To retrieve the list of files that are in this state, Wwise calls the AK::Wwise::ISourceControl::GetMissingFilesInDirectories() method. The first parameter is the list of directories in which Wwise will look for such missing files, while the second parameter is a list of strings that will be overwritten with the names of the missing files.

Warning.gif
Warning: The plug-in must not include files located in subdirectories of the given directories.

After Wwise has obtained the complete file list, the Status and Owner(s) columns must be refreshed. To do this, Wwise calls the AK::Wwise::ISourceControl::GetFileStatus() method. For each file, the plug-in needs to display the corresponding status and owner of the file. Wwise obtains the status of the files listed in the function's first parameter. The second parameter is the resulting map containing the text to be displayed in the Status and Owner(s) columns.

Warning.gif
Warning: The memory of the string members of AK::Wwise::ISourceControl::FilenameToStatusMapItem must be allocated using the SysAllocString function because Wwise is responsible for deleting this memory. Two strings must not share the same memory space because Wwise will try to destroy these two strings separately.

Exposing your Plug-in in Contextual Menus

When Wwise displays a contextual menu that includes source control operations, it needs the list of all operations that are available in a specific context. To get this list, Wwise calls the AK::Wwise::ISourceControl::GetOperationList( OperationMenuType in_menuType, const StringList& in_rFilenameList, OperationList& out_rOperationList ) method. The first parameter is the context in which the operation list will be displayed. Depending on this context, some plug-ins could restrict the user to specific operations. The second parameter is the list of file names that the user has selected. This can be used to enable or disable some operations depending on the status of the files. The third parameter is the list of operations available in the current context. This list of operations must be filled by the plug-in. The information about the operations contained in this list is used to fill the contextual menu and to call back the plug-in with the ID of the operation. There are no restrictions on either IDs.

Wwise calls the virtual LPCWSTR GetOperationName( DWORD in_dwOperationID ) method to obtain the operation name for displaying in menus and dialogs.

Warning.gif
Warning: Wwise will not delete the memory occupied by the operation name's string. We therefore recommend you create static strings that are created and destroyed at the same time as the plug-in instance.

Exposing Source Control Operations in Contextual Menus

When Wwise users choose an operation from a contextual menu, Wwise first calls the AK::Wwise::ISourceControl::GetOperationEffect( DWORD in_dwOperationID ) method. The parameter is the operation ID corresponding to the operation. The implementation of this method returns a mask made of one or many values of the AK::Wwise::ISourceControl::OperationEffect enumeration. Wwise uses the return value to learn if it must ask users to save their projects before continuing with the source control operation. Operations such as update, rename, revert, and delete modify the contents of the local files. Operations such as commit and check-in modify the contents of the file on the server.

Warning.gif
Warning: Not returning information about the effect of an operation on a file may lead to frustration for Wwise users. When a file changes on the hard drive during a source control operation, Wwise detects the change and asks the user to reload the project. If users had pending changes (that is, the project is dirty) and are asked to reload, their changes are lost. If users revert the changes to a file that is dirty, choose not to reload the project, and then save the changes, they may overwrite the newly-updated file. AK::Wwise::ISourceControl::GetOperationEffect uses the information returned to avoid such situations by forcing users to save.

After successfully calling the first method, Wwise calls the AK::Wwise::ISourceControl::DoOperation( DWORD in_dwOperationID, const StringList& in_rFilenameList ) method. The first parameter is the operation ID corresponding to the operation. The second parameter is the list of selected files. The implementation of this method uses the AK::Wwise::ISourceControlOperationProgress interface to display a progress dialog. For more information, refer to Implementing the Source Control Operation Progress Interface.

Allowing Wwise to Refresh Project Explorer Icons

Wwise needs to refresh icons in the following situations:

  • The source control plug-in is loaded
  • The user accepts the plug-in configuration
  • The user refreshes the icons manually by clicking on the "Refresh" or "Refresh All" Project Explorer contextual menu item
  • The File Manager dialog is closed.

Using a pattern similar to that of the AK::Wwise::ISourceControl::GetFileStatus() method, AK::Wwise::ISourceControl::GetFileStatusIcons( const StringList& in_rFilenameList, FilenameToIconMap& out_rFileIconsMap ) must return a map containing icons and tool tip texts for files in the list. The first parameter is the list of names of the file for which Wwise needs to have icon maps. The second parameter is the resulting map containing the following components:

  • The icon to be displayed as an overlay on the work unit's original icon
  • The tool tip text to be displayed when you move the mouse over the given icon.
Warning.gif
Warning: The memory of the string members of AK::Wwise::ISourceControl::FilenameToIconMapItem must be allocated using the SysAllocString function because Wwise is responsible for deleting this memory. Two strings must not share the same memory space because Wwise will try to destroy these two strings separately.

The icons contained in the map can be any size, but they will be resized to a format of 15x15 pixels. Functions related to icons are only called if AK::Wwise::ISourceControl::PluginInfo::m_bStatusIconAvailable is set to True.

Tip.gif
Tip: A set of icons you can use is installed with this SDK.

Allowing for the Creation and Modification of Files in Wwise

File creation and modification happens when a Wwise user does the following:

  • Creates a new work unit
  • Imports audio sources
  • Saves the project
  • Edits the audio source in an external editor.

When any of these situations arises, Wwise calls the AK::Wwise::ISourceControl::PreCreateOrModify( const StringList& in_rFilenameList, CreateOrModifyOperation in_eOperation, bool& out_rContinue ) and AK::Wwise::ISourceControl::PostCreateOrModify( const StringList& in_rFilenameList, CreateOrModifyOperation in_eOperation, bool& out_rContinue ) methods. The first parameter is the list of names of the files that are to be created or modified. The second parameter is a flag defining the operation that will be performed. Since you can perform either operation on any of the files listed, you must use the bitwise AND operator to compare the second parameter with a predefined flag. For example, to know if some files were created, do the following:

if ( in_eOperation & CreateOrModifyOperation_Create )
{
    // Do operations
}

The third parameter of the AK::Wwise::ISourceControl::PreCreateOrModify() and AK::Wwise::ISourceControl::PostCreateOrModify() functions is set by the plug-in to inform Wwise to continue or stop the current operation. This parameter is mostly used by calls to the AK::Wwise::ISourceControl::PreCreateOrModify() method.

Tip.gif
Tip: We recommend that these two methods be used to perform operations that are specific to your source control system. For example, you could use the AK::Wwise::ISourceControl::PreCreateOrModify() method to perform Perforce's checkout operation, or the AK::Wwise::ISourceControl::PostCreateOrModify() method to add files which are not on the server yet. The first method is always called before file creation or modification, and the second one is always called after such an operation. This feature can be used to implement a layer of security in your plug-in.

Defining the Source Control Plug-in Dialog

If your DLL contains dialogs, you'll want them to have the Wwise UI look and feel. To do that, you need to follow the following steps:

Creating the Dialog Resource

You can create both standard Windows controls and controls specific to Wwise.

Regular Controls

You can add regular controls such as static controls, edit controls, check boxes, push buttons, radio buttons, and group controls directly in the Microsoft Development Environment Dialog Editor using the corresponding tools in the Dialog Editor section of the Toolbox. These controls will be automatically subclassed by Wwise so they have the same look as similar controls elsewhere in the application.

Note.gif
Note: The dropdown/combobox control is not automatically subclassed. If you need a dropdown control in your dialog, use the Combo custom control instead. Refer to Wwise Controls for more information.

Wwise Controls

To integrate Wwise dialog controls (such as Captions and ComboBox) into your dialog, use static text control placeholders with a specially-coded caption text. This text needs to have the following form:

Class=[Classname];

where Classname can be one of the following:

  • Caption: Read-only text display
    The static control in your resources should be exactly 13 units high, and wide enough to accommodate the longest text it might contain. To change the text of the caption, you need to use the following standard Windows functions:
    • SetWindowText
    • GetWindowText
  • Combo: Dropdown list
    The static control in your resources should be exactly 13 units high, and wide enough to hold the longest text it might contain. To populate the combo box or either set or get its current selection, you must use the following standard Windows message macros:
    • ComboBox_InsertString
    • ComboBox_GetCurSel
    • ComboBox_SetCurSel
Tip.gif
Tip: To make it easier to view the layout of the dialog controls, set Border to True in the properties of the static placeholders in the Microsoft Development Environment Dialog Editor.

Enabling the Dialog

Before Wwise can display your dialog, you must implement the AK::Wwise::ISourceControlDialogBase interface. This interface exposes the following methods:

Wwise needs to know in which context the resources can be found. Before creating the dialog, Wwise calls the AK::Wwise::ISourceControlDialogBase::GetResourceHandle() method. A typical implementation for this method is:

HINSTANCE DlgSimple::GetResourceHandle() const
{
    AFX_MANAGE_STATE( ::AfxGetStaticModuleState() );
    return ::AfxGetResourceHandle();
}

Wwise also needs the ID of the dialog in the resource to create the dialog. To retrieve it, Wwise calls the AK::Wwise::ISourceControlDialogBase::GetDialog() method. A typical implementation of this method is:

void DlgSimple::GetDialog( UINT & out_uiDialogID ) const
{
    out_uiDialogID = IDD_SIMPLEDIALOGID;
}

To know if the "?" should be shown on the dialog title bar, Wwise calls AK::Wwise::ISourceControlDialogBase::HasHelp(). The plug-in must return True if there is a Help section associated with the dialog. If so, the "?" icon appears.

bool DlgSimple::HasHelp() const
{
    return true;
}

When the Wwise user clicks the "?" button of the dialog, Wwise calls the AK::Wwise::ISourceControlDialogBase::Help() method. The plug-in must return True when it manages the Help request and false when nothing is done. An implementation example of this method is:

bool DlgSimple::Help( HWND in_hWnd ) const
{
    AFX_MANAGE_STATE( ::AfxGetStaticModuleState() ) ;

    // Note: Do NOT call AfxGetApp()->HtmlHelp() as it will launch the Help
    // window from the wrong parent window which will make floating views
    // behave unexpectedly.
    ::HtmlHelp( NULL, AfxGetApp()->m_pszHelpFilePath, HH_HELP_CONTEXT, ONLINEHELP::Simple_Dialog );

    return true;
}
Caution.gif
Caution: The Help() method should NOT call AfxGetApp()->HtmlHelp(). It will launch the Help window from the wrong parent window which will make floating views behave unexpectedly. Instead, use HtmlHelp() with a NULL window handle, as shown in the example above.

The dialog cannot use the MFC methods to manage Windows messages. Instead, each time the dialog receives a Windows message, the AK::Wwise::ISourceControlDialogBase::WindowProc() is called. An implementation example of this method is:

bool DlgConfiguration::WindowProc( HWND in_hWnd, UINT in_message, WPARAM in_wParam, LPARAM in_lParam, 
    LRESULT & out_lResult )
{

    if ( in_message == WM_INITDIALOG )
    {
        // Initialize the dialog
    }

    // For example: Catch window command actions (only for the main dialog) to enable/disable controls
    else if ( in_message == WM_COMMAND )
    {
        // Notification code
        switch ( HIWORD( in_wParam ) )
        {
        case BN_CLICKED:
            // Check which button was clicked
            switch ( LOWORD( in_wParam ) )
            {
            case IDOK:
                // The user pressed the 'Ok' button
                break;
            }           
        } // End switch hi word (notification code)

    } // End command window event

    // Return False to let the parent window deal with the message. Return True
    // for messages you don't want the parent window to handle.

    return false;
}

The meaning of this method's return value is as follows:

  • False indicates that the message will be propagated to the object's parent class. This is the value that is generally returned
  • True indicates that the message will not be propagated to the object's parent class. Return this value when you do not want the parent to react to the message. For example, when receiving the IDOK button message, the parent generally closes the dialog. In certain circumstances, you might want to let the dialog open if some information has not been completed properly.

To manually close the dialog, you need to use the Windows PostMessage() function. A typical call to this function looks like this:

PostMessage( in_hWnd, WM_CLOSE, 0, 0 );

Displaying the Dialog

To display the dialog, an instance of the corresponding AK::Wwise::ISourceControlDialogBase implementation must be created. Using the AK::Wwise::ISourceControlUtilities::CreateModalCustomDialog() method, the dialog will be displayed like a modal dialog. Here is an example that shows how to create and display the dialog:

bool SamplePlugin::ShowConfigDlg()
{
    DlgConfiguration configurationDialog( m_pSourceControlUtilities );

    // return true if the user presses 'OK'
    return m_pSourceControlUtilities->CreateModalCustomDialog( &configurationDialog ) == IDOK;
}