Well, first of all my engine contains the basic controls: button, textbox, checkbox.
So, when I want a button I only need to create a variable from it and call its update and draw at the right places. The button will handle the mouseover, click and similar events and changes the image that is displayed based on its states (isvisible, isenabled, ismouseover, …), although I have an OnClick event that I can subscribe onto so this is what I am using in my dialogue to navigate. It looks like this:
CustomButton nextButton = new CustomButton(...);
nextButton.OnClick += NextClick();
private void NextClick() { ... }
My static mousehandler class takes care of pressed/released state changes, so even if you hold the left mouse button pressed for a long time over a button, the OnClick event is only called once. Even, if you hold the button pressed, but you move the cursor from/onto the same button, the event will not get called until you do not release the button. I tried to mimic the winforms functionalities.
The same applies to my other controls as well, so the textbox handles its own statuses and update/draw logic, etc.
So, basically this dialogue will be one big class with its own Update and Draw method. Also, it should either have an Initialize or LoadContent or similar methods where you can instantiate those controls that you want to display. This dialogue should not take care of control states, “simply” iterate through the controls and call their Update/Draw in the dialogue’s Update/Draw method.
I strongly recommend to create your own TextView control, in which you can display any kind of text. In its Initialize method you should split the text into multiple texts based on your own wrapping logic. My logic is the following:
- 5px padding on all sides
- One line of text width must be the maximum available width based on the control
width and the padding. If the control is 200px wide, then it will be 200-2x5, so
190. I iterate through eash word in the text, check if the current size will be
smaller than this maximum and if it is, then I simply append the word to the actual
line of text. When I exceed the maximum value, or I have a line break in the text,
I add a new line of text to my list.
- You should create your own text scrolling, or simply design the displayed text to
be smaller than the available space.
- In your dialogue you should have a list of texts you want to display. In each step
add one of them to the TextView, call wrapping logic and in its Draw method draw
each line of text.
Maybe there is an easier way to do this, I do not know.
Basically, when I create a new control I always create the Constructor, Initialize and/or LoadContent, Update and Draw methods, and any extra public methods that I need to call from outside of the control.
To be totally honest, I only use enum keys and not actual strings when I want to display a text. This is because my controls have a public UpdateText method that is called when I change language. This method changes the source string to a new one based on the selected language and call the wrapping logic on this new text. The new text list overwrites the previous list and in the Draw method I dispay this new list, this is why the player can change language settings during a dialogue.
So, I have someting like this in my control:
private List<TranslationKey> KeysOfTheTextIWantToDisplay { get; set; }
private List<string> DisplayedTexts { get; set; }
private MyClassConstructor(List<TranslationKey> keysOfTheTextIWantToDisplay , ...)
{
...
KeysOfTheTextIWantToDisplay = keysOfTheTextIWantToDisplay;
...
}
public void UpdateTexts()
{
DisplayedTexts.Clear();
foreach(translationKey key in KeysOfTheTextIWantToDisplay)
{
List<string> wrappedTexts = WrapText(LanguageHelper.GetText(key));
foreach(string s in wrappedTexts)
DisplayedTexts.Add(s);
}
...
}
private List<string> WrapText(string textToWrap)
{
//based on the above logic wrap the text into small parts and return them
return wrappedTexts;
}