942 lines
29 KiB
C++
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);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|