Files
biomed/GUI.cpp
2026-02-12 10:51:02 +01:00

942 lines
29 KiB
C++

#include "GUI.h"
#include "screen.h"
#include <SDL2/SDL_opengl.h>
#include "GUIDraw.h"
#include "font.h"
#include "GUIMouse.h"
#include "GUIKeyboard.h"
#include "GUIViewport.h"
#include "Model.h"
#include "renderer.h"
#include "Editor.h"
//#include "GUIDialogs.h"
#include "texture.h"
#include <stdlib.h>
const Color winBack{30, 30, 30, 255};
const Color panelBack{53, 53, 60, 255};
const Color panel3DBack{40, 40, 43, 255};
const Color textBoxBack{61, 61, 66, 255};
const Color textBoxBorder{76, 77, 81, 255};
const Color buttonBack{63, 63, 70, 255};
const Color buttonPressed{62, 153, 247, 255};
namespace GUI
{
Font* font {nullptr};
float viewPos{0};
Vector4 viewSize{0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
Vector4 viewStack[10];
char viewStackPos{0};
int focus{-1};
int id{0};
bool dot{false};
bool empty{false};
bool menuVisible {false};
Vector2 menuPos {0, 0};
int subMenu{-1};
Vector2 subMenuPos {0, 0};
bool comboBoxVisible {false};
int selectedViewport {0};
bool zoomed {false};
Color currentColor {0, 0, 0, 255};
float a = 6.5f;
float b = 12.0f;
float c = 24.0f;
void ResetFocus()
{
focus = -1;
dot = false;
empty = false;
menuVisible = false;
}
void StartSplitV(const float& value)
{
assert(viewStackPos < 10);
viewPos = 0;
viewStack[viewStackPos] = viewSize;
if (value > 0) {
viewStack[viewStackPos].w -= (value + 5);
viewSize.w = value;
} else {
viewStack[viewStackPos].w = -value;
viewSize.w -= (-value + 5);
}
viewStack[viewStackPos].y = viewSize.y + viewSize.w + 5;
viewStackPos++;
}
void StartSplitH(const float& value)
{
assert(viewStackPos < 10);
viewPos = 0;
viewStack[viewStackPos] = viewSize;
if (value > 0) {
viewStack[viewStackPos].z -= (value + 5);
viewSize.z = value;
} else {
viewStack[viewStackPos].z = -value;
viewSize.z -= (-value + 5);
}
viewStack[viewStackPos].x = viewSize.x + viewSize.z + 5;
viewStackPos++;
}
void NextSplit()
{
assert(viewStackPos > 0);
viewPos = 0;
viewStackPos--;
viewSize = viewStack[viewStackPos];
}
void DrawPanel()
{
viewPos = 0;
GUIDraw::FillRect(viewSize, panelBack);
viewSize.x += 10;
viewSize.y += 10;
viewSize.z -= 20;
viewSize.w -= 20;
}
void Draw3DPanel(const int index)
{
if (not menuVisible and GUIMouse::position.inside(viewSize.GetPosition(), viewSize.GetSize())) {
selectedViewport = index;
if (GUIKeyboard::key == SDLK_z) {
GUIKeyboard::key = SDLK_UNKNOWN;
zoomed = not zoomed;
}
}
const Color color = (index == selectedViewport ? Color(128, 0, 0, 255) : panel3DBack);
viewPos = 0;
GUIDraw::FillRect(viewSize, color);
viewSize.x += 5;
viewSize.y += 5;
viewSize.z -= 10;
viewSize.w -= 10;
}
void DrawTitle(const char* title)
{
viewPos = 0;
GUIDraw::FillRect({viewSize.x, viewSize.y, viewSize.z, 25}, winBack);
Vector2 textSize = font->GetSize(title);
const float pos = (viewSize.z-5) * 0.5f - textSize.x * 0.5f;
font->Print(viewSize.x+5+pos, viewSize.y+4, title);
viewSize.y += 30;
viewSize.w -= 30;
}
void DrawCaption(const char* title)
{
viewPos = 0;
font->Print(viewSize.x, viewSize.y, title);
viewSize.y += 20;
viewSize.w -= 20;
}
const bool DrawComboBox(char* text)
{
bool retVal = false;
Vector4 rect {viewPos+viewSize.x, viewSize.y, viewSize.z, 22};
Color backColor = textBoxBack;
if (text != nullptr and GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
retVal = true;
}
backColor = textBoxBorder;
}
GUIDraw::FillRect(rect, backColor);
GUIDraw::DrawRect(rect, textBoxBorder);
if (text != nullptr) font->Print(viewPos+viewSize.x+5, viewSize.y+2, text, 15);
viewPos = 0;
viewSize.y += 27;
viewSize.w -= 27;
return retVal;
}
void DrawTextBox(char* text)
{
Vector4 rect {viewPos+viewSize.x, viewSize.y, viewSize.z, 22};
Color backColor = textBoxBack;
if (text != nullptr and GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
focus = id;
}
backColor = textBoxBorder;
}
GUIDraw::FillRect(rect, backColor);
GUIDraw::DrawRect(rect, textBoxBorder);
if (text != nullptr) {
char textColor = 15;
if (focus == id) {
textColor = 11;
if (GUIKeyboard::key >= SDLK_SPACE and GUIKeyboard::key <= SDLK_z) {
const size_t len = strlen(text);
if (len < 9) {
text[len] = GUIKeyboard::key;
text[len+1] = '\0';
GUIKeyboard::key = SDLK_UNKNOWN;
}
} else if (GUIKeyboard::key == SDLK_BACKSPACE) {
GUIKeyboard::key = SDLK_UNKNOWN;
const size_t len = strlen(text);
if (len > 0) text[len-1] = '\0';
} else if (GUIKeyboard::key == SDLK_RETURN) {
GUIKeyboard::key = SDLK_UNKNOWN;
ResetFocus();
textColor = 15;
} else if (GUIKeyboard::key == SDLK_TAB) {
GUIKeyboard::key = SDLK_UNKNOWN;
focus++;
textColor = 15;
}
if (focus == id) {
const Vector2 size = font->GetSize(text);
font->Print(size.x+viewPos+viewSize.x+5, viewSize.y+2, "_", textColor);
}
}
font->Print(viewPos+viewSize.x+5, viewSize.y+2, text, textColor);
}
viewPos = 0;
viewSize.y += 27;
viewSize.w -= 27;
id++;
}
void DrawNumTextBox(float* number, const float size)
{
Vector4 rect {viewPos+viewSize.x, viewSize.y, size, 22};
Color backColor = textBoxBack;
if (number != nullptr and GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
dot = false;
empty = false;
focus = id;
}
backColor = textBoxBorder;
}
GUIDraw::FillRect(rect, backColor);
GUIDraw::DrawRect(rect, textBoxBorder);
if (number != nullptr) {
int i;
char s1[20];
char* s2;
//sprintf(text, "%.f", number);
sprintf(s1, "%f", *number);
s2 = strchr(s1, '.');
i = int(s2 - s1);
sprintf(s1, "%.*g", (i+2), *number);
char textColor = 15;
if (focus == id) {
textColor = 11;
if (dot) strcat(s1, ".");
if (empty) s1[0] = '\0';
const bool dotAlready = (strchr(s1, '.') != nullptr);
if (GUIKeyboard::key >= SDLK_0 and GUIKeyboard::key <= SDLK_9) {
if (not empty and s1[0] == '0' and not (strlen(s1)>1 and s1[1] == '.' )) s1[0] = '\0';
empty = false;
const size_t len = strlen(s1);
s1[len] = GUIKeyboard::key;
s1[len+1] = '\0';
GUIKeyboard::key = SDLK_UNKNOWN;
} else if (not dotAlready and GUIKeyboard::key == SDLK_PERIOD) {
empty = false;
const size_t len = strlen(s1);
s1[len] = GUIKeyboard::key;
s1[len+1] = '\0';
GUIKeyboard::key = SDLK_UNKNOWN;
} else if (GUIKeyboard::key == SDLK_BACKSPACE) {
GUIKeyboard::key = SDLK_UNKNOWN;
const size_t len = strlen(s1);
if (len == 1) empty = true;
s1[len-1] = '\0';
} else if (GUIKeyboard::key == SDLK_RIGHT) {
GUIKeyboard::key = SDLK_UNKNOWN;
(*number)++;
sprintf(s1, "%f", *number);
s2 = strchr(s1, '.');
i = int(s2 - s1);
sprintf(s1, "%.*g", (i+2), *number);
} else if (GUIKeyboard::key == SDLK_LEFT) {
GUIKeyboard::key = SDLK_UNKNOWN;
(*number)--;
sprintf(s1, "%f", *number);
s2 = strchr(s1, '.');
i = int(s2 - s1);
sprintf(s1, "%.*g", (i+2), *number);
} else if (GUIKeyboard::key == SDLK_RETURN) {
GUIKeyboard::key = SDLK_UNKNOWN;
ResetFocus();
textColor = 15;
const size_t len = strlen(s1);
if (s1[len-1] == '.') s1[len-1] = '\0';
} else if (GUIKeyboard::key == SDLK_TAB) {
GUIKeyboard::key = SDLK_UNKNOWN;
focus++;
textColor = 15;
const size_t len = strlen(s1);
if (s1[len-1] == '.') s1[len-1] = '\0';
}
if (focus == id) {
const size_t len = strlen(s1);
dot = (s1[len-1] == '.');
*number = atof(s1);
const Vector2 size = font->GetSize(s1);
font->Print(size.x+viewPos+viewSize.x+5, viewSize.y+2, "_", textColor);
}
}
font->Print(viewPos+viewSize.x+5, viewSize.y+2, s1, textColor);
}
int numElements = viewSize.z / size;
float separation = (viewSize.z - (size*numElements)) / (numElements-1);
viewPos += size+separation;
if (viewPos > viewSize.z) {
viewPos = 0;
viewSize.y += 27;
viewSize.w -= 27;
}
id++;
}
void DrawViewport(const int index)
{
glViewport(viewSize.x, SCREEN_HEIGHT-(viewSize.y+viewSize.w), viewSize.z, viewSize.w);
glEnable(GL_SCISSOR_TEST);
glScissor(viewSize.x, SCREEN_HEIGHT-(viewSize.y+viewSize.w), viewSize.z, viewSize.w);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
float zoom = viewports[index].zoom;
if (zoom < 0) zoom = 1.0f/-zoom;
const float x = (viewSize.z * 0.5f) / zoom;
const float y = (viewSize.w * 0.5f) / zoom;
glOrtho(-x, x, y, -y, 1000, -1000);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glTranslatef(viewports[index].offset.x, viewports[index].offset.y, 0);
glRotatef(viewports[index].rotation.x, 1, 0, 0);
glRotatef(viewports[index].rotation.y, 0, 1, 0);
if (not menuVisible and GUIMouse::position.inside(viewSize.GetPosition(), viewSize.GetSize())) {
if (GUIMouse::buttons[GUIMouse::Button::Right] == GUIMouse::ButtonState::Down) {
menuVisible = true;
menuPos = GUIMouse::position;
}
if (not GUIKeyboard::alt and GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
if (Editor::state == Editor::State::None) {
if (Editor::mode == Editor::Mode::Paint) {
if (viewports[index].renderMode == Viewport::RenderMode::UV) {
Renderer::SetState(RENDER_FILL);
Color color = model.PickPixel(GUIMouse::position.x, GUIMouse::position.y);
Editor::bitmap[(color.x*4)+color.y*128] = currentColor.r;
Editor::bitmap[(color.x*4)+1+color.y*128] = currentColor.g;
Editor::bitmap[(color.x*4)+2+color.y*128] = currentColor.b;
Editor::bitmap[(color.x*4)+3+color.y*128] = currentColor.a;
Texture::Update(Editor::texture, 32, 32, Editor::bitmap);
} else {
Renderer::SetState(RENDER_DEPTH | RENDER_FILL);
Color color = model.PickPaint(GUIMouse::position.x, GUIMouse::position.y);
Editor::bitmap[(color.y*4)+color.z*128] = currentColor.r;
Editor::bitmap[(color.y*4)+1+color.z*128] = currentColor.g;
Editor::bitmap[(color.y*4)+2+color.z*128] = currentColor.b;
Editor::bitmap[(color.y*4)+3+color.z*128] = currentColor.a;
Texture::Update(Editor::texture, 32, 32, Editor::bitmap);
}
} else {
Renderer::SetState(RENDER_DEPTH | RENDER_FILL);
Color color = model.Pick(GUIMouse::position.x, GUIMouse::position.y);
if (Editor::mode == Editor::Mode::Cube) {
model.SelectCube(color.r, GUIKeyboard::shift);
} else if (Editor::mode == Editor::Mode::Face) {
model.SelectFace(color.r, color.g, GUIKeyboard::shift);
}
}
}
ResetFocus();
}
if (GUIMouse::delta.x != 0 or GUIMouse::delta.y != 0) {
if (GUIKeyboard::alt or GUIMouse::buttons[GUIMouse::Button::Middle] == GUIMouse::ButtonState::Pressed) {
if (GUIKeyboard::shift) {
viewports[index].offset += GUIMouse::delta / viewports[index].zoom;
} else {
viewports[index].rotation += Vector2(GUIMouse::delta.y, -GUIMouse::delta.x)*1;
if (viewports[index].rotation.x < -90) viewports[index].rotation.x = -90;
if (viewports[index].rotation.x > 90) viewports[index].rotation.x = 90;
}
}
}
if (GUIMouse::wheel.x != 0 or GUIMouse::wheel.y != 0) {
if (GUIKeyboard::shift) {
viewports[index].offset += GUIMouse::wheel / viewports[index].zoom;
} else {
viewports[index].zoom -= GUIMouse::wheel.y;
}
}
}
glClearColor(float(panel3DBack.r)/255.0f, float(panel3DBack.g)/255.0f, float(panel3DBack.b)/255.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (viewports[index].renderMode == Viewport::RenderMode::Solid) {
Renderer::SetState(RENDER_DEPTH | RENDER_FILL);
if (viewports[index].light) Renderer::Light(ON);
model.DrawSolid();
} else if (viewports[index].renderMode == Viewport::RenderMode::Textured) {
Renderer::SetState(RENDER_DEPTH | RENDER_FILL | RENDER_TEXTURE);
if (viewports[index].light) Renderer::Light(ON);
glBindTexture(GL_TEXTURE_2D, Editor::texture);
model.DrawSolid();
} else if (viewports[index].renderMode == Viewport::RenderMode::Wire) {
Renderer::SetState(RENDER_DEPTH);
model.DrawWire();
} else if (viewports[index].renderMode == Viewport::RenderMode::UV) {
Renderer::SetState(RENDER_FILL | RENDER_TEXTURE);
glBindTexture(GL_TEXTURE_2D, Editor::texture);
model.DrawUV();
}
glDisable(GL_SCISSOR_TEST);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
}
const bool DrawButton(const char* text, const SDL_Keycode key, const bool state, const float size = 85)
{
Vector4 rect {viewPos+viewSize.x, viewSize.y, size, 22};
Color backColor = buttonBack;
Color borders[4] = {textBoxBorder, winBack, winBack, textBoxBorder};
bool retVal {false};
ivec2 textPadding {5,2};
if (state) {
backColor = textBoxBorder;
borders[0] = borders[3] = winBack;
borders[1] = borders[2] = textBoxBorder;
textPadding += {1,1};
}
if (GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Pressed) {
borders[0] = borders[3] = winBack;
borders[1] = borders[2] = textBoxBorder;
textPadding += {1,1};
}
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Up) {
borders[0] = borders[3] = winBack;
borders[1] = borders[2] = textBoxBorder;
textPadding += {1,1};
ResetFocus();
retVal = true;
}
backColor = textBoxBorder;
}
if (focus == -1 and key != SDLK_UNKNOWN and GUIKeyboard::key == key) {
ResetFocus();
retVal = true;
}
GUIDraw::FillRect({viewPos+viewSize.x, viewSize.y, size, 22}, backColor);
GUIDraw::DrawRect({viewPos+viewSize.x, viewSize.y, size, 22}, borders);
font->Print(viewPos+viewSize.x+textPadding.x, viewSize.y+textPadding.y, text, 15);
int numElements = viewSize.z / size;
float separation = (viewSize.z - (size*numElements)) / (numElements-1);
viewPos += size+separation;
if (viewPos > viewSize.z) {
viewPos = 0;
viewSize.y += 27;
viewSize.w -= 27;
}
//id++;
return retVal;
}
void DrawStaticTextBox(const char* text, const float size = 85)
{
Vector4 rect {viewPos+viewSize.x, viewSize.y, size, 22};
GUIDraw::FillRect(rect, textBoxBack);
GUIDraw::DrawRect(rect, textBoxBorder);
font->Print(viewPos+viewSize.x+5, viewSize.y+2, text, 7);
viewPos += size+10;
if (viewPos > viewSize.z) {
viewPos = 0;
viewSize.y += 27;
viewSize.w -= 27;
}
}
void DrawSpace(const int space)
{
viewPos = 0;
viewSize.y += space;
viewSize.w -= space;
}
void Reset()
{
if (font == nullptr) {
font = new Font();
font->Load("font");
}
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 100, -100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
viewStackPos = 0;
viewPos = 0;
viewSize = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
id = 0;
}
void DrawMenu(const int numItems, const float size)
{
viewSize = Vector4(menuPos.x, menuPos.y, size, 25*numItems);
if (menuPos.x+size > SCREEN_WIDTH) viewSize.x = SCREEN_WIDTH - size;
if (menuPos.y+25*numItems > SCREEN_HEIGHT) viewSize.y = SCREEN_HEIGHT - 25*numItems;
GUIDraw::FillRect(viewSize, panelBack);
GUIDraw::DrawRect(viewSize, winBack);
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
if (not GUIMouse::position.inside(viewSize.GetPosition(), viewSize.GetSize())) {
ResetFocus();
}
}
}
void DrawSubMenu(const int numItems, const float size)
{
viewSize = Vector4(subMenuPos.x, subMenuPos.y, size, 25*numItems);
if (subMenuPos.x+size > SCREEN_WIDTH) viewSize.x = subMenuPos.x - (size*2);
if (subMenuPos.y+25*numItems > SCREEN_HEIGHT) viewSize.y = SCREEN_HEIGHT - 25*numItems;
GUIDraw::FillRect(viewSize, panelBack);
GUIDraw::DrawRect(viewSize, winBack);
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
if (not GUIMouse::position.inside(viewSize.GetPosition(), viewSize.GetSize())) {
ResetFocus();
}
}
}
const bool DrawMenuItem(const char* text, const bool state)
{
bool retVal = false;
Vector4 rect {viewSize.x, viewSize.y, viewSize.z, 25};
if (GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
subMenu = -1;
GUIDraw::FillRect(rect, textBoxBack);
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
retVal = true;
menuVisible = false;
comboBoxVisible = false;
}
}
if (state) font->Print(viewSize.x+3, viewSize.y+2, "+", 15);
font->Print(viewSize.x+13, viewSize.y+2, text, 15);
viewSize.y += 25;
viewSize.w -= 25;
return retVal;
}
void DrawMenuSubItem(const char* text, const int subMenuIndex)
{
Vector4 rect {viewSize.x, viewSize.y, viewSize.z, 25};
if (GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
GUIDraw::FillRect(rect, textBoxBack);
subMenu = subMenuIndex;
subMenuPos = Vector2(viewSize.x+viewSize.z, viewSize.y);
} else if (subMenu == subMenuIndex) {
GUIDraw::FillRect(rect, textBoxBack);
}
font->Print(viewSize.x+viewSize.z-13, viewSize.y+2, ">", 15);
font->Print(viewSize.x+13, viewSize.y+2, text, 15);
viewSize.y += 25;
viewSize.w -= 25;
}
const bool DrawSubMenuItem(const char* text, const bool state)
{
bool retVal = false;
Vector4 rect {viewSize.x, viewSize.y, viewSize.z, 25};
if (GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
GUIDraw::FillRect(rect, textBoxBack);
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
retVal = true;
menuVisible = false;
}
}
if (state) font->Print(viewSize.x+3, viewSize.y+2, "+", 15);
font->Print(viewSize.x+13, viewSize.y+2, text, 15);
viewSize.y += 25;
viewSize.w -= 25;
return retVal;
}
Vector2 GetTransformedAxesUV(const float x, const float y)
{
Vector2 result {x, y};
if (Editor::forcedAxis == 0) result.y = 0;
else if (Editor::forcedAxis == 1) result.x = 0;
return result;
}
Vector3 GetTransformedAxes(const float x, const float y)
{
Vector3 result {0, 0, 0};
if (Editor::forcedAxis == 0) {
result.x = x + y;
result.y = 0;
result.z = 0;
} else if (Editor::forcedAxis == 1) {
result.x = 0;
result.y = x + y;
result.z = 0;
} else if (Editor::forcedAxis == 2) {
result.x = 0;
result.y = 0;
result.z = x + y;
} else {
float rx = viewports[selectedViewport].rotation.x; while (rx >= 360) rx -= 360; while (rx < 0) rx += 360;
float ry = viewports[selectedViewport].rotation.y; while (ry >= 360) ry -= 360; while (ry < 0) ry += 360;
if (rx <= 45 or rx >= 315 ) {
if (ry <= 45 or ry >= 315) {
// x, y
result.x = x;
result.y = y;
} else if (ry > 45 and ry < 135) {
// z, y
result.z = x;
result.y = y;
} else if (ry >= 135 and ry < 225) {
// -x, y
result.x = -x;
result.y = y;
} else {
// -z, y
result.z = -x;
result.y = y;
}
} else if (rx > 45 and rx < 180) {
if (ry <= 45 or ry >= 315) {
// x, -z
result.x = x;
result.z = -y;
} else if (ry > 45 and ry < 135) {
// z, x
result.z = x;
result.x = y;
} else if (ry >= 135 and ry < 225) {
// -x, z
result.x = -x;
result.z = y;
} else {
// -z, -x
result.z = -x;
result.x = -y;
}
} else {
if (ry <= 45 or ry >= 315) {
// x, z
result.x = x;
result.z = y;
} else if (ry > 45 and ry < 135) {
// -z, x
result.z = x;
result.x = -y;
} else if (ry >= 135 and ry < 225) {
// -x, -z
result.x = -x;
result.z = -y;
} else {
// z, -x
result.z = -x;
result.x = y;
}
}
}
return result;
}
void Draw()
{
if (Editor::state != Editor::State::None) {
if (Editor::mode == Editor::Mode::Face) {
if (GUIKeyboard::key == SDLK_x) { Editor::forcedAxis = 0; GUIKeyboard::key = SDLK_UNKNOWN; }
if (GUIKeyboard::key == SDLK_y) { Editor::forcedAxis = 1; GUIKeyboard::key = SDLK_UNKNOWN; }
if (GUIMouse::slowDelta.x != 0 or GUIMouse::slowDelta.y != 0) {
Vector2 axes = GetTransformedAxesUV(GUIMouse::slowDelta.x, GUIMouse::slowDelta.y);
if (Editor::state == Editor::State::Grab) model.GrabFaces(axes.x, axes.y);
if (Editor::state == Editor::State::Scale) model.ScaleFaces(axes.x, axes.y);
}
} else if (Editor::mode == Editor::Mode::Cube) {
if (GUIKeyboard::key == SDLK_x) { Editor::forcedAxis = 0; GUIKeyboard::key = SDLK_UNKNOWN; }
if (GUIKeyboard::key == SDLK_y) { Editor::forcedAxis = 1; GUIKeyboard::key = SDLK_UNKNOWN; }
if (GUIKeyboard::key == SDLK_z) { Editor::forcedAxis = 2; GUIKeyboard::key = SDLK_UNKNOWN; }
if (GUIMouse::slowDelta.x != 0 or GUIMouse::slowDelta.y != 0) {
Vector3 axes = GetTransformedAxes(GUIMouse::slowDelta.x, GUIMouse::slowDelta.y);
if (Editor::state == Editor::State::Grab) model.GrabCubes(axes.x, axes.y, axes.z);
if (Editor::state == Editor::State::Scale) model.ScaleCubes(axes.x, axes.y, axes.z);
}
}
}
Reset();
//model.cubes[0].selected = true;
StartSplitV(30); //TOOLBAR
DrawPanel();
NextSplit();
StartSplitV(-30);
StartSplitH(200);
// INFO PANEL
DrawPanel();
DrawTitle("State");
if (DrawButton("Cubes", SDLK_1, Editor::mode == Editor::Mode::Cube)) Editor::SetMode(Editor::Mode::Cube);
if (DrawButton("Faces", SDLK_2, Editor::mode == Editor::Mode::Face)) Editor::SetMode(Editor::Mode::Face);
if (DrawButton("Paint", SDLK_3, Editor::mode == Editor::Mode::Paint)) Editor::SetMode(Editor::Mode::Paint);
if (DrawButton("Anim", SDLK_4, Editor::mode == Editor::Mode::Anim)) Editor::SetMode(Editor::Mode::Anim);
DrawSpace(20);
if (Editor::mode == Editor::Mode::Cube) {
int index = model.GetSelectedCube();
DrawTitle("Cube Info");
DrawCaption("Name:");
DrawTextBox(index != -1 ? model.cubes[index].name : nullptr);
float* v[9] = {nullptr};
if (index != -1) {
v[0] = &model.cubes[index].position.x;
v[1] = &model.cubes[index].position.y;
v[2] = &model.cubes[index].position.z;
v[3] = &model.cubes[index].size.x;
v[4] = &model.cubes[index].size.y;
v[5] = &model.cubes[index].size.z;
v[6] = &model.cubes[index].pivot.x;
v[7] = &model.cubes[index].pivot.y;
v[8] = &model.cubes[index].pivot.z;
}
DrawCaption("Position:");
DrawNumTextBox(v[0], 50);
DrawNumTextBox(v[1], 50);
DrawNumTextBox(v[2], 50);
DrawCaption("Size:");
DrawNumTextBox(v[3], 50);
DrawNumTextBox(v[4], 50);
DrawNumTextBox(v[5], 50);
DrawCaption("Pivot:");
DrawNumTextBox(v[6], 50);
DrawNumTextBox(v[7], 50);
DrawNumTextBox(v[8], 50);
DrawCaption("Parent:");
char parent[10] = "<none>";
if (index != -1 and model.cubes[index].parent != -1) strcpy(parent, model.cubes[model.cubes[index].parent].name);
if (DrawComboBox(index != -1 ? parent : nullptr)) {
comboBoxVisible = not comboBoxVisible;
if (comboBoxVisible) {
subMenuPos.x = viewSize.z;
menuPos = {viewSize.x, viewSize.y};
}
}
DrawSpace(20);
DrawTitle("Cube Ops");
if (DrawButton("New", SDLK_n, false)) model.NewCube();
if (DrawButton("Delete", SDLK_BACKSPACE, false)) model.DeleteCube();
if (DrawButton("Dup", SDLK_d, false)) {
model.DupCube();
Editor::SetState(Editor::State::Grab);
}
if (DrawButton("Grab", SDLK_g, Editor::state == Editor::State::Grab)) Editor::SetState(Editor::State::Grab);
if (DrawButton("Scale", SDLK_s, Editor::state == Editor::State::Scale)) Editor::SetState(Editor::State::Scale);
if (DrawButton("Pivot", SDLK_p, Editor::state == Editor::State::Pivot)) Editor::SetState(Editor::State::Pivot);
} else if (Editor::mode == Editor::Mode::Face) {
DrawTitle("Face Info");
float* v[8] = {nullptr};
ivec2 index = model.GetSelectedFace();
if (index.x != -1) {
v[0] = &model.cubes[index.x].faces[index.y].uv[2].x;
v[1] = &model.cubes[index.x].faces[index.y].uv[2].y;
v[2] = &model.cubes[index.x].faces[index.y].uv[1].x;
v[3] = &model.cubes[index.x].faces[index.y].uv[1].y;
v[4] = &model.cubes[index.x].faces[index.y].uv[3].x;
v[5] = &model.cubes[index.x].faces[index.y].uv[3].y;
v[6] = &model.cubes[index.x].faces[index.y].uv[0].x;
v[7] = &model.cubes[index.x].faces[index.y].uv[0].y;
}
DrawCaption("UV:");
DrawNumTextBox(v[0], 42);
DrawNumTextBox(v[1], 42);
DrawNumTextBox(v[2], 42);
DrawNumTextBox(v[3], 42);
DrawNumTextBox(v[4], 42);
DrawNumTextBox(v[5], 42);
DrawNumTextBox(v[6], 42);
DrawNumTextBox(v[7], 42);
DrawSpace(20);
DrawTitle("Face Ops");
if (DrawButton("Clear", SDLK_c, false)) model.ClearFaces();
if (DrawButton("Rotate", SDLK_r, false)) model.RotateFaces();
if (DrawButton("FlipH", SDLK_h, false)) model.FlipHFaces();
if (DrawButton("FlipV", SDLK_v, false)) model.FlipVFaces();
if (DrawButton("Grab", SDLK_g, Editor::state == Editor::State::Grab)) Editor::SetState(Editor::State::Grab);
if (DrawButton("Scale", SDLK_s, Editor::state == Editor::State::Scale)) Editor::SetState(Editor::State::Scale);
}
DrawSpace(20);
DrawTitle("Texture");
char* shortPath = strrchr(Editor::textureFilename, '/')+1;
DrawStaticTextBox(shortPath, 145);
if (DrawButton("...", SDLK_UNKNOWN, false, 25)) {
char oldPath[400];
strcpy(oldPath, Editor::textureFilename);
const char* path = nullptr;//GUIDialogs::ChooseFile();
if (path != nullptr) {
strcpy(Editor::textureFilename, path);
//free(path);
uint8_t* data = Texture::Load(Editor::textureFilename);
if (data == nullptr) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "File is not a correct PNG!", nullptr);
strcpy(Editor::textureFilename, oldPath);
} else {
memcpy(Editor::bitmap, data, 32*32*4);
free(data);
Texture::Update(Editor::texture, 32, 32, Editor::bitmap);
}
}
}
NextSplit();
// 3D VIEWS
if (zoomed) {
Draw3DPanel(selectedViewport);
DrawViewport(selectedViewport);
} else {
StartSplitH(2.0f*viewSize.z/3.0f);
Draw3DPanel(0);
DrawViewport(0);
NextSplit();
StartSplitV(viewSize.w/2.0f);
Draw3DPanel(1);
DrawViewport(1);
NextSplit();
Draw3DPanel(2);
DrawViewport(2);
}
NextSplit();
// STATUS BAR
DrawPanel();
if (comboBoxVisible) {
int numItems = model.numCubes;
DrawMenu(numItems, subMenuPos.x);
int sel = model.GetSelectedCube();
for (int i = 0; i < model.numCubes; i++) {
if (i != sel and DrawMenuItem(model.cubes[i].name, model.cubes[sel].parent == i)) model.cubes[sel].parent = i;
}
if (DrawMenuItem("<none>", model.cubes[sel].parent == -1)) model.cubes[sel].parent = -1;
}
if (menuVisible) {
DrawMenu(6, 120);
DrawMenuSubItem("Render", 0);
DrawMenuSubItem("View", 1);
DrawMenuSubItem("Projection", 2);
if (DrawMenuItem("Light", viewports[selectedViewport].light)) viewports[selectedViewport].light = not viewports[selectedViewport].light;
if (DrawMenuItem("Grid", viewports[selectedViewport].grid)) viewports[selectedViewport].grid = not viewports[selectedViewport].grid;
if (DrawMenuItem("Zoomed", zoomed)) zoomed = not zoomed;
if (subMenu == 0) {
DrawSubMenu(4, 120);
if (DrawSubMenuItem("Wire", viewports[selectedViewport].renderMode == Viewport::RenderMode::Wire)) viewports[selectedViewport].renderMode = Viewport::RenderMode::Wire;
if (DrawSubMenuItem("Solid", viewports[selectedViewport].renderMode == Viewport::RenderMode::Solid)) viewports[selectedViewport].renderMode = Viewport::RenderMode::Solid;
if (DrawSubMenuItem("Textured", viewports[selectedViewport].renderMode == Viewport::RenderMode::Textured)) viewports[selectedViewport].renderMode = Viewport::RenderMode::Textured;
if (DrawSubMenuItem("UV", viewports[selectedViewport].renderMode == Viewport::RenderMode::UV)) viewports[selectedViewport].renderMode = Viewport::RenderMode::UV;
} else if (subMenu == 1) {
DrawSubMenu(6, 120);
if (DrawSubMenuItem("Front", viewports[selectedViewport].rotation.x == 0 and viewports[selectedViewport].rotation.y == 0)) {
viewports[selectedViewport].rotation.x = 0;
viewports[selectedViewport].rotation.y = 0;
}
DrawSubMenuItem("Left", false);
DrawSubMenuItem("Top", false);
DrawSubMenuItem("Back", false);
DrawSubMenuItem("Right", false);
DrawSubMenuItem("Bottom", false);
} else if (subMenu == 2) {
DrawSubMenu(2, 120);
DrawSubMenuItem("Orthogonal", true);
DrawSubMenuItem("Perspective", false);
}
}
if (Editor::state != Editor::State::None) {
if (GUIKeyboard::key == SDLK_RETURN) {
GUIKeyboard::key = SDLK_UNKNOWN;
Editor::SetState(Editor::State::None);
}
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
Editor::SetState(Editor::State::None);
}
}
}
}