Pengembangan antarmuka pengguna menggunakan arsitektur ECS (Entity-Component-System), bukan warisan tradisional
Artikel ini adalah kelanjutan dari pidato Evgeny Zakharov di konferensi musim panas C ++ Rusia, di mana dia menjelaskan pengembangan antarmuka pengguna menggunakan arsitektur ECS (Entity-Component-System) alih-alih warisan tradisional dan bagian dari perangkat UI di World of Tanks Blitz.
Dalam laporannya, Eugene membahas secara rinci tentang prinsip-prinsip pembuatan kerangka kerja untuk UI yang digunakan di dunia saat ini, dan juga memberi tahu bagaimana Anda dapat berteman dengan ECS dan UI, dan pro dan kontra apa yang dapat Anda peroleh dari hal ini sebagai hasilnya.
Dalam artikel ini, dengan menggunakan contoh UI kecil di World of Tanks Blitz, Eugene menunjukkan nilai tambah besar arsitektur ECS di UI.
Sebelum mempelajari artikel tersebut, kami menyarankan Anda untuk menonton video dari laporannya.
Menerapkan tampilan kemajuan radial
, , .. , 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 β , , ( ) .