summaryrefslogtreecommitdiff
path: root/kon/kontextbox.h
diff options
context:
space:
mode:
Diffstat (limited to 'kon/kontextbox.h')
-rw-r--r--kon/kontextbox.h186
1 files changed, 186 insertions, 0 deletions
diff --git a/kon/kontextbox.h b/kon/kontextbox.h
new file mode 100644
index 0000000..25c60b0
--- /dev/null
+++ b/kon/kontextbox.h
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * kontextbox.h
+ *
+ * Copyright (c) 2026 KonAki
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef KONTEXTBOX_H
+#define KONTEXTBOX_H
+
+#include "konsofren.h"
+#include "konfont.h"
+#include "kon2d.h"
+
+/*** panels ***/
+
+typedef enum kon_panelMode {
+ KON_PANEL_STRETCH, /* the image is stretched over the whole panel */
+ KON_PANEL_SLICE /* nine patch: the corners stay as they are, the edges and the middle stretch */
+} kon_panelMode_t;
+
+/* what a box, a name plate or a menu is drawn on. every part is optional: colours with alpha 0 and a NULL image draw nothing.
+ the fill is drawn first, then the image over it, then the border */
+typedef struct kon_panel {
+ uint32_t fill; /* 0xAARRGGBB, a low alpha lets what is behind show through */
+ uint32_t border;
+ int borderWidth;
+ const kon_image *image;
+ kon_rect_t src; /* w == 0 is the whole image */
+ kon_panelMode_t mode;
+ int slice; /* with KON_PANEL_SLICE: the size of the corners in image pixels */
+} kon_panel_t;
+
+/* alpha from 0 to 1 fades the whole panel */
+void kon_drawPanel(kon_framebuffer_t *fb, const kon_panel_t *panel, int x, int y, int width, int height, float alpha);
+
+/*** text box ***/
+
+#define KON_TEXTBOX_TEXT 1024 /* bytes of text kept, a longer text is cut */
+#define KON_TEXTBOX_NAME 64
+#define KON_TEXTBOX_LINES 64 /* lines kept after wrapping */
+#define KON_TEXTBOX_CHOICES 8
+#define KON_TEXTBOX_LABEL 64
+
+typedef enum kon_textboxState {
+ KON_TEXTBOX_EMPTY,
+ KON_TEXTBOX_TYPING, /* the letters are still coming in */
+ KON_TEXTBOX_WAITING, /* the page is all there, waiting for kon_textboxAdvance */
+ KON_TEXTBOX_CHOOSING /* a menu is up, see kon_textboxConfirm */
+} kon_textboxState_t;
+
+typedef enum kon_side {
+ KON_SIDE_LEFT,
+ KON_SIDE_RIGHT
+} kon_side_t;
+
+typedef enum kon_align {
+ KON_ALIGN_LEFT,
+ KON_ALIGN_CENTER,
+ KON_ALIGN_RIGHT
+} kon_align_t;
+
+typedef enum kon_choiceMode {
+ KON_CHOICES_LIST, /* the rows of a menu inside the box's panel */
+ KON_CHOICES_BUTTONS /* every choice is a panel of its own, the box's panel is not drawn. the usual look in a visual novel */
+} kon_choiceMode_t;
+
+typedef enum kon_portraitMode {
+ KON_PORTRAIT_INSIDE, /* in the middle of the box's height, inside its padding */
+ KON_PORTRAIT_HANG /* standing on the bottom of the box, a tall picture reaches above the top edge */
+} kon_portraitMode_t;
+
+/* one box for a message in an RPG, a visual novel or a plain popup, and with kon_textboxChoices it is the menu too.
+ fill in the public fields after kon_textboxInit, the rest is private. the box does not read input, the game calls kon_textboxAdvance
+ and kon_textboxSelect when it wants to. sprites in a visual novel belong to the stage, the box only holds the face that sits inside it */
+typedef struct kon_textbox {
+ kon_font_t *font;
+ int width, height;
+ kon_tween_t x, y, alpha; /* where it is and how solid, see kon_textboxMove and kon_textboxFade */
+
+ kon_panel_t panel, plate;
+ int padding;
+ int marginLeft, marginRight; /* extra room kept clear of text on each side, for a sprite that stands over the box */
+ int showEmpty; /* draw the panel while there is nothing to say, for a box that stays on screen. otherwise an empty box is not drawn */
+ int platePadding;
+ int plateOffsetX, plateOffsetY; /* the name plate sits on the top left of the box, moved by this */
+ uint32_t textColor, nameColor, choiceColor, selectColor, selectFill;
+ kon_align_t align; /* of the lines of a message */
+ kon_align_t choiceAlign; /* of the text of a choice */
+ kon_choiceMode_t choiceMode;
+ kon_panel_t button, buttonSelected; /* for KON_CHOICES_BUTTONS, a button is as wide as the box and as tall as a line plus the padding */
+ int buttonGap;
+ float speed; /* letters a second, 0 shows each page at once */
+ int lineSpacing; /* extra pixels between lines */
+
+ const kon_image *portrait;
+ kon_rect_t portraitSrc; /* w == 0 is the whole image */
+ kon_side_t portraitSide;
+ kon_portraitMode_t portraitMode;
+
+ /* private */
+ kon_textboxState_t state;
+ char text[KON_TEXTBOX_TEXT];
+ char name[KON_TEXTBOX_NAME];
+ int length;
+ int lineStart[KON_TEXTBOX_LINES], lineLength[KON_TEXTBOX_LINES];
+ int lineCount, linesPerPage, page, pageCount;
+ int pageChars;
+ float shown;
+ char labels[KON_TEXTBOX_CHOICES][KON_TEXTBOX_LABEL];
+ int choiceCount, selected;
+} kon_textbox_t;
+
+/* x, y is the top left. the font has to stay alive as long as the box is used. the defaults are the pastel on dark palette */
+void kon_textboxInit(kon_textbox_t *box, kon_font_t *font, int x, int y, int width, int height);
+
+/* shows text, wrapped to the box and split into pages that fit. name may be NULL. replaces what was there, menu included.
+ the text is copied. new lines in it start a new line in the box */
+void kon_textboxSay(kon_textbox_t *box, const char *name, const char *text);
+
+/* a face from a sheet of equally sized faces, counted left to right then top to bottom, 144 by 144 and 4 across in RPG Maker.
+ an index off the sheet takes the face out */
+void kon_textboxFace(kon_textbox_t *box, const kon_image *sheet, int frameWidth, int frameHeight, int index, kon_side_t side);
+
+/* the face inside the box, NULL takes it out. src NULL is the whole image. the text is wrapped again to fit beside it */
+void kon_textboxPortrait(kon_textbox_t *box, const kon_image *image, const kon_rect_t *src, kon_side_t side, kon_portraitMode_t mode);
+
+/* the action key. finishes the letters coming in, or turns to the next page, or ends the message. returns 1 when the last
+ page was dismissed, the box is empty again */
+int kon_textboxAdvance(kon_textbox_t *box);
+
+/* 1 when the page is complete, and 1 if there is a page after it, for a "more" mark you draw yourself */
+int kon_textboxWaiting(const kon_textbox_t *box);
+int kon_textboxMore(const kon_textbox_t *box);
+
+/* shows a menu in place of a message, the labels are copied. at most KON_TEXTBOX_CHOICES, the rest are dropped.
+ kon_textboxFitChoices makes the box just big enough for them, at least minWidth wide */
+void kon_textboxChoices(kon_textbox_t *box, const char *const *labels, int count);
+void kon_textboxFitChoices(kon_textbox_t *box, int minWidth);
+
+/* moves the selection by delta, wrapping round */
+void kon_textboxSelect(kon_textbox_t *box, int delta);
+void kon_textboxHighlight(kon_textbox_t *box, int index);
+
+/* the choice under a point (in the pixels you draw at), or -1 */
+int kon_textboxChoiceAt(const kon_textbox_t *box, int x, int y);
+
+/* returns the selected choice and closes the menu, -1 if there is none */
+int kon_textboxConfirm(kon_textbox_t *box);
+
+void kon_textboxClear(kon_textbox_t *box);
+
+/* puts the box against the left, in the middle or against the right of a view, margin pixels from the edge, at once.
+ RPG Maker's choice position. a menu with no panel at all (fill and border 0 on panel, button and buttonSelected) is its transparent window */
+void kon_textboxPlaceX(kon_textbox_t *box, int viewWidth, kon_align_t align, int margin);
+
+/* puts the box in the middle of a view of that size, along the axes you ask for, at once */
+void kon_textboxCenter(kon_textbox_t *box, int viewWidth, int viewHeight, int horizontal, int vertical);
+
+void kon_textboxMove(kon_textbox_t *box, float x, float y, float seconds, kon_ease_t ease);
+void kon_textboxFade(kon_textbox_t *box, float alpha, float seconds, kon_ease_t ease);
+
+/* returns 1 on the frame the page finished appearing */
+int kon_textboxUpdate(kon_textbox_t *box, float dt);
+
+void kon_textboxDraw(kon_textbox_t *box, kon_framebuffer_t *fb);
+
+#endif