User interface development using ECS (Entity-Component-System) architecture instead of traditional inheritance
This article is a continuation of Evgeny Zakharov's speech at the summer conference C ++ Russia, where he described the development of a user interface using the ECS (Entity-Component-System) architecture instead of traditional inheritance and part of the UI device in World of Tanks Blitz.
In his report, Eugene dwells in detail on what principles of creating frameworks for UI are used in the world today, and also tells how you can make ECS and UI friends, and what pros and cons you can get from this as a result.
In this article, using a small UI example in World of Tanks Blitz, Eugene shows what is the big plus of the ECS architecture in UI.
Before studying the article, we advise you to watch the video of the report.
Implementing radial progress display
, , .. , 360 , - 100%. World of Tanks Blitz , , DLC .
, :
texture component;
texture component.
, . , : RadialProgressComponent.
, .
-, :
. : , ( ) "" .
texture- .
:
, texture- , .
:
, : RadialProgressComponent. ( ) 0.5:
:
, , , ( – RadialProgressSystem).
, ClipPolygonComponent – , - . RadialProgress- .
void RadialProgressSystem::RegisterControl(Control &control)
{
auto *pieClippable = control.GetComponent<RadialProgressComponent>();
if (pieClippable && control.GetComponent<TextureComponent>())
{
pieClippable->MarkAsDirty();
this->registeredControls.insert(&control);
}
}
, , TextureComponent RadialProgressComponent. , , – Process.
void RadialProgressSystem::UnregisterControl(Control &control)
{
this->registeredControls.erase(&control);
}
, , .
Progress , . "" dirty RadialProgressComponent. "" , RadialProgressComponent dirty true, false.
void RadialProgressSystem::Process(float elapsedTime)
{
for (Control *control : this->registeredControls)
{
auto *pieClippable = control->GetComponent<UIRadialProgressComponent>();
if (!pieClippable->IsDirty())
{
continue;
}
auto *polygon = control->GetComponent<ClipPolygonComponent>();
if (!polygon)
{
ReportError(control, "You need UIClipPolygonComponent for UIRadialProgressComponent");
continue;
}
auto *textureComponent = control->GetComponent<TextureComponent>();
if (textureComponent != nullptr && textureComponent->GetSprite() != nullptr)
{
Polygon2 &polygonData = polygon->GetPolygon();
polygonData.Clear();
const Vector2 imageSize = textureComponent->GetSprite()->GetSize();
const Vector2 pivot = CalcPivot(pieClippable);
const Vector2 center = imageSize * pivot;
const float progress = pieClippable->GetProgress();
float startAngle = pieClippable->GetNormalizedStartAngle();
float endAngle = pieClippable->GetNormalizedEndAngle();
const float currentAngle = Interpolation::Linear(startAngle, endAngle, 0, progress, 1);
const float width = pivot.x > 0 ? center.x : imageSize.x;
const float height = pivot.y > 0 ? center.y : imageSize.y;
const float initAngle = std::atan(width / height);
polygonData.AddPoint(center);
polygonData.AddPoint(CalcPointOnRectangle(startAngle, center, imageSize));
int direction = startAngle < endAngle ? 1 : -1;
float startOffset = direction > 0 ? 0 : PI_2 + pieClippable->GetAngleBias();
float squareAngle = startOffset + direction * initAngle;
const float directedStartAngle = direction * startAngle;
const float directedEndAngle = direction * endAngle;
const float directedCurrentAngle = direction * currentAngle;
float directedSqureAngle = direction * squareAngle;
const float doubledInitAngle = initAngle * 2.f;
Vector<Vector2> squares {
Vector2(imageSize.x, 0),
Vector2(imageSize.x, imageSize.y),
Vector2(0.f, imageSize.y),
Vector2(0.f, 0.f)
};
int i = 0;
while (directedSqureAngle < directedEndAngle)
{
if (directedSqureAngle < directedCurrentAngle && directedSqureAngle > directedStartAngle)
{
int squareIndex = direction > 0 ? i % 4 : 3 - i % 4;
polygonData.AddPoint(squares[squareIndex]);
}
i++;
int switcher = i % 2;
squareAngle += direction * (PI * switcher - Sign(switcher - 0.5f) * doubledInitAngle);
directedSqureAngle = direction * squareAngle;
}
polygonData.AddPoint(CalcPointOnRectangle(currentAngle, center, imageSize));
pieClippable->ResetDirty();
}
}
}
, RadialProgress-, , – , . :
, UI World of Tanks Blitz – . . ECS UI – , , ( ) .