Fixed scrollable container issues and refactor

This commit is contained in:
Booklordofthedings 2024-06-28 20:50:42 +02:00
parent cfefe7db2b
commit 6d06a13d64
18 changed files with 322 additions and 187 deletions

View file

@ -7,5 +7,20 @@ StartupProject = "ExampleGui"
[Configs.Debug.Win64] [Configs.Debug.Win64]
ConfigSelections = {raylib-beef = {Config = "StaticDebug"}} ConfigSelections = {raylib-beef = {Config = "StaticDebug"}}
[Configs.Debug.wasm32]
AllocType = "CRT"
EnableObjectDebugFlags = false
EmitObjectAccessCheck = false
[Configs.Release.Win64] [Configs.Release.Win64]
ConfigSelections = {raylib-beef = {Config = "StaticRelease"}} ConfigSelections = {raylib-beef = {Config = "StaticRelease"}}
[Configs.Paranoid.wasm32]
AllocType = "CRT"
EnableObjectDebugFlags = false
EmitObjectAccessCheck = false
[Configs.Test.wasm32]
AllocType = "CRT"
EnableObjectDebugFlags = false
EmitObjectAccessCheck = false

View file

@ -1,37 +1,51 @@
namespace TheaterGui; namespace TheaterGui;
using TheaterGui.Components;
using System; using System;
using System.Collections; using System.Collections;
using RaylibBeef; using RaylibBeef;
using internal TheaterGui;
using TheaterGui.Components;
class App class App
{ {
/*
There are two ways to run TheaterGui.
Either full, by using the Run function or by manually calling the functions in Run.
This way you can integrate TheaterGui into other raylib applications of your choice.
//All loaded textures Components are supposed to be created via inheritance for each individual component, except some very simple exeptions (Labels, Placeholders)
private static List<Popup> Popups = new .() ~ DeleteContainerAndItems!(_); */
#region Fields
//For hover items //For hover items
private static Vector2 oldPos = .(0,0); private static List<Popup> _Popups = new .() ~ DeleteContainerAndItems!(_);
private static double movTime = 0; private static Vector2 _OldPos = .(0, 0);
private static String hoverText = new .() ~ delete _; private static double _MovTime = 0;
private static String _HoverText = new .() ~ delete _;
private static Vector2 _OldSize = .(0, 0);
public static Textures Textures ~ delete _;
public static Textures Textures ~ delete _; //All loaded textures
public static Component Selected; //Currently selected component public static Component Selected; //Currently selected component
public static bool AllowReorder = true; public static bool AllowReorder = true;
private static Screen _CurrentScreen = null;
private static Screen _CurrentScreen = null ~ delete _;
public static Screen CurrentScreen public static Screen CurrentScreen
{ {
get => _CurrentScreen; get => _CurrentScreen;
set set
{ {
if(_CurrentScreen != null) if (_CurrentScreen != null)
delete _CurrentScreen; delete _CurrentScreen;
_CurrentScreen = value; _CurrentScreen = value;
} }
}; };
///Window width ///Window width
public static int32 Width public static int32 Width
{ {
@ -39,6 +53,7 @@ class App
set => Raylib.SetWindowSize(value, Raylib.GetRenderHeight()); set => Raylib.SetWindowSize(value, Raylib.GetRenderHeight());
} }
///Window height ///Window height
public static int32 Height public static int32 Height
{ {
@ -46,12 +61,14 @@ class App
set => Raylib.SetWindowSize(Raylib.GetRenderWidth(), value); set => Raylib.SetWindowSize(Raylib.GetRenderWidth(), value);
} }
///Mouse position ///Mouse position
public static Vector2 Mouse public static Vector2 Mouse
{ {
get => Raylib.GetMousePosition(); get => Raylib.GetMousePosition();
} }
//Mouse wheel offset //Mouse wheel offset
public static float Wheel public static float Wheel
{ {
@ -59,223 +76,285 @@ class App
set; set;
} }
public static void ForceReorder()
{
if(AllowReorder && CurrentScreen != null)
CurrentScreen.Reorder(Width);
}
public static void OpenPopup(Popup popup) private static bool _ShouldClose;
public static bool ShouldClose
{ {
Popups.Add(popup); public get
{
return _ShouldClose || Raylib.WindowShouldClose();
}
public set => _ShouldClose = value;
}
#endregion
///Run TheaterGui (Use for fully independent programs)
///@param pName Name of the window
///@param pWidth Width of the window
///@param pHeight Height of the window
///@param pStartScreen The starting Screen of the application
public static void Run<T>(StringView pName, int32 pWidth, int32 pHeight) where T : Screen
{
InitializeRaylib(pName, pWidth, pHeight);
InitializeGui<T>();
#if BF_PLATFORM_WASM
WebAssembly.emscripten_set_main_loop(=> ProcessDrawFrame, 40, 1);
///Afaik the infinite loop means, that the deinitialization functionality will not be called,
///but that should be fine for wasm since it fully cleans up when you exit the page.
///If we dont do it calls the deinitialization directly afterwards
#else
while (!App.ShouldClose)
ProcessDrawFrame();
#endif
DeinitializeGui();
DeinitializeRaylib();
} }
///Initializes the raylib enviroment
///Initialize the TheaterGui app ///@param pName Name of the window
public static void Initialize(StringView pAppTitle = "TheaterApp") ///@param pWidth Width of the window
///@param pHeight Height of the window
public static void InitializeRaylib(StringView pName, int32 pWidth, int32 pHeight)
{ {
//Default raylib settings //Default raylib settings
Raylib.SetConfigFlags((.)(ConfigFlags.FLAG_WINDOW_RESIZABLE | ConfigFlags.FLAG_WINDOW_HIGHDPI)); Raylib.SetConfigFlags((.)(ConfigFlags.FLAG_WINDOW_RESIZABLE | ConfigFlags.FLAG_WINDOW_HIGHDPI));
Raylib.InitWindow(1280, 720, scope String(pAppTitle)); Raylib.InitWindow(pWidth, pHeight, scope String(pName));
Raylib.SetExitKey(0); Raylib.SetExitKey(0);
Raylib.SetTargetFPS(40); #if !BF_PLATFORM_WASM ///Otherwise raylib sleeps and delays browser responsiveness
Raylib.SetWindowMinSize(640,360); Raylib.SetTargetFPS(40); //Should be a resonable framerate for gui apps
#endif
Raylib.SetWindowMinSize(640, 360);
///Set the default window icon ///Set the default window icon
var icon = Raylib.LoadImageFromMemory(".png", (.)&Theme.Texture_WindowIcon, Theme.Texture_WindowIcon.Count); var icon = Raylib.LoadImageFromMemory(".png", (.)&Theme.Texture_WindowIcon, Theme.Texture_WindowIcon.Count);
Raylib.SetWindowIcon(icon); Raylib.SetWindowIcon(icon);
Raylib.UnloadImage(icon); Raylib.UnloadImage(icon);
}
//Load textures
///Initialize the gui enviroment
public static void InitializeGui<T>() where T : Screen
{
Textures = new .(); Textures = new .();
Theme.Font = Raylib.LoadFontFromMemory(".ttf", (.)&Theme.Din, Theme.Din.Count, Theme.FontSize, null, 256); CurrentScreen = new T();
Theme.FontSmall = Raylib.LoadFontFromMemory(".ttf", (.)&Theme.Din, Theme.Din.Count, Theme.FontSizeSmall, null, 256);
Theme.FontLarge = Raylib.LoadFontFromMemory(".ttf", (.)&Theme.Din, Theme.Din.Count, Theme.FontSizeLarge, null, 256);
} }
///Deinitialize the TheaterGui app
public static void Deinitialize()
{
///Cleanup the gui enviroment
public static void DeinitializeGui() => void();
///Cleanup the raylib enviroment
public static void DeinitializeRaylib() => void();
///To be called by emscripten
private static void ProcessDrawFrame()
{
ProcessFrame();
Raylib.BeginDrawing();
Raylib.ClearBackground(Theme.Background);
DrawFrame();
Raylib.EndDrawing();
} }
///Start the application on the input stream
public static void Start(Screen pScreen)
{
CurrentScreen = pScreen;
Vector2 oldSize = .(0,0);
while(!Raylib.WindowShouldClose()) ///Process the logic for a single frame of the application
public static void ProcessFrame()
{ {
if(oldSize != .(Width,Height))
Vector2 newSize = .(Width, Height);
if (_OldSize != newSize)
{ {
CurrentScreen.Reorder(Width); CurrentScreen.Reorder((.)newSize.x);
oldSize = .(Width,Math.Min(Height, CurrentScreen.Height)); _OldSize = newSize;
} }
//This could probably be solved better Input.HandleScrolling(Raylib.GetMouseWheelMove());
var wh = Raylib.GetMouseWheelMove();
if(!CurrentScreen.HandleScrollEvent(wh*wh*wh, (.)Mouse.x, (.)Mouse.y) && CurrentScreen.Height - Height > 0)
{
var w = Raylib.GetMouseWheelMove();
Wheel += w * w * w;
Wheel = Math.Clamp(Wheel, -1*(CurrentScreen.Height - Height), 0);
}
else
Wheel = 0;
if(Raylib.IsMouseButtonPressed(0))
if (Raylib.IsMouseButtonPressed(0))
HandleLeftClick(); HandleLeftClick();
else if(Raylib.IsMouseButtonDown(0)) else if (Raylib.IsMouseButtonDown(0))
HandleButtonDown(); HandleButtonDown();
else if(Raylib.IsMouseButtonPressed(1)) else if (Raylib.IsMouseButtonPressed(1))
{ {
if(Popups.Count > 0) if (_Popups.Count > 0)
{ {
var top = Popups[Popups.Count-1]; var top = _Popups[_Popups.Count - 1];
if(top is RightClickPopup) if (top is RightClickPopup)
{ {
Popups.Remove(top); _Popups.Remove(top);
delete top; delete top;
} }
} }
Toolbar.ToolbarCategory popupCat = new .("Items"); Toolbar.ToolbarCategory popupCat = new .("Items");
CurrentScreen.OnRightClick((.)Mouse.x, (.)Mouse.y, popupCat); CurrentScreen.OnRightClick((.)Mouse.x, (.)Mouse.y, popupCat);
if(popupCat.Items.Count > 0) if (popupCat.Items.Count > 0)
Popups.Add(new RightClickPopup((.)Mouse.x, (.)Mouse.y, popupCat)); _Popups.Add(new RightClickPopup((.)Mouse.x, (.)Mouse.y, popupCat));
else else
delete popupCat; delete popupCat;
} }
else else
HandleHover(); HandleHover();
}
///Draw the current state of the application
public static void DrawFrame()
{
//Drawing logic //Drawing logic
Raylib.BeginDrawing();
Raylib.ClearBackground(Theme.Background);
CurrentScreen.Render((.)Wheel); CurrentScreen.Render((.)Wheel);
for(var i in Popups) for (var i in _Popups)
i.Render((.)Wheel); i.Render((.)Wheel);
if(hoverText != String.Empty) if (!_HoverText.IsEmpty)
{ //TODO: When you move outside of the window, the hover fucks up {
RenderHoverText();
_HoverText.Clear();
}
}
private static void RenderHoverText()
{
int32 yOffset = 0; int32 yOffset = 0;
int32 xOffset = 0; int32 xOffset = 0;
var measure = Raylib.MeasureTextEx(Theme.FontSmall, hoverText, Theme.FontSizeSmall, 0);
if(Raylib.GetMouseX() < Width/2) var measure = Raylib.MeasureTextEx(Theme.FontSmall, _HoverText, Theme.FontSizeSmall, 0);
if (Mouse.x < Width / 2) //Render the textbox to the right of the cursor
xOffset = 15; xOffset = 15;
else else //Render the textbox to the left of the cursor
xOffset = (.)(-1 * measure.x)-15; xOffset = (.)(-1 * measure.x) - 15;
if(Raylib.GetMouseY() < Height/2) if (Mouse.y < Height / 2) //Render the textbox at the y location of the cursor
yOffset = 0; yOffset = 0;
else else //Render the textbox offset so, that the textbox y ends at the y location of the cursor
yOffset = (.)(-1 * measure.y); yOffset = (.)(-1 * measure.y);
Raylib.DrawRectangle((.)Mouse.x-3+xOffset+3, (.)Mouse.y-3+yOffset+3, (.)measure.x+6, (.)measure.y+3, .(0, 0, 0, 70));
Raylib.DrawRectangle((.)Mouse.x-3+xOffset, (.)Mouse.y-3+yOffset, (.)measure.x+6, (.)measure.y+3, .(218, 211, 176, 255)); //BoxShadow
Raylib.DrawRectangleLines((.)Mouse.x-3+xOffset, (.)Mouse.y-3+yOffset, (.)measure.x+6, (.)measure.y+3, Raylib.BLACK); //Box
Raylib.DrawTextEx(Theme.FontSmall, hoverText, Raymath.Vector2Add(Mouse, .(xOffset,yOffset)), Theme.FontSizeSmall, 0, Raylib.BLACK); //BoxBorder
//BoxContent
Raylib.DrawRectangle((.)Mouse.x - 3 + xOffset + 3, (.)Mouse.y - 3 + yOffset + 3, (.)measure.x + 6, (.)measure.y + 3, Color(0, 0, 0, 70));
Raylib.DrawRectangle((.)Mouse.x - 3 + xOffset, (.)Mouse.y - 3 + yOffset, (.)measure.x + 6, (.)measure.y + 3, Color(218, 211, 176, 255));
Raylib.DrawRectangleLines((.)Mouse.x - 3 + xOffset, (.)Mouse.y - 3 + yOffset, (.)measure.x + 6, (.)measure.y + 3, Raylib.BLACK);
Raylib.DrawTextEx(Theme.FontSmall, _HoverText, Raymath.Vector2Add(Mouse, Vector2(xOffset, yOffset)), Theme.FontSizeSmall, 0, Raylib.BLACK);
} }
Raylib.EndTextureMode();
Raylib.EndDrawing();
if(hoverText != String.Empty) public static void ForceReorder()
hoverText.Clear(); {
if (AllowReorder && CurrentScreen != null)
CurrentScreen.Reorder(Width);
} }
public static void OpenPopup(Popup popup)
{
_Popups.Add(popup);
} }
///Handles the leftclick action ///Handles the leftclick action
private static void HandleLeftClick() private static void HandleLeftClick()
{ {
if(Popups.Count > 0) if (_Popups.Count > 0)
{ //Only checking the topmost popup { //Only checking the topmost popup
var top = Popups[Popups.Count-1]; var top = _Popups[_Popups.Count - 1];
if(Rectangle(top.X, top.Y, top.Width, top.Height).Overlaps(Raylib.GetMouseX(), (.)(Raylib.GetMouseY()-Wheel))) if (Rectangle(top.X, top.Y, top.Width, top.Height).Overlaps(Raylib.GetMouseX(), (.)(Raylib.GetMouseY() - Wheel)))
{ {
if(!top.OnClick(Raylib.GetMouseX(), Raylib.GetMouseY())) if (!top.OnClick(Raylib.GetMouseX(), Raylib.GetMouseY()))
{ {
Popups.Remove(top); _Popups.Remove(top);
top.OnClose(); //Any last words ? top.OnClose(); //Any last words ?
delete top; delete top;
} }
} }
else else
{ {
bool a = top is DropdownPopup; //TODO: Make this less horrible bool a = top is DropdownPopup; //TODO: Make this less horrible
Popups.Remove(top); _Popups.Remove(top);
top.OnClose(); //Any last words ? top.OnClose(); //Any last words ?
delete top; delete top;
if(!a) if (!a)
CurrentScreen.OnClick(Raylib.GetMouseX(), (.)(Raylib.GetMouseY()-App.Wheel)); //So that we dont eat any inputs CurrentScreen.OnClick(Raylib.GetMouseX(), (.)(Raylib.GetMouseY() - App.Wheel)); //So that we dont eat any inputs
} }
} }
else else
CurrentScreen.OnClick(Raylib.GetMouseX(), (.)(Raylib.GetMouseY()-App.Wheel)); CurrentScreen.OnClick(Raylib.GetMouseX(), (.)(Raylib.GetMouseY() - App.Wheel));
} }
private static bool HandleButtonDown() private static bool HandleButtonDown()
{ {
//Topmost first //Topmost first
for(var i in Popups.Reversed) for (var i in _Popups.Reversed)
{ {
var hoverResult = i.OnDown(Raylib.GetMouseX(), Raylib.GetMouseY()-(.)Wheel); var hoverResult = i.OnDown(Raylib.GetMouseX(), Raylib.GetMouseY() - (.)Wheel);
if(hoverResult == false) if (hoverResult == false)
continue; continue;
return hoverResult; return hoverResult;
} }
return CurrentScreen.OnDown(Raylib.GetMouseX(), (.)(Raylib.GetMouseY()-App.Wheel)); return CurrentScreen.OnDown(Raylib.GetMouseX(), (.)(Raylib.GetMouseY() - App.Wheel));
} }
///Handles the hovering effect ///Handles the hovering effect
private static void HandleHover() private static void HandleHover()
{ {
Component hoverRes = HandleHoverPopups(); Component hoverRes = HandleHoverPopups();
if(hoverRes == null) if (hoverRes == null)
hoverRes = HandleHoverScreen(); hoverRes = HandleHoverScreen();
if(hoverRes == null) if (hoverRes == null)
Raylib.SetMouseCursor((.)MouseCursor.MOUSE_CURSOR_DEFAULT); Raylib.SetMouseCursor((.)MouseCursor.MOUSE_CURSOR_DEFAULT);
else else
{ {
if(hoverRes.Enabled) if (hoverRes.Enabled)
Raylib.SetMouseCursor((.)MouseCursor.MOUSE_CURSOR_POINTING_HAND); Raylib.SetMouseCursor((.)MouseCursor.MOUSE_CURSOR_POINTING_HAND);
if(oldPos != Mouse) if (_OldPos != Mouse)
movTime = Raylib.GetTime(); _MovTime = Raylib.GetTime();
if(Raylib.GetTime() - movTime >= 0.5) if (Raylib.GetTime() - _MovTime >= 0.5)
hoverText.Append(hoverRes.Description); _HoverText.Append(hoverRes.Description);
oldPos = Mouse; _OldPos = Mouse;
} }
} }
///Handle the hover effect for all screen objects ///Handle the hover effect for all screen objects
private static Component HandleHoverScreen() private static Component HandleHoverScreen()
{ {
return CurrentScreen.OnHover(Raylib.GetMouseX(), (.)(Raylib.GetMouseY()-App.Wheel)); return CurrentScreen.OnHover(Raylib.GetMouseX(), (.)(Raylib.GetMouseY() - App.Wheel));
} }
///Checks if any popup catches the hover ///Checks if any popup catches the hover
private static Component HandleHoverPopups() private static Component HandleHoverPopups()
{ {
//Topmost first //Topmost first
for(var i in Popups.Reversed) for (var i in _Popups.Reversed)
{ {
var hoverResult = i.OnHover(Raylib.GetMouseX(), Raylib.GetMouseY()-(.)Wheel); var hoverResult = i.OnHover(Raylib.GetMouseX(), Raylib.GetMouseY() - (.)Wheel);
if(hoverResult == null) if (hoverResult == null)
continue; continue;
return hoverResult; return hoverResult;
} }
return null; return null;
} }
} }

View file

@ -40,7 +40,7 @@ abstract class Button : Component
{ {
Sprite.Render(X,Y + soy, Tint); Sprite.Render(X,Y + soy, Tint);
var measure = Raylib.MeasureTextEx(Theme.Font, Label.ToScopeCStr!(), Theme.FontSize, 0); var measure = Raylib.MeasureTextEx(Theme.Font, Label.ToScopeCStr!(), Theme.FontSize, 0);
Raylib.DrawTextEx(Theme.Font, Label.ToScopeCStr!(), .(X+Width/2-measure.x/2,Y+Height/2-measure.y/2 + soy), Theme.FontSize, 0, Theme.Text); Raylib.DrawTextEx(Theme.Font, Label.ToScopeCStr!(), Vector2(X+Width/2-measure.x/2,Y+Height/2-measure.y/2 + soy), Theme.FontSize, 0, Theme.Text);
if(!Enabled) if(!Enabled)
{ {
Sprite.Render(X,Y + soy, Theme.DisabledTint); Sprite.Render(X,Y + soy, Theme.DisabledTint);

View file

@ -41,7 +41,7 @@ abstract class Checkbox : Component
else else
SpriteChecked.Render(X,Y + soy,Tint); SpriteChecked.Render(X,Y + soy,Tint);
var measure = Raylib.MeasureTextEx(Theme.Font, Label.ToScopeCStr!(), Theme.FontSize, 0); var measure = Raylib.MeasureTextEx(Theme.Font, Label.ToScopeCStr!(), Theme.FontSize, 0);
Raylib.DrawTextEx(Theme.Font, Label.ToScopeCStr!(), .(X + Sprite.Width + 2, (.)(Y + Sprite.Height/2 - 0.5*measure.y) + soy), Theme.FontSize, 0, Theme.Text); Raylib.DrawTextEx(Theme.Font, Label.ToScopeCStr!(), Vector2(X + Sprite.Width + 2, (.)(Y + Sprite.Height/2 - 0.5*measure.y) + soy), Theme.FontSize, 0, Theme.Text);
if(_IsHovered) if(_IsHovered)
Sprite.Render(X,Y + soy, HoverTint); Sprite.Render(X,Y + soy, HoverTint);
_IsHovered = false; _IsHovered = false;

View file

@ -103,4 +103,5 @@ abstract class Component
public abstract Component OnHover(int32 x, int32 y); public abstract Component OnHover(int32 x, int32 y);
public virtual void WhileSelected() { } public virtual void WhileSelected() { }
} }

View file

@ -48,9 +48,16 @@ class Container : Component
if(e is Container) if(e is Container)
{ {
((Container)e).Reorder(w); ((Container)e).Reorder(w);
if(x+e.Width+e.MarginLeft > w-MarginLeft) //Change both instances of padding to 2*Padding to ensure proper padding on the leftmost side of the screen
{ //Automatic row break
x = 0;
y = y + rowHeight;
rowHeight = 0;
}
MoveChildrenRecursive((Container)e, x, y); MoveChildrenRecursive((Container)e, x, y);
} }
if(e is Toolbar) if(e is Toolbar)
e.Width = App.Width; e.Width = App.Width;

View file

@ -20,8 +20,8 @@ abstract class Dropdown : Component
public override void Render(int32 soy) public override void Render(int32 soy)
{ {
Sprite.Render(X,Y + soy, Tint); Sprite.Render(X,Y + soy, Tint);
var measure = Raylib.MeasureTextEx(Theme.Font, Entries[SelectedEntry], Theme.FontSize, 0); var measure = Raylib.MeasureTextEx(Theme.Font, Entries[(.)SelectedEntry], Theme.FontSize, 0);
Raylib.DrawTextEx(Theme.Font, Entries[SelectedEntry], .(X+Width/2-measure.x/2,Y+Height/2-measure.y/2 + soy), Theme.FontSize, 0, Theme.Text); Raylib.DrawTextEx(Theme.Font, Entries[(.)SelectedEntry], Vector2(X+Width/2-measure.x/2,Y+Height/2-measure.y/2 + soy), Theme.FontSize, 0, Theme.Text);
if(!Enabled) if(!Enabled)
{ {
Sprite.Render(X,Y + soy, Theme.DisabledTint); Sprite.Render(X,Y + soy, Theme.DisabledTint);

View file

@ -40,21 +40,21 @@ class DropdownPopup : Popup
Raylib.DrawTextureNPatch( Raylib.DrawTextureNPatch(
*Sprite.Source, *Sprite.Source,
PatchInfo, PatchInfo,
.(X, Y + soy, Width, Height), Rectangle(X, Y + soy, Width, Height),
.(0,0), Vector2(0,0),
0, 0,
Tint); Tint);
int32 y = 5; int32 y = 5;
for(var i in Options) for(var i in Options)
{ {
Raylib.DrawTextEx(Theme.Font, scope String(i), .(X + 5, Y + y + soy), Theme.FontSize, 0, Theme.Text); Raylib.DrawTextEx(Theme.Font, scope String(i), Vector2(X + 5, Y + y + soy), Theme.FontSize, 0, Theme.Text);
if(@i.Index == SelectedItem) if(@i.Index == SelectedItem)
{ {
Raylib.DrawTextureNPatch( Raylib.DrawTextureNPatch(
*Sprite.Source, *Sprite.Source,
PatchInfo, PatchInfo,
.(X, Y + y - 4 + soy, Width, Theme.FontSize+10), Rectangle(X, Y + y - 4 + soy, Width, Theme.FontSize+10),
.(0,0), Vector2(0,0),
0, 0,
HoverTint); HoverTint);
} }

View file

@ -19,7 +19,7 @@ class Label : Component
public override void Render(int32 soy) public override void Render(int32 soy)
{ {
Raylib.DrawTextEx(Theme.FontLarge, Label.Ptr, .(X,Y + soy), Theme.FontSizeLarge, 0, Theme.Text); Raylib.DrawTextEx(Theme.FontLarge, Label.Ptr, Vector2(X,Y + soy), Theme.FontSizeLarge, 0, Theme.Text);
Raylib.DrawLine(X,Y + (.)_Measure.y + soy,X + (.)_Measure.x, Y + (.)_Measure.y + soy, Theme.Text); Raylib.DrawLine(X,Y + (.)_Measure.y + soy,X + (.)_Measure.x, Y + (.)_Measure.y + soy, Theme.Text);
} }
} }

View file

@ -16,7 +16,7 @@ abstract class LargeButton : Button
{ {
Sprite.Render(X,Y + soy, Tint); Sprite.Render(X,Y + soy, Tint);
var measure = Raylib.MeasureTextEx(Theme.Font, Label.Ptr, Theme.FontSize, 0); var measure = Raylib.MeasureTextEx(Theme.Font, Label.Ptr, Theme.FontSize, 0);
Raylib.DrawTextEx(Theme.Font, Label.Ptr, .(X+Width/2-measure.x/2,Y+Height/2-measure.y/2 + soy), Theme.FontSize, 0, Theme.Text); Raylib.DrawTextEx(Theme.Font, Label.Ptr, Vector2(X+Width/2-measure.x/2,Y+Height/2-measure.y/2 + soy), Theme.FontSize, 0, Theme.Text);
if(_IsHovered) if(_IsHovered)
Sprite.Render(X,Y + soy, HoverTint); Sprite.Render(X,Y + soy, HoverTint);
_IsHovered = false; _IsHovered = false;

View file

@ -22,21 +22,21 @@ abstract class NButton : Button
Raylib.DrawTextureNPatch( Raylib.DrawTextureNPatch(
*Sprite.Source, *Sprite.Source,
PatchInfo, PatchInfo,
.(X, Y + soy, Width, Height), Rectangle(X, Y + soy, Width, Height),
.(0,0), Vector2(0,0),
0, 0,
Tint); Tint);
var measure = Raylib.MeasureTextEx(Theme.Font, Label.ToScopeCStr!(), Theme.FontSize, 0); var measure = Raylib.MeasureTextEx(Theme.Font, Label.ToScopeCStr!(), Theme.FontSize, 0);
Raylib.DrawTextEx(Theme.Font, Label.ToScopeCStr!(), .(X+Width/2-measure.x/2,Y+Height/2-measure.y/2 + soy), Theme.FontSize, 0, Theme.Text); Raylib.DrawTextEx(Theme.Font, Label.ToScopeCStr!(), Vector2(X+Width/2-measure.x/2,Y+Height/2-measure.y/2 + soy), Theme.FontSize, 0, Theme.Text);
if(!Enabled) if(!Enabled)
{ {
Raylib.DrawTextureNPatch( Raylib.DrawTextureNPatch(
*Sprite.Source, *Sprite.Source,
PatchInfo, PatchInfo,
.(X, Y + soy, Width, Height), Rectangle(X, Y + soy, Width, Height),
.(0,0), Vector2(0,0),
0, 0,
Theme.DisabledTint); Theme.DisabledTint);
} }
@ -46,8 +46,8 @@ abstract class NButton : Button
Raylib.DrawTextureNPatch( Raylib.DrawTextureNPatch(
*Sprite.Source, *Sprite.Source,
PatchInfo, PatchInfo,
.(X, Y + soy, Width, Height), Rectangle(X, Y + soy, Width, Height),
.(0,0), Vector2(0,0),
0, 0,
HoverTint); HoverTint);
} }

View file

@ -44,21 +44,21 @@ class RightClickPopup : Popup
Raylib.DrawTextureNPatch( Raylib.DrawTextureNPatch(
*Sprite.Source, *Sprite.Source,
PatchInfo, PatchInfo,
.(X, Y + soy, Width, Height), Rectangle(X, Y + soy, Width, Height),
.(0,0), Vector2(0,0),
0, 0,
Tint); Tint);
int32 y = 5; int32 y = 5;
for(var i in Category.Items) for(var i in Category.Items)
{ {
Raylib.DrawTextEx(Theme.Font, scope String(i.Name), .(X + 5, Y + y + soy), Theme.FontSize, 0, Theme.Text); Raylib.DrawTextEx(Theme.Font, scope String(i.Name), Vector2(X + 5, Y + y + soy), Theme.FontSize, 0, Theme.Text);
if(SelectedItem == i) if(SelectedItem == i)
{ {
Raylib.DrawTextureNPatch( Raylib.DrawTextureNPatch(
*Sprite.Source, *Sprite.Source,
PatchInfo, PatchInfo,
.(X, Y + y - 5 + soy, Width, i.NameMeasurement.y+10), Rectangle(X, Y + y - 5 + soy, Width, i.NameMeasurement.y+10),
.(0,0), Vector2(0,0),
0, 0,
HoverTint); HoverTint);
} }

View file

@ -15,9 +15,6 @@ class ScrollableContainer : Container
} }
private List<Component> _LayoutData = new .() ~ delete _; private List<Component> _LayoutData = new .() ~ delete _;
///Recalculate the layout of all entries ///Recalculate the layout of all entries
public override void Reorder(int32 w) public override void Reorder(int32 w)
{ {
@ -63,7 +60,6 @@ class ScrollableContainer : Container
y = y + rowHeight; y = y + rowHeight;
rowHeight = 0; rowHeight = 0;
} }
e.[Friend]X = x + e.MarginLeft; e.[Friend]X = x + e.MarginLeft;
x = x + e.Width + e.MarginLeft + e.MarginRight; x = x + e.Width + e.MarginLeft + e.MarginRight;
e.[Friend]Y = y + e.MarginTop; e.[Friend]Y = y + e.MarginTop;
@ -72,6 +68,7 @@ class ScrollableContainer : Container
if(rowHeight < e.Height+e.MarginTop+e.MarginBottom) if(rowHeight < e.Height+e.MarginTop+e.MarginBottom)
rowHeight = e.Height+e.MarginTop+e.MarginBottom; rowHeight = e.Height+e.MarginTop+e.MarginBottom;
} }
Width = maxWidth + MarginLeft + MarginRight; Width = maxWidth + MarginLeft + MarginRight;
@ -135,7 +132,7 @@ class ScrollableContainer : Container
public override void Render(int32 soy) public override void Render(int32 soy)
{ {
Raylib.BeginScissorMode(X, Y + soy, Width, ContainerHeight); Raylib.BeginScissorMode(X, Y + soy, Width, Height);
for(var i in Children) for(var i in Children)
i.Render((.)(soy + Scroll)); i.Render((.)(soy + Scroll));
Raylib.EndScissorMode(); Raylib.EndScissorMode();
@ -145,7 +142,7 @@ class ScrollableContainer : Container
{ {
for(var e in Children) for(var e in Children)
{ {
if(RaylibBeef.Rectangle(e.X, e.Y - Scroll, e.Width, e.Height).Overlaps(x, y)) if(RaylibBeef.Rectangle(e.X, e.Y, e.Width, e.Height).Overlaps(x, (.)(y - Scroll)))
return e.OnClick(x, (.)(y - Scroll)); return e.OnClick(x, (.)(y - Scroll));
} }
return false; return false;
@ -155,8 +152,8 @@ class ScrollableContainer : Container
{ {
for(var e in Children) for(var e in Children)
{ {
if(RaylibBeef.Rectangle(e.X, e.Y, e.Width, e.Height).Overlaps(x, y)) if(RaylibBeef.Rectangle(e.X, e.Y, e.Width, e.Height).Overlaps(x, (.)(y - Scroll)))
return e.OnDown(x, y); return e.OnDown(x, (.)(y - Scroll));
} }
return false; return false;
} }
@ -165,7 +162,7 @@ class ScrollableContainer : Container
{ {
for(var e in Children) for(var e in Children)
{ {
if(RaylibBeef.Rectangle(e.X, e.Y - Scroll, e.Width, e.Height).Overlaps(x, y)) if(RaylibBeef.Rectangle(e.X, e.Y, e.Width, e.Height).Overlaps(x, (.)(y - Scroll)))
return e.OnHover(x, (.)(y - Scroll)); return e.OnHover(x, (.)(y - Scroll));
} }
return null; return null;
@ -175,8 +172,8 @@ class ScrollableContainer : Container
{ {
for(var e in Children) for(var e in Children)
{ {
if(RaylibBeef.Rectangle(e.X, e.Y, e.Width, e.Height).Overlaps(x, y)) if(RaylibBeef.Rectangle(e.X, e.Y, e.Width, e.Height).Overlaps(x, (.)(y - Scroll)))
e.OnRightClick(x, y, items); e.OnRightClick(x, (.)(y - Scroll), items);
} }
} }
@ -184,11 +181,11 @@ class ScrollableContainer : Container
{ {
for(var e in Children) for(var e in Children)
{ {
if(RaylibBeef.Rectangle(e.X, e.Y, e.Width, e.Height).Overlaps(x, y)) if(RaylibBeef.Rectangle(e.X, e.Y, e.Width, e.Height).Overlaps(x, (.)(y - Scroll)))
if(e.HandleScrollEvent(scroll, x, y)) if(e.HandleScrollEvent(scroll, x, (.)(y - Scroll)))
return true; return true;
} }
//Do our own rendering
Scroll += scroll; Scroll += scroll;
Scroll = Math.Clamp(Scroll,-(Height-ContainerHeight),0); Scroll = Math.Clamp(Scroll,-(Height-ContainerHeight),0);
return true; return true;

View file

@ -23,22 +23,22 @@ abstract class Toolbar : Component
Raylib.DrawTextureNPatch( Raylib.DrawTextureNPatch(
*Sprite.Source, *Sprite.Source,
PatchInfo, PatchInfo,
.(X, Y + soy, Width, Height), Rectangle(X, Y + soy, Width, Height),
.(0,0), Vector2(0,0),
0, 0,
Tint); Tint);
int32 x = 5; int32 x = 5;
for(var i in Categories) for(var i in Categories)
{ {
Raylib.DrawTextEx(Theme.Font, scope String(scope $"{i.Name}"), .(X + x, Y + Height/2 - i.NameMeasurement.y/2 + soy), Theme.FontSize, 0, Theme.Text); Raylib.DrawTextEx(Theme.Font, scope String(scope $"{i.Name}"), Vector2(X + x, Y + Height/2 - i.NameMeasurement.y/2 + soy), Theme.FontSize, 0, Theme.Text);
if(i == _SelectedPopup) if(i == _SelectedPopup)
{ {
//5 padding in every direction //5 padding in every direction
Raylib.DrawTextureNPatch( Raylib.DrawTextureNPatch(
*Sprite.Source, *Sprite.Source,
PatchInfo, PatchInfo,
.(X + x-5, Y + soy, i.NameMeasurement.x+10, Height), Rectangle(X + x-5, Y + soy, i.NameMeasurement.x+10, Height),
.(0,0), Vector2(0,0),
0, 0,
HoverTint); HoverTint);
} }

View file

@ -40,21 +40,21 @@ class ToolbarPopup : Popup
Raylib.DrawTextureNPatch( Raylib.DrawTextureNPatch(
*Sprite.Source, *Sprite.Source,
PatchInfo, PatchInfo,
.(X, Y + soy, Width, Height), Rectangle(X, Y + soy, Width, Height),
.(0,0), Vector2(0,0),
0, 0,
Tint); Tint);
int32 y = 5; int32 y = 5;
for(var i in Category.Items) for(var i in Category.Items)
{ {
Raylib.DrawTextEx(Theme.Font, scope String(i.Name), .(X + 5 + 32, Y + y + soy), Theme.FontSize, 0, Theme.Text); Raylib.DrawTextEx(Theme.Font, scope String(i.Name), Vector2(X + 5 + 32, Y + y + soy), Theme.FontSize, 0, Theme.Text);
if(SelectedItem == i) if(SelectedItem == i)
{ {
Raylib.DrawTextureNPatch( Raylib.DrawTextureNPatch(
*Sprite.Source, *Sprite.Source,
PatchInfo, PatchInfo,
.(X, Y + y - 5 + soy, Width, i.NameMeasurement.y+10), Rectangle(X, Y + y - 5 + soy, Width, i.NameMeasurement.y+10),
.(0,0), Vector2(0,0),
0, 0,
HoverTint); HoverTint);
} }

View file

@ -32,3 +32,14 @@ namespace System
} }
} }
} }
namespace System
{
#if BF_PLATFORM_WASM
extension WebAssembly
{
[CLink, CallingConvention(.Stdcall)]
public static extern void emscripten_set_main_loop(function void() func, int32 fps, int32 simulateInfinteLoop);
}
#endif
}

17
src/Input.bf Normal file
View file

@ -0,0 +1,17 @@
namespace TheaterGui;
using System;
class Input
{
internal static void HandleScrolling(float pWheelMove)
{
var w = pWheelMove * pWheelMove * pWheelMove;
if (!App.CurrentScreen.HandleScrollEvent(w, (.)App.Mouse.x, (.)(App.Mouse.y - App.Wheel)) && App.CurrentScreen.Height - App.Height > 0)
{
App.Wheel += w;
App.Wheel = Math.Clamp(App.Wheel, -1 * (App.CurrentScreen.Height - App.Height), 0);
}
}
}

View file

@ -11,6 +11,10 @@ class Textures
public this() public this()
{ {
Theme.Font = Raylib.LoadFontFromMemory(".ttf", (.)&Theme.Din, Theme.Din.Count, Theme.FontSize, null, 256);
Theme.FontSmall = Raylib.LoadFontFromMemory(".ttf", (.)&Theme.Din, Theme.Din.Count, Theme.FontSizeSmall, null, 256);
Theme.FontLarge = Raylib.LoadFontFromMemory(".ttf", (.)&Theme.Din, Theme.Din.Count, Theme.FontSizeLarge, null, 256);
LoadAsset(Theme.Texture_Button, "button"); LoadAsset(Theme.Texture_Button, "button");
LoadAsset(Theme.Texture_NButton, "n_button"); LoadAsset(Theme.Texture_NButton, "n_button");
LoadAsset(Theme.Texture_SquareButton, "square_button"); LoadAsset(Theme.Texture_SquareButton, "square_button");
@ -58,8 +62,12 @@ class Textures
{ {
Raylib.BeginDrawing(); Raylib.BeginDrawing();
Raylib.BeginTextureMode(_Textures[@i.Index]); Raylib.BeginTextureMode(_Textures[@i.Index]);
#if BF_PLATFORM_WINDOWS || BF_PLATFORM_LINUX
var img = Raylib.LoadTextureFromImage((.)res.id); var img = Raylib.LoadTextureFromImage((.)res.id);
Raylib.DrawTexturePro(img, .(0, 0, img.width, -img.height), .((.)res.rc[0], 2048 - res.rc[1] - (.)res.rc[3], img.width, img.height), .(0, 0), 0, Raylib.WHITE); #elif BF_PLATFORM_WASM
var img = Raylib.LoadTextureFromImage((Image)res.id);
#endif
Raylib.DrawTexturePro(img, Rectangle(0, 0, img.width, -img.height), Rectangle((.)res.rc[0], 2048 - res.rc[1] - (.)res.rc[3], img.width, img.height), Vector2(0, 0), 0, Raylib.WHITE);
Raylib.EndTextureMode(); Raylib.EndTextureMode();
Raylib.EndDrawing(); Raylib.EndDrawing();
Raylib.UnloadTexture(img); Raylib.UnloadTexture(img);
@ -86,7 +94,7 @@ class Textures
{ {
public Node[2] childs = .(null, null); public Node[2] childs = .(null, null);
public uint64[4] rc = .(0, 0, 2048, 2048); //x,y, width, height public uint64[4] rc = .(0, 0, 2048, 2048); //x,y, width, height
public Image? id = null; public Image? id;
public Node Insert(Image toInsert) public Node Insert(Image toInsert)
{ {
@ -162,6 +170,6 @@ struct sprite
public void Render(float x, float y, Color color = Raylib.WHITE) public void Render(float x, float y, Color color = Raylib.WHITE)
{ {
Raylib.DrawTexturePro(*Source, SourceRect, .(x + Width / 2, y + Height / 2, Width, Height), .(Width / 2, Height / 2), Rotation, color); Raylib.DrawTexturePro(*Source, SourceRect, Rectangle(x + Width / 2, y + Height / 2, Width, Height), Vector2(Width / 2, Height / 2), Rotation, color);
} }
} }