Game DLL - Create component, add lua and ui, activate?

So im trying to figure out the new component system stuff and am wondering how i can create a component in c++, add the lua and ui components to it and activate it for usage.

I currently can load canvases directly using gEnv->pLyShine->LoadCanvas(canvaspath), but would like to move towards the component system to where i can create components for what i would need.

I did figure out how to load scripts using the gEnv->pScriptSystem and, like above, would like to move towards the component system.

Any help would be appreciated.

yea, i’ve looked through those documents.

all they say is how to create a NEW component, not create an EXISTING component.

what i’m looking for is something like:

AZ::Component component = gEnv->AZWhaterver->CreateComponent("basic component").
component->addComponent("LuaComponent");
component->addComponent("UIComponent");

I think i came across something like this with LYShine.

Hi @alatnet,

The docs on creating a component in C++ are here:

http://docs.aws.amazon.com/lumberyard/latest/developerguide/component-entity-system-pg-intro.html

You mention using the component system with the UI system and Lua. In v1.9 you can add Lua Script components directly to UI elements in the UI editor which gives you a lot of power (especially when combined with slices in the UI system). So for example you can create a Button element and have it load another UI canvas with a few lines of Lua.

If you want to load a UI canvas when a level loads you can do that using the UiAssetRefComponent on an entity in the world.

Feel free to follow up with more questions as I’m not sure exactly what you are looking for.

Hi @alatnet,

Thanks for the clarification. Yes, you can add a component to an entity in C++, there are few different ways to do it. In LyShine it has changed a bit in v1.9 so it depends which release you are using.

The AZ::Entity class allows you to create a component on an entity using either the component type UUID or (with a templated method) the component class. The latter is only available if you have access to the component class definition (which will not be the case for LyShine since they are internal to the gem).

Note that you cannot add components to an entity when it is active, so if it is active you need to deactivate it first.

You can see an example of building a UI canvas programatically in LyShineDebug.cpp in LyShine. See the CreateComponent function.

I hope that helps,

Rob

Yea, i see that. It’s kind of what im looking for but im looking more at this but programically.

I.E. create component, add lyshine component, add lua scripting component.

Lyshine does help in that i do see that there’s an AZ::Component::AddComponent and AZ::Component::CreateComponent, but I do not know what the UUID’s are for lyshine and the lua scripting.

k, i did see that. now the next question is asigning the script and uicanvas parameters within the components.

Hi @alatnet,

The UUIDs for all the UI components are available in CryCommon/LyShine/UiComponentTypes.h.
The Lua Script component is defined here: AzFramework/AzFramework/Script/ScriptComponent.h

You can either copy/paste the UUID from the AZ_COMPONENT line or you can access it by including that header and using AzFramework::ScriptComponent::RTTI_Type()

I know how to deal with child elements. what i would need is something like “AZ::EntityId id = gEnv->pLyShine->LoadCanvas(canvaspath);” to which i could load the uicanvas into the entity’s lyshine component. Same with the script component. I see the SetScript method but the problem is that it doesnt take a path but an asset to which i see that i could create an asset with the ScriptAsset and ScriptSystemComponent in AzCore.

The LyShineDebug.cpp example demonstrates how to create new child elements and set various properties on them. Are there any particular ones you want help with?

For setting the script there is a SetScript method on the ScriptComponent. It is not part of a bus but you can get a pointer to the ScriptComponent if you use the templated CreateComponent method on the Entity.

ah, sorry about the misscommunication.
I do see the UiCanvasAssetRefComponent which has a function SetCanvasPathname which is what I believe to be what i would needed. Accessing that function might be a bit wierd unless it has a bus that is available.

I couldnt find anything similar for a script component.

so i think i have an idea on how to load a canvas into an entity:

	AZ::Entity * ent = new AZ::Entity("LyShine Test Entity");
AZ::Component * lyshineComponent = ent->CreateComponent(LyShine::lyShineSystemComponentUuid);
AZ::Component * scriptComponent = ent->CreateComponent("{8D1BC97E-C55D-4D34-A460-E63C57CD0D4B}");
AZ::Component * canvasAssetComponent = ent->CreateComponent("{05BED4D7-E331-4020-9C17-BD3F4CE4DE85}");
EBUS_EVENT_ID(ent->GetId(), UiCanvasAssetRefBus, SetCanvasPathname, "path/to/canvas.uicanvas");
ent->Init();
ent->Activate();

I believe this is how to create an entity and load a lyshine canvas into it.
Now if i could do the same with the script component, i would be set.

I’m still not sure exactly what you are trying to do here and why.
Why do you want to load a UI canvas into an entity? You can load a canvas using the UiCanvasManagerBus if you just want load a canvas from C++ using an ebus event.

For the Lua case, since you are writing C++ you can use the SetScript method on the ScriptComponent. Are you saying that you would prefer to have a bus method to do this?

Ah, end goal is to be able to load a canvas and a script into an entity so that the script can control the canvas. I know how to load a script through the gEnv-pScriptSystem->ExecuteFile and how to load a canvas through gEnv->pLyShine->LoadCanvas, the only issue is that the script would not be able to control the canvas as they are both separate. So this is where the Component system comes into play as in the editor you can add a UiCanvasAssetRef Component and a Script Component easily and set the parameters. Now doing this through code is a somewhat different matter.

Thanks for the clarification that makes sense. Note that you can also add a lot of functionality inside the UI canvas by adding lua scripts to individual UI elements if you desire.
Is using SetScript on the ScriptComponent not working for you?

ok, this is what im trying to do programmically that you can do within the editor:

Step 1 - create entity:

Step 2 - Add Lua Script Component:

Step 3 - Set Lua Script:

Step 4 - Add Ui Canvas Asset Ref:

Step 5 - Set Canvas:

This, in it’s simplest terms, is what im trying to pull off in C++.
I figured out how to set the canvas path in step 5 in C++ using the UiCanvasAssetRefBus but i have no clue on how to set the lua script for the entity.

Hi @alatnet,

I’m not sure what you mean by “to which i could load the uicanvas into the entity’s lyshine component”. What do you mean by the lyshine component? Are you talking about setting a property or calling a method on the UiCanvasAssetRefComponent?

So, I’m guessing you are having trouble getting the Asset to pass to SetScript? I think you would need something like this:


    AzFramework::ScriptComponent* scriptComponent = entity->CreateComponent<AzFramework::ScriptComponent>();
const AZ::Data::AssetType& scriptAssetType = azrtti_typeid<AZ::ScriptAsset>();
AZ::Data::AssetId assetId;
EBUS_EVENT_RESULT(assetId, AZ::Data::AssetCatalogRequestBus, GetAssetIdByPath, scriptPathname, scriptAssetType, false);
if (assetId.IsValid())
{
AZ::Data::Asset<AZ::ScriptAsset> scriptAsset(assetId, scriptAssetType);
scriptComponent->SetScript(scriptAsset);
}

It should load them both when you activate the entity.

Have the Activate in the CompleteInit function and it didnt do anything.
Didnt load up the canvas nor did it execute the script.
Tried it both in stand alone launcher and in Editor.
Here’s the test script:

	menu = {
Properties = {
},
}
function menu:OnActivate()
Debug.Log("Hello, world!")
end
return menu

EDIT:
It looks like the script DID in fact load and executed in stand alone launcher.
So that is working as intended. Now to get the canvas which doesnt seem to want to load…

EDIT2:
So script does load in Editor but time difference between the script executing in Editor and in stand alone is noticeable.

EDIT3:
Thinking i can use “gEnv->pLyShine->LoadCanvas”, which gives me an entity id to which i flip it to an entity itself via “AZ::Entity * ent = new AZ::Entity(id);” and attach the script component to it.

EDIT4: That didnt really pan out…

So this is what i have for code:


CryLog("Creating Test Ent.");
this->ent = new AZ::Entity("LyShine Test Entity");
//AZ::Component * lyshineComponent = ent->CreateComponent(LyShine::lyShineSystemComponentUuid);
AzFramework::ScriptComponent * scriptComponent = this->ent->CreateComponent<AzFramework::ScriptComponent>();
AZ::Component * canvasAssetComponent = this->ent->CreateComponent("{05BED4D7-E331-4020-9C17-BD3F4CE4DE85}");
if (this->ent->GetId().IsValid()) CryLog("Entity is Valid.");
if (scriptComponent != nullptr) CryLog("Script Component is Valid.");
if (canvasAssetComponent != nullptr) CryLog("Canvas Asset Component is Valid.");
CryLog("Initializing Test Ent.");
this->ent->Init();
CryLog("Setting Canvas.");
EBUS_EVENT_ID(this->ent->GetId(), UiCanvasAssetRefBus, SetCanvasPathname, gEnv->pFileIO->GetAlias("@assets@") + AZStd::string("/Test/text test.uicanvas"));
EBUS_EVENT_ID(this->ent->GetId(), UiCanvasAssetRefBus, SetIsAutoLoad, true);
AZStd::string ret;
EBUS_EVENT_ID_RESULT(ret, this->ent->GetId(), UiCanvasAssetRefBus, GetCanvasPathname);
CryLog("Canvas: %s", ret);
CryLog("Loading Script.");
const AZ::Data::AssetType& scriptAssetType = azrtti_typeid<AZ::ScriptAsset>();
AZ::Data::AssetId assetId;
AZStd::string str = gEnv->pFileIO->GetAlias("@assets@") + AZStd::string("/Test/test.lua");
CryLog("Script Path: %s", str.c_str());
EBUS_EVENT_RESULT(assetId, AZ::Data::AssetCatalogRequestBus, GetAssetIdByPath, str.c_str(), scriptAssetType, false);
if (assetId.IsValid()) {
CryLog("Setting Script.");
AZ::Data::Asset<AZ::ScriptAsset> scriptAsset(assetId, scriptAssetType);
scriptComponent->SetScript(scriptAsset);
}

And this is the output:

<23:45:34> Creating Test Ent.
<23:45:34> Entity is Valid.
<23:45:34> Script Component is Valid.
<23:45:34> Canvas Asset Component is Valid.
<23:45:34> Initializing Test Ent.
<23:45:34> Setting Canvas.
<23:45:34> Canvas: <23:45:34> Loading Script.
<23:45:34> Script Path: @assets@/Test/test.lua

Doesnt seem to be loading either the canvas nor the script…