add floating window example (#382)
* add floating window example A reusable floating window function. Window can be moved around through its title bar, minimized with its close button, resized from the icon in the lower right. The window is kept within the application area if the user pushes it outside the window/screen. The contents of the window are clipped with `BeginScissorMode` only if required and also a `GuiScrollPanel` enables user to see the clipped content of the window if current window size does not encapsulate all the content. * modify to add ability to create multiple windows * formatting for pointer dereference style consistency
This commit is contained in:
parent
623bc61f29
commit
82ba2b1a78
146
examples/floating_window/floating_window.c
Normal file
146
examples/floating_window/floating_window.c
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#define RAYGUI_IMPLEMENTATION
|
||||||
|
#include "../../raygui.h"
|
||||||
|
|
||||||
|
#include "../../styles/dark/style_dark.h"
|
||||||
|
|
||||||
|
static Vector2 window_position = { 10, 10 };
|
||||||
|
static Vector2 window_size = { 200, 400 };
|
||||||
|
static bool minimized = false;
|
||||||
|
static bool moving = false;
|
||||||
|
static bool resizing = false;
|
||||||
|
static Vector2 scroll;
|
||||||
|
|
||||||
|
static Vector2 window2_position = { 250, 10 };
|
||||||
|
static Vector2 window2_size = { 200, 400 };
|
||||||
|
static bool minimized2 = false;
|
||||||
|
static bool moving2 = false;
|
||||||
|
static bool resizing2 = false;
|
||||||
|
static Vector2 scroll2;
|
||||||
|
|
||||||
|
void GuiWindowFloating(Vector2 *position, Vector2 *size, bool *minimized, bool *moving, bool *resizing, void (*draw_content)(Vector2, Vector2), Vector2 content_size, Vector2 *scroll, const char* title) {
|
||||||
|
#if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT)
|
||||||
|
#define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(RAYGUI_WINDOW_CLOSEBUTTON_SIZE)
|
||||||
|
#define RAYGUI_WINDOW_CLOSEBUTTON_SIZE 18
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int close_title_size_delta_half = (RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_WINDOW_CLOSEBUTTON_SIZE) / 2;
|
||||||
|
|
||||||
|
// window movement and resize input and collision check
|
||||||
|
if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && !*moving && !*resizing) {
|
||||||
|
Vector2 mouse_position = GetMousePosition();
|
||||||
|
|
||||||
|
Rectangle title_collision_rect = { position->x, position->y, size->x - (RAYGUI_WINDOW_CLOSEBUTTON_SIZE + close_title_size_delta_half), RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT };
|
||||||
|
Rectangle resize_collision_rect = { position->x + size->x - 20, position->y + size->y - 20, 20, 20 };
|
||||||
|
|
||||||
|
if(CheckCollisionPointRec(mouse_position, title_collision_rect)) {
|
||||||
|
*moving = true;
|
||||||
|
} else if(!*minimized && CheckCollisionPointRec(mouse_position, resize_collision_rect)) {
|
||||||
|
*resizing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// window movement and resize update
|
||||||
|
if(*moving) {
|
||||||
|
Vector2 mouse_delta = GetMouseDelta();
|
||||||
|
position->x += mouse_delta.x;
|
||||||
|
position->y += mouse_delta.y;
|
||||||
|
|
||||||
|
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
|
||||||
|
*moving = false;
|
||||||
|
|
||||||
|
// clamp window position keep it inside the application area
|
||||||
|
if(position->x < 0) position->x = 0;
|
||||||
|
else if(position->x > GetScreenWidth() - size->x) position->x = GetScreenWidth() - size->x;
|
||||||
|
if(position->y < 0) position->y = 0;
|
||||||
|
else if(position->y > GetScreenHeight()) position->y = GetScreenHeight() - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if(*resizing) {
|
||||||
|
Vector2 mouse_delta = GetMouseDelta();
|
||||||
|
size->x += mouse_delta.x;
|
||||||
|
size->y += mouse_delta.y;
|
||||||
|
|
||||||
|
// clamp window size to an arbitrary minimum value and the window size as the maximum
|
||||||
|
if(size->x < 100) size->x = 100;
|
||||||
|
else if(size->x > GetScreenWidth()) size->x = GetScreenWidth();
|
||||||
|
if(size->y < 100) size->y = 100;
|
||||||
|
else if(size->y > GetScreenHeight()) size->y = GetScreenHeight();
|
||||||
|
|
||||||
|
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
|
||||||
|
*resizing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// window and content drawing with scissor and scroll area
|
||||||
|
if(*minimized) {
|
||||||
|
GuiStatusBar((Rectangle){ position->x, position->y, size->x, RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }, title);
|
||||||
|
|
||||||
|
if (GuiButton((Rectangle){ position->x + size->x - RAYGUI_WINDOW_CLOSEBUTTON_SIZE - close_title_size_delta_half,
|
||||||
|
position->y + close_title_size_delta_half,
|
||||||
|
RAYGUI_WINDOW_CLOSEBUTTON_SIZE,
|
||||||
|
RAYGUI_WINDOW_CLOSEBUTTON_SIZE },
|
||||||
|
"#120#")) {
|
||||||
|
*minimized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
*minimized = GuiWindowBox((Rectangle) { position->x, position->y, size->x, size->y }, title);
|
||||||
|
|
||||||
|
// scissor and draw content within a scroll panel
|
||||||
|
if(draw_content != NULL) {
|
||||||
|
Rectangle scissor = { 0 };
|
||||||
|
GuiScrollPanel((Rectangle) { position->x, position->y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, size->x, size->y - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT },
|
||||||
|
NULL,
|
||||||
|
(Rectangle) { position->x, position->y, content_size.x, content_size.y },
|
||||||
|
scroll,
|
||||||
|
&scissor);
|
||||||
|
|
||||||
|
bool require_scissor = size->x < content_size.x || size->y < content_size.y;
|
||||||
|
|
||||||
|
if(require_scissor) {
|
||||||
|
BeginScissorMode(scissor.x, scissor.y, scissor.width, scissor.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_content(*position, *scroll);
|
||||||
|
|
||||||
|
if(require_scissor) {
|
||||||
|
EndScissorMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the resize button/icon
|
||||||
|
GuiDrawIcon(71, position->x + size->x - 20, position->y + size->y - 20, 1, WHITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DrawContent(Vector2 position, Vector2 scroll) {
|
||||||
|
GuiButton((Rectangle) { position.x + 20 + scroll.x, position.y + 50 + scroll.y, 100, 25 }, "Button 1");
|
||||||
|
GuiButton((Rectangle) { position.x + 20 + scroll.x, position.y + 100 + scroll.y, 100, 25 }, "Button 2");
|
||||||
|
GuiButton((Rectangle) { position.x + 20 + scroll.x, position.y + 150 + scroll.y, 100, 25 }, "Button 3");
|
||||||
|
GuiLabel((Rectangle) { position.x + 20 + scroll.x, position.y + 200 + scroll.y, 250, 25 }, "A Label");
|
||||||
|
GuiLabel((Rectangle) { position.x + 20 + scroll.x, position.y + 250 + scroll.y, 250, 25 }, "Another Label");
|
||||||
|
GuiLabel((Rectangle) { position.x + 20 + scroll.x, position.y + 300 + scroll.y, 250, 25 }, "Yet Another Label");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
InitWindow(960, 560, "raygui - floating window example");
|
||||||
|
SetTargetFPS(60);
|
||||||
|
GuiLoadStyleDark();
|
||||||
|
|
||||||
|
while(!WindowShouldClose()) {
|
||||||
|
BeginDrawing();
|
||||||
|
ClearBackground(DARKGREEN);
|
||||||
|
GuiWindowFloating(&window_position, &window_size, &minimized, &moving, &resizing, &DrawContent, (Vector2) { 140, 320 }, &scroll, "Movable & Scalable Window");
|
||||||
|
GuiWindowFloating(&window2_position, &window2_size, &minimized2, &moving2, &resizing2, &DrawContent, (Vector2) { 140, 320 }, &scroll2, "Another window");
|
||||||
|
EndDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseWindow();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user