GameBryo Asset Service provides an easy way to access game data. For all the assets( Entity models, logic scripts,images etc), the asset service assigns a unique name to each of them. The unique id is called Uniform Resource Identifier (URI) that is prefixed by the string “urn:”, followed by one or more specifiers.
Examples:
- urn:gamebryo-scenegraph:Precache—All assets that are tagged with both “gamebryo-scenegraph” and “Precache”, which might be used to identify every asset that should be pre-loaded during application startup.
- urn:emergent-world:Level1—An asset that is tagged with “emergent-world” and has the name of “Level1″, which might be used to load all the entities needed in the first level of a game.
- urn:llid:0716a14d-81ca-46f2-9e7e-7dc30ff2c561:Wii—A logical asset with the indicated unique ID and also tagged “Wii”, which might be used to load the Wii variation of an asset selected with an asset-picker in a tool.
Assets in Hello World Demo:
In the hello world example, the HelloWorldService::SetupInputActions() function uses “urn:gamebryo-actionmap:HelloWorldActionMap” to load a key-action map. It maps the “m” key to HELLOWROLD_ACTION_DROP event and “n” key to HELLOWORLD_ACTION_PICKUP event. The actionmap file is located in \Gamebryo\Media\Samples\GameFramework\HelloWorld\HelloWroldActionMap.actionmap.
Also, in ConfigCommon.ini file, the initial world is specified by
[Game]
InitialWorld = urn:emergent-world:HelloWorld
The question is how does gamebryo map URN to file. This question is very important because you must understand the asset service in order to use assets.
Let’s take a close look on HelloWrold cpp project.
In Config.ini file, we have an attribute
[AssetWeb.Win32]
Path=$(SourceBaseDir)/../../../Media
This attribute specifies the root directory for Asset directory. The config manager service will load this attribute in run time. On my computer, the AssetWeb root folder is F:\Gamebryo\Media. There are three files in Media/asset-web-config directory which define the asset web.
The LogicalIdTagger.ini defines some logical tags:
; The Assets are a list of asset types (assigned by the MimeTagger) that should have logical
; asset id’s assigned to them. If the asset does not possess one of these tags, then no logical
; asset id is created for it. Logical asset id’s are only needed for assets that will be referenced
; by other asset files, like block or model files.
[LogicalIdTagger.Assets]
=gamebryo-scenegraph
=gamebryo-animation
=gamebryo-terrain
=gamebryo-terrain-materialpkg
=physx-terrain
=gamebryo-actionmap
=wwise-sound-bank
=bmp-image
In MimeTagger.ini, for each file extension, a pair of tags is created from the associated MIME type. For example, “py=script/python-behavior” will result in every file
with the “.py” extension having two tag values – “script” and “python- behavior”.
xblock=x-world/emergent-world
kf=application/gamebryo-sequence-file
actionmap=application/gamebryo-actionmap
bnk=audio/wwise-sound-bank
Therefore, HelloWorldActionMap.actionmap file is named as “urn:gamebryo-actionmap:HelloWorldActionMap” and the HelloWrold.xblock is named as “urn:emergent-world:HelloWorld”. The path of those files are irrlevent to urn. The asset service searches all the sub directories under AssetWeb root and classifies files accordingly.
Key Actionmap
The Hello World example demonstrates two ways of handling key event.
1. Register a key handler function and switch the logic according to key code.
EE_HANDLER(HelloWorldService, HandleKeyDownMessage, KeyDownMessage); // Register handler
void HelloWorldService::HandleKeyUpMessage(const KeyUpMessage *pMessage,
efd::Category targetChannel)
{
Entity* pAvatar = GetAvatar();
if (pAvatar)
{
switch (pMessage->GetKey()) // Switch key code
{
case NiInputKeyboard::KEY_UP:
pAvatar->SetPropertyValue("IsMoving", false);
break;
case NiInputKeyboard::KEY_LEFT:
pAvatar->SetPropertyValue("IsTurningLeft", false);
break;
...
2. Use a data-driven actionmap to bind keys to events. Currently, there’s no tool to help you generate actionmap file; therefore, you need to edit the file by hand. Please read the The ecrInput Library documentation for detail.
HelloWorldActionMap.actionmap
...
<Event EventName="HELLOWORLD_ACTION_DROP" EventCategory="0xC000000007765433" EventFlags="RETURN_MAGNITUDE">
<ActionsList>
<!--Flags - InputService.h ActionFlags enum - use individual string values or combined bitmask as an int-->
<!--DeviceID - a way to define action for specific controllers-->
<!--Modifiers - NiInputKeyboard Modifiers enum-->
<!--ActionClsID - (ACTION/DPAD/STICK)-->
<!--Semantic - NiAction.h Semantic enum for gpad string values GP_BUTTON_LUP or NiInputKeyboard.h for key value strings KEY_M, etc-->
<Action Flags="ON_ACTIVATE" DeviceID="0" Modifiers="0" ActionClsID="ACTION" Semantic="KEY_M"MinRange="-1.000000" MaxRange="1.000000" />
<Action Flags="ON_ACTIVATE" DeviceID="0" Modifiers="0" ActionClsID="ACTION" Semantic="GP_BUTTON_RDOWN" MinRange="-1.000000" MaxRange="1.000000" />
</ActionsList>
</Event>
<!--0xC000000007765432-->
<!--13835058055407359026-->
<Event EventName="HELLOWORLD_ACTION_PICKUP" EventCategory="0xC000000007765432" EventFlags="RETURN_MAGNITUDE">
<ActionsList>
<Action Flags="ON_ACTIVATE" DeviceID="0" Modifiers="0" ActionClsID="ACTION" Semantic="KEY_N" MinRange="-1.000000" MaxRange="1.000000" />
<Action Flags="ON_ACTIVATE" DeviceID="0" Modifiers="0" ActionClsID="ACTION" Semantic="GP_BUTTON_RRIGHT" MinRange="-1.000000" MaxRange="1.000000" />
After you create the actionmap, you can create an action message handler.
// Define the message categories for the actions
static const efd::Category kCAT_STANDALONE_ACTION_PICKUP =
Category( efd::UniversalID::ECU_Any, 0, 0x07765432 );
static const efd::Category kCAT_STANDALONE_ACTION_DROP =
Category( efd::UniversalID::ECU_Any, 0, 0x07765433 );
...
void HelloWorldService::HandleActionMessage(const InputActionMessage* pMsg,
efd::Category targetChannel)
{
Entity* pAvatar = GetAvatar();
switch(pMsg->GetClassID())
{
case efd::kMSGID_CoreInputAction:
if (pAvatar)
{
if(targetChannel == kCAT_STANDALONE_ACTION_PICKUP)
{
pAvatar->SendEvent(pAvatar->GetEntityID(), "Jack", "PickupEntity");
}
else if(targetChannel == kCAT_STANDALONE_ACTION_DROP)
{
pAvatar->SendEvent(pAvatar->GetEntityID(), "Jack", "DropEntity");
}
}
break;
}
}
Reference:
Gamebryo Documentation: Programmer Level->Foundation->Asset Runtime Service
Gamebryo Documentation: The ecrInput Library
HelloWorld example project