/* SPDX-License-Identifier: MIT */ /* * konstage.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 KONSTAGE_H #define KONSTAGE_H #include "konsofren.h" #include "kon2d.h" /*** definition ***/ /* the picture behind everything. none leaves the framebuffer as it is, so a map or a scene drawn first shows through */ typedef enum kon_fit { KON_FIT_NONE, KON_FIT_STRETCH, /* fills the view, squashing the picture if the shapes differ */ KON_FIT_COVER, /* fills the view keeping the shape, the edges that don't fit are cut off */ KON_FIT_CONTAIN, /* the whole picture keeping the shape, the rest of the view is left alone */ KON_FIT_CENTER /* the picture as it is, in the middle */ } kon_fit_t; /* sprites are drawn in two goes so the game can put its text box in between. back is under the box, front is over it, so a see through effect on a sprite does not turn into a smear over the text */ typedef enum kon_layer { KON_LAYER_BACK, KON_LAYER_FRONT } kon_layer_t; /* standing places across the view, where a sprite goes with kon_stagePlace. their x is stage->slotX, as a share of the width */ typedef enum kon_slot { KON_SLOT_FAR_LEFT, KON_SLOT_LEFT, KON_SLOT_CENTER, KON_SLOT_RIGHT, KON_SLOT_FAR_RIGHT, KON_SLOT_COUNT } kon_slot_t; /* what kon_stageTween can glide */ typedef enum kon_prop { KON_PROP_X, KON_PROP_Y, KON_PROP_ALPHA, /* 0 to 1 */ KON_PROP_SCALE, KON_PROP_BRIGHTNESS, /* 1 as drawn, lower darkens it, the usual way to show who is not talking */ KON_PROP_COUNT } kon_prop_t; typedef struct kon_stageSprite { int used; const kon_image *image; kon_rect_t src; /* w == 0 is the whole image */ kon_tween_t prop[KON_PROP_COUNT]; float anchorX, anchorY; /* the point of the sprite, 0 to 1, that sits at x, y. 0.5, 1 is the middle of its feet */ int flip; kon_layer_t layer; int z; /* higher is in front inside its layer, sprites with the same z go in the order they were added */ int hiding; /* removes itself when it has faded out */ } kon_stageSprite_t; typedef struct kon_stageBackground { const kon_image *image; kon_fit_t fit; kon_tween_t alpha; kon_tween_t zoom, focusX, focusY; } kon_stageBackground_t; /* the stage does not own its sprites or the images, sprites is room for capacity of them */ typedef struct kon_stage { int width, height; /* the view, in the pixels you draw at */ kon_stageSprite_t *sprites; int capacity; float slotX[KON_SLOT_COUNT]; kon_filter_t filter; /* for sprites and the background that get scaled */ kon_stageBackground_t back, old; } kon_stage_t; /*** functions ***/ void kon_stageInit(kon_stage_t *stage, kon_stageSprite_t *sprites, int capacity, int width, int height); /* the background fades in over the old one for seconds, 0 swaps at once. image NULL clears it */ void kon_stageBackground(kon_stage_t *stage, const kon_image *image, kon_fit_t fit, float seconds); /* pans and zooms the background, which is what a CG wants. zoom 1 shows it as the fit says and 2 shows half of it. focus is the point of the picture, 0 to 1 across and down, kept in the middle of the view. a picture that fills the view never lets its edge slide in. a new background starts at zoom 1, focus 0.5 */ void kon_stageBackgroundView(kon_stage_t *stage, float zoom, float focusX, float focusY, float seconds, kon_ease_t ease); /* a new sprite at 0, 0 in view, not faded in. returns its index or -1 when there is no room. src NULL is the whole image. it stands on the bottom middle of itself, change anchorX and anchorY on the sprite for anything else */ int kon_stageAdd(kon_stage_t *stage, const kon_image *image, const kon_rect_t *src, kon_layer_t layer); void kon_stageRemove(kon_stage_t *stage, int index); /* moves a sprite to the other side of the text box. they start in the back layer, behind the box, which is where characters belong */ void kon_stageLayer(kon_stage_t *stage, int index, kon_layer_t layer); /* swaps the picture, for a new expression. the sprite keeps where it is */ void kon_stageFrame(kon_stage_t *stage, int index, const kon_image *image, const kon_rect_t *src); void kon_stageTween(kon_stage_t *stage, int index, kon_prop_t prop, float to, float seconds, kon_ease_t ease); /* shorthands for a move, a fade and for walking to a slot along the bottom of the view */ void kon_stageMove(kon_stage_t *stage, int index, float x, float y, float seconds, kon_ease_t ease); void kon_stageFade(kon_stage_t *stage, int index, float alpha, float seconds, kon_ease_t ease); void kon_stagePlace(kon_stage_t *stage, int index, kon_slot_t slot, float seconds, kon_ease_t ease); /* fades out and removes itself */ void kon_stageHide(kon_stage_t *stage, int index, float seconds); void kon_stageUpdate(kon_stage_t *stage, float dt); /* 1 while anything is still gliding or fading, for a script that waits for it */ int kon_stageBusy(const kon_stage_t *stage); /* draw the background and then the back layer, then your text box, then the front layer. without a background pass 0 */ void kon_stageDrawBackground(const kon_stage_t *stage, kon_framebuffer_t *fb); void kon_stageDraw(const kon_stage_t *stage, kon_framebuffer_t *fb, kon_layer_t layer); #endif