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]
ConfigSelections = {raylib-beef = {Config = "StaticDebug"}}
[Configs.Debug.wasm32]
AllocType = "CRT"
EnableObjectDebugFlags = false
EmitObjectAccessCheck = false
[Configs.Release.Win64]
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;
using TheaterGui.Components;
using System;
using System.Collections;
using RaylibBeef;
using internal TheaterGui;
using TheaterGui.Components;
class App
{
//All loaded textures
private static List<Popup> Popups = new .() ~ DeleteContainerAndItems!(_);
/*
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.
Components are supposed to be created via inheritance for each individual component, except some very simple exeptions (Labels, Placeholders)
*/
#region Fields
//For hover items
private static Vector2 oldPos = .(0,0);
private static double movTime = 0;
private static String hoverText = new .() ~ delete _;
private static List<Popup> _Popups = new .() ~ DeleteContainerAndItems!(_);
private static Vector2 _OldPos = .(0, 0);
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 bool AllowReorder = true;
private static Screen _CurrentScreen = null;
private static Screen _CurrentScreen = null ~ delete _;
public static Screen CurrentScreen
{
get => _CurrentScreen;
set
{
if(_CurrentScreen != null)
if (_CurrentScreen != null)
delete _CurrentScreen;
_CurrentScreen = value;
}
};
///Window width
public static int32 Width
{
@ -39,6 +53,7 @@ class App
set => Raylib.SetWindowSize(value, Raylib.GetRenderHeight());
}
///Window height
public static int32 Height
{
@ -46,12 +61,14 @@ class App
set => Raylib.SetWindowSize(Raylib.GetRenderWidth(), value);
}
///Mouse position
public static Vector2 Mouse
{
get => Raylib.GetMousePosition();
}
//Mouse wheel offset
public static float Wheel
{
@ -59,223 +76,285 @@ class App
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();
}
///Initialize the TheaterGui app
public static void Initialize(StringView pAppTitle = "TheaterApp")
///Initializes the raylib enviroment
///@param pName Name of the window
///@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
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.SetTargetFPS(40);
Raylib.SetWindowMinSize(640,360);
#if !BF_PLATFORM_WASM ///Otherwise raylib sleeps and delays browser responsiveness
Raylib.SetTargetFPS(40); //Should be a resonable framerate for gui apps
#endif
Raylib.SetWindowMinSize(640, 360);
///Set the default window icon
var icon = Raylib.LoadImageFromMemory(".png", (.)&Theme.Texture_WindowIcon, Theme.Texture_WindowIcon.Count);
Raylib.SetWindowIcon(icon);
Raylib.UnloadImage(icon);
}
//Load textures
///Initialize the gui enviroment
public static void InitializeGui<T>() where T : Screen
{
Textures = new .();
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);
CurrentScreen = new T();
}
///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()
{
Vector2 newSize = .(Width, Height);
if (_OldSize != newSize)
{
if(oldSize != .(Width,Height))
{
CurrentScreen.Reorder(Width);
oldSize = .(Width,Math.Min(Height, CurrentScreen.Height));
}
CurrentScreen.Reorder((.)newSize.x);
_OldSize = newSize;
}
//This could probably be solved better
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;
Input.HandleScrolling(Raylib.GetMouseWheelMove());
if(Raylib.IsMouseButtonPressed(0))
HandleLeftClick();
else if(Raylib.IsMouseButtonDown(0))
HandleButtonDown();
else if(Raylib.IsMouseButtonPressed(1))
if (Raylib.IsMouseButtonPressed(0))
HandleLeftClick();
else if (Raylib.IsMouseButtonDown(0))
HandleButtonDown();
else if (Raylib.IsMouseButtonPressed(1))
{
if (_Popups.Count > 0)
{
if(Popups.Count > 0)
var top = _Popups[_Popups.Count - 1];
if (top is RightClickPopup)
{
var top = Popups[Popups.Count-1];
if(top is RightClickPopup)
{
Popups.Remove(top);
delete top;
}
_Popups.Remove(top);
delete top;
}
Toolbar.ToolbarCategory popupCat = new .("Items");
CurrentScreen.OnRightClick((.)Mouse.x, (.)Mouse.y, popupCat);
if(popupCat.Items.Count > 0)
Popups.Add(new RightClickPopup((.)Mouse.x, (.)Mouse.y, popupCat));
else
delete popupCat;
}
Toolbar.ToolbarCategory popupCat = new .("Items");
CurrentScreen.OnRightClick((.)Mouse.x, (.)Mouse.y, popupCat);
if (popupCat.Items.Count > 0)
_Popups.Add(new RightClickPopup((.)Mouse.x, (.)Mouse.y, popupCat));
else
HandleHover();
//Drawing logic
Raylib.BeginDrawing();
Raylib.ClearBackground(Theme.Background);
delete popupCat;
}
else
HandleHover();
}
CurrentScreen.Render((.)Wheel);
for(var i in Popups)
i.Render((.)Wheel);
///Draw the current state of the application
public static void DrawFrame()
{
//Drawing logic
CurrentScreen.Render((.)Wheel);
if(hoverText != String.Empty)
{ //TODO: When you move outside of the window, the hover fucks up
int32 yOffset = 0;
int32 xOffset = 0;
var measure = Raylib.MeasureTextEx(Theme.FontSmall, hoverText, Theme.FontSizeSmall, 0);
if(Raylib.GetMouseX() < Width/2)
xOffset = 15;
else
xOffset = (.)(-1 * measure.x)-15;
if(Raylib.GetMouseY() < Height/2)
yOffset = 0;
else
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));
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, .(xOffset,yOffset)), Theme.FontSizeSmall, 0, Raylib.BLACK);
}
for (var i in _Popups)
i.Render((.)Wheel);
Raylib.EndTextureMode();
Raylib.EndDrawing();
if(hoverText != String.Empty)
hoverText.Clear();
if (!_HoverText.IsEmpty)
{
RenderHoverText();
_HoverText.Clear();
}
}
private static void RenderHoverText()
{
int32 yOffset = 0;
int32 xOffset = 0;
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;
else //Render the textbox to the left of the cursor
xOffset = (.)(-1 * measure.x) - 15;
if (Mouse.y < Height / 2) //Render the textbox at the y location of the cursor
yOffset = 0;
else //Render the textbox offset so, that the textbox y ends at the y location of the cursor
yOffset = (.)(-1 * measure.y);
//BoxShadow
//Box
//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);
}
public static void ForceReorder()
{
if (AllowReorder && CurrentScreen != null)
CurrentScreen.Reorder(Width);
}
public static void OpenPopup(Popup popup)
{
_Popups.Add(popup);
}
///Handles the leftclick action
private static void HandleLeftClick()
{
if(Popups.Count > 0)
if (_Popups.Count > 0)
{ //Only checking the topmost popup
var top = Popups[Popups.Count-1];
if(Rectangle(top.X, top.Y, top.Width, top.Height).Overlaps(Raylib.GetMouseX(), (.)(Raylib.GetMouseY()-Wheel)))
var top = _Popups[_Popups.Count - 1];
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 ?
delete top;
}
}
}
else
{
bool a = top is DropdownPopup; //TODO: Make this less horrible
Popups.Remove(top);
_Popups.Remove(top);
top.OnClose(); //Any last words ?
delete top;
if(!a)
CurrentScreen.OnClick(Raylib.GetMouseX(), (.)(Raylib.GetMouseY()-App.Wheel)); //So that we dont eat any inputs
if (!a)
CurrentScreen.OnClick(Raylib.GetMouseX(), (.)(Raylib.GetMouseY() - App.Wheel)); //So that we dont eat any inputs
}
}
else
CurrentScreen.OnClick(Raylib.GetMouseX(), (.)(Raylib.GetMouseY()-App.Wheel));
CurrentScreen.OnClick(Raylib.GetMouseX(), (.)(Raylib.GetMouseY() - App.Wheel));
}
private static bool HandleButtonDown()
{
//Topmost first
for(var i in Popups.Reversed)
for (var i in _Popups.Reversed)
{
var hoverResult = i.OnDown(Raylib.GetMouseX(), Raylib.GetMouseY()-(.)Wheel);
if(hoverResult == false)
continue;
return hoverResult;
var hoverResult = i.OnDown(Raylib.GetMouseX(), Raylib.GetMouseY() - (.)Wheel);
if (hoverResult == false)
continue;
return hoverResult;
}
return CurrentScreen.OnDown(Raylib.GetMouseX(), (.)(Raylib.GetMouseY()-App.Wheel));
return CurrentScreen.OnDown(Raylib.GetMouseX(), (.)(Raylib.GetMouseY() - App.Wheel));
}
///Handles the hovering effect
private static void HandleHover()
{
Component hoverRes = HandleHoverPopups();
if(hoverRes == null)
if (hoverRes == null)
hoverRes = HandleHoverScreen();
if(hoverRes == null)
if (hoverRes == null)
Raylib.SetMouseCursor((.)MouseCursor.MOUSE_CURSOR_DEFAULT);
else
{
if(hoverRes.Enabled)
if (hoverRes.Enabled)
Raylib.SetMouseCursor((.)MouseCursor.MOUSE_CURSOR_POINTING_HAND);
if(oldPos != Mouse)
movTime = Raylib.GetTime();
if(Raylib.GetTime() - movTime >= 0.5)
hoverText.Append(hoverRes.Description);
oldPos = Mouse;
if (_OldPos != Mouse)
_MovTime = Raylib.GetTime();
if (Raylib.GetTime() - _MovTime >= 0.5)
_HoverText.Append(hoverRes.Description);
_OldPos = Mouse;
}
}
///Handle the hover effect for all screen objects
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
private static Component HandleHoverPopups()
{
//Topmost first
for(var i in Popups.Reversed)
for (var i in _Popups.Reversed)
{
var hoverResult = i.OnHover(Raylib.GetMouseX(), Raylib.GetMouseY()-(.)Wheel);
if(hoverResult == null)
continue;
return hoverResult;
var hoverResult = i.OnHover(Raylib.GetMouseX(), Raylib.GetMouseY() - (.)Wheel);
if (hoverResult == null)
continue;
return hoverResult;
}
return null;
}
}

View file

@ -40,7 +40,7 @@ abstract class Button : Component
{
Sprite.Render(X,Y + soy, Tint);
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)
{
Sprite.Render(X,Y + soy, Theme.DisabledTint);

View file

@ -41,7 +41,7 @@ abstract class Checkbox : Component
else
SpriteChecked.Render(X,Y + soy,Tint);
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)
Sprite.Render(X,Y + soy, HoverTint);
_IsHovered = false;

View file

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

View file

@ -48,9 +48,16 @@ class Container : Component
if(e is Container)
{
((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);
}
if(e is Toolbar)
e.Width = App.Width;

View file

@ -20,8 +20,8 @@ abstract class Dropdown : Component
public override void Render(int32 soy)
{
Sprite.Render(X,Y + soy, Tint);
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);
var measure = Raylib.MeasureTextEx(Theme.Font, Entries[(.)SelectedEntry], Theme.FontSize, 0);
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)
{
Sprite.Render(X,Y + soy, Theme.DisabledTint);

View file

@ -40,21 +40,21 @@ class DropdownPopup : Popup
Raylib.DrawTextureNPatch(
*Sprite.Source,
PatchInfo,
.(X, Y + soy, Width, Height),
.(0,0),
Rectangle(X, Y + soy, Width, Height),
Vector2(0,0),
0,
Tint);
int32 y = 5;
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)
{
Raylib.DrawTextureNPatch(
*Sprite.Source,
PatchInfo,
.(X, Y + y - 4 + soy, Width, Theme.FontSize+10),
.(0,0),
Rectangle(X, Y + y - 4 + soy, Width, Theme.FontSize+10),
Vector2(0,0),
0,
HoverTint);
}

View file

@ -19,7 +19,7 @@ class Label : Component
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);
}
}

View file

@ -16,7 +16,7 @@ abstract class LargeButton : Button
{
Sprite.Render(X,Y + soy, Tint);
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)
Sprite.Render(X,Y + soy, HoverTint);
_IsHovered = false;

View file

@ -22,21 +22,21 @@ abstract class NButton : Button
Raylib.DrawTextureNPatch(
*Sprite.Source,
PatchInfo,
.(X, Y + soy, Width, Height),
.(0,0),
Rectangle(X, Y + soy, Width, Height),
Vector2(0,0),
0,
Tint);
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)
{
Raylib.DrawTextureNPatch(
*Sprite.Source,
PatchInfo,
.(X, Y + soy, Width, Height),
.(0,0),
Rectangle(X, Y + soy, Width, Height),
Vector2(0,0),
0,
Theme.DisabledTint);
}
@ -46,8 +46,8 @@ abstract class NButton : Button
Raylib.DrawTextureNPatch(
*Sprite.Source,
PatchInfo,
.(X, Y + soy, Width, Height),
.(0,0),
Rectangle(X, Y + soy, Width, Height),
Vector2(0,0),
0,
HoverTint);
}

View file

@ -44,21 +44,21 @@ class RightClickPopup : Popup
Raylib.DrawTextureNPatch(
*Sprite.Source,
PatchInfo,
.(X, Y + soy, Width, Height),
.(0,0),
Rectangle(X, Y + soy, Width, Height),
Vector2(0,0),
0,
Tint);
int32 y = 5;
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)
{
Raylib.DrawTextureNPatch(
*Sprite.Source,
PatchInfo,
.(X, Y + y - 5 + soy, Width, i.NameMeasurement.y+10),
.(0,0),
Rectangle(X, Y + y - 5 + soy, Width, i.NameMeasurement.y+10),
Vector2(0,0),
0,
HoverTint);
}

View file

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

View file

@ -23,22 +23,22 @@ abstract class Toolbar : Component
Raylib.DrawTextureNPatch(
*Sprite.Source,
PatchInfo,
.(X, Y + soy, Width, Height),
.(0,0),
Rectangle(X, Y + soy, Width, Height),
Vector2(0,0),
0,
Tint);
int32 x = 5;
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)
{
//5 padding in every direction
Raylib.DrawTextureNPatch(
*Sprite.Source,
PatchInfo,
.(X + x-5, Y + soy, i.NameMeasurement.x+10, Height),
.(0,0),
Rectangle(X + x-5, Y + soy, i.NameMeasurement.x+10, Height),
Vector2(0,0),
0,
HoverTint);
}

View file

@ -40,21 +40,21 @@ class ToolbarPopup : Popup
Raylib.DrawTextureNPatch(
*Sprite.Source,
PatchInfo,
.(X, Y + soy, Width, Height),
.(0,0),
Rectangle(X, Y + soy, Width, Height),
Vector2(0,0),
0,
Tint);
int32 y = 5;
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)
{
Raylib.DrawTextureNPatch(
*Sprite.Source,
PatchInfo,
.(X, Y + y - 5 + soy, Width, i.NameMeasurement.y+10),
.(0,0),
Rectangle(X, Y + y - 5 + soy, Width, i.NameMeasurement.y+10),
Vector2(0,0),
0,
HoverTint);
}

View file

@ -31,4 +31,15 @@ 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()
{
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_NButton, "n_button");
LoadAsset(Theme.Texture_SquareButton, "square_button");
@ -58,8 +62,12 @@ class Textures
{
Raylib.BeginDrawing();
Raylib.BeginTextureMode(_Textures[@i.Index]);
#if BF_PLATFORM_WINDOWS || BF_PLATFORM_LINUX
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.EndDrawing();
Raylib.UnloadTexture(img);
@ -86,7 +94,7 @@ class Textures
{
public Node[2] childs = .(null, null);
public uint64[4] rc = .(0, 0, 2048, 2048); //x,y, width, height
public Image? id = null;
public Image? id;
public Node Insert(Image toInsert)
{
@ -162,6 +170,6 @@ struct sprite
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);
}
}