2
\$\begingroup\$

I'm working on an engine for my game (in C++). I've done the graphics related stuff and I've started working on UI (user interface). When I was working on buttons I've realized that hardcoding every kind of button would not be possible (or would be too many classes) as I have buttons with only labels, with colored backgrounds, with texture backgrounds and so on...

So I think what I need are Components. I just build the button I want:

UIButton* btn = new UIButton();
btn->AddRenderComponent(new DrawRectComponent(...));
btn->AddRenderComponent(new DrawStringComponent(...));
btn->AddLogicComponent(new SendEventOnClickComponent(...));

My problem is that I don't know how to tell the component objects what fields should they use from the UI elements? For example position and size (which could change dinamically). Should I use references for example?

Also it would be good if I could not only use this in the UI, but a similar component system could be used in other parts of the engine (at entities for example).

\$\endgroup\$
2
\$\begingroup\$

Let's see if I can understand your question here:

  • You want to create some UI elements (such as your UIButton);
  • All of the components that are passed to it (eg.: RenderComponent) should be able to access the UI object's properties.

Is this it? Because if that's the case, then you can do use the following logic:

  • Each of the UI elements should have fields for position, sizeX and sizeY for example;
  • With that in mind, you can create a super class that represents an UI element, and have all your elements inherit from that class;
  • In that very same super class, you can already leave declarations for possible components you want to add, and those methods declared already as well (eg.: AddRenderComponent);
  • In each one of the subclasses (eg.: UIButton), since you say the size and position aren't always the same, these variables should be controlled within the UI component;
  • That is good, because then you decouple code from the outside of the elements themselves. By doing that, each button will have different characteristics (like random animations that you might want to apply to the buttons, or have them move around the screen);
  • It's also good because then you can just access the object's position and size through its instance. Like that, you can have all buttons as dynamic as you want, and independent from one another;
  • As for the components, since they're "coupled" to the UI element, they can use all of the information from the element as they want - that can be achieved in passing the needed information in the methods:

    void UIButton::AddRenderComponent(T renderComponent) {
      renderComponent.elementSize = this->size; //size passing example
      // Add your render component to the element here
    }
    

With the above, your elements will have their properties set for themselves, with the possibility for the outside to access them, as well as keep your components with the needed knowledge.

Hope that helps you!

\$\endgroup\$
0
\$\begingroup\$

What you should do is have a local relative field in the subcomponents, for instance the size and position could be floats in the range of [0,1] and then you figure out the absolute size, position and everything else of a subcomponent by multiplying the elements values with the components values when rendering.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.