merged GUI elements into vb01

This commit is contained in:
devZoGok
2023-08-13 12:12:25 +03:00
parent 217fc53edd
commit a2472c8929
11 changed files with 929 additions and 0 deletions
+5
View File
@@ -7,6 +7,7 @@ set(BUILD_SHARED_LIBS OFF)
set(BUILD_TESTS OFF)
set(BUILD_SAMPLES OFF)
set(BUILD_WITH_ASSIMP OFF)
set(BUILD_GUI_ELEMENTS ON)
set(LIB_NAME vb01)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
@@ -25,6 +26,10 @@ if(BUILD_WITH_ASSIMP)
set(ASSET_READERS ${ASSET_READERS} assimpModelReader.cpp)
endif()
if(BUILD_GUI_ELEMENTS)
set(GUI ${GUI} button.cpp listbox.cpp textbox.cpp checkbox.cpp slider.cpp)
endif()
set(LIB_SRC ${RENDER} ${MATH} ${UTILS} ${GUI} ${ARMATURE} ${ASSET_MANAGER} ${ASSET_READERS} ${ANIM})
include_directories(external/tinydir)
+156
View File
@@ -0,0 +1,156 @@
#include <locale>
#include <codecvt>
#include <glfw3.h>
#include "root.h"
#include "quad.h"
#include "node.h"
#include "material.h"
#include "text.h"
#include "texture.h"
#include "util.h"
#include "button.h"
using namespace std;
using namespace vb01;
namespace vb01Gui{
Button::Button(Vector2 pos, Vector2 size, string name, string fontPath, int trigger, bool separate, string imagePath){
this->pos = pos;
this->size = size;
this->name = name;
this->separate = separate;
this->imagePath = imagePath;
this->trigger = trigger;
Root *root = Root::getSingleton();
guiNode = root->getGuiNode();
rect = new Quad(Vector3(size.x, size.y, 0), false);
rectNode = new Node(Vector3(pos.x, pos.y, 0));
Material *mat = new Material(root->getLibPath() + "gui");
if(imagePath == ""){
mat->addBoolUniform(texUni, false);
mat->addVec4Uniform(diffColUni, color);
}
else{
mat->addBoolUniform(texUni, true);
string frame[]{imagePath};
Texture *tex = new Texture(frame, 1, false);
mat->addTexUniform("diffuseMap", tex, false);
textures.push_back(tex);
}
rect->setMaterial(mat);
rectNode->attachMesh(rect);
guiNode->attachChild(rectNode);
if(separate){
text = new Text(fontPath, stringToWstring(name));
text->setScale(.2);
textNode = new Node(Vector3(pos.x, pos.y + size.y, - .1));
textNode->addText(text);
Material *textMat = new Material(root->getLibPath() + "text");
textMat->addBoolUniform(texUni, false);
textMat->addVec4Uniform(diffColUni, Vector4::VEC_IJKL);
text->setMaterial(textMat);
guiNode->attachChild(textNode);
}
initWindowSize[0] = Root::getSingleton()->getWidth();
initWindowSize[1] = Root::getSingleton()->getHeight();
}
Button::~Button(){
if(textNode){
guiNode->dettachChild(textNode);
delete textNode;
}
guiNode->dettachChild(rectNode);
delete rectNode;
}
void Button::update(){
int width, height;
GLFWwindow *window = Root::getSingleton()->getWindow();
glfwGetWindowSize(window, &width, &height);
float posRatio[] = {pos.x / initWindowSize[0], pos.y / initWindowSize[1]};
float sizeRatio[] = {size.x / initWindowSize[0], size.y / initWindowSize[1]};
pos = Vector2(width * posRatio[0], height * posRatio[1]);
size = Vector2(width * sizeRatio[0], height * sizeRatio[1]);
initWindowSize[0] = width;
initWindowSize[1] = height;
if(textNode)
textNode->setVisible(active);
rectNode->setVisible(active);
}
void Button::onMouseOver(){
mouseOver = true;
}
void Button::onMouseOff(){
mouseOver = false;
}
void Button::setPos(Vector2 pos){
this->pos = pos;
float z1 = rectNode->getPosition().z;
rectNode->setPosition(Vector3(pos.x, pos.y, z1));
if(textNode){
float z2 = textNode->getPosition().z;
textNode->setPosition(Vector3(pos.x, pos.y + size.y, z2));
}
}
void Button::setSize(Vector2 size){
this->size = size;
rect->setSize(Vector3(size.x, size.y, 0));
}
void Button::setColor(Vector4 c){
this->color = c;
((Material::Vector4Uniform*)rect->getMaterial()->getUniform(diffColUni))->value = color;
}
void Button::setZOrder(float zOrder){
Vector3 rectPos = rectNode->getPosition();
rectNode->setPosition(Vector3(rectPos.x, rectPos.y, zOrder));
if(textNode){
Vector3 textPos = textNode->getPosition();
textNode->setPosition(Vector3(textPos.x, textPos.y, zOrder - .1));
}
}
void Button::setImage(string image){
int texId = -1;
Material *mat = rect->getMaterial();
for(int i = 0; i < textures.size(); i++)
if(textures[i]->getPath()[0] == image)
texId = i;
/*
if(texId == -1){
string p[]{image};
textures.push_back(new Texture(p, 1));
mat->setDiffuseMap(textures[textures.size() - 1], 0);
}
else
mat->setDiffuseMap(textures[texId], 0);
*/
this->imagePath = image;
}
}
+53
View File
@@ -0,0 +1,53 @@
#ifndef BUTTON_H
#define BUTTON_H
#include <vector>
#include <string>
#include "vector.h"
class GLFWwindow;
namespace vb01{
class Quad;
class Node;
class Text;
class Texture;
}
namespace vb01Gui{
class Button{
public:
Button(vb01::Vector2, vb01::Vector2, std::string, std::string, int = -1, bool = true, std::string = "");
virtual ~Button();
void update();
virtual void onMouseOver();
virtual void onMouseOff();
virtual void onClick(){}
inline vb01::Vector2 getPos(){return pos;}
void setPos(vb01::Vector2);
inline vb01::Vector2 getSize(){return size;}
void setSize(vb01::Vector2);
inline std::string getName(){return name;}
inline void setActive(bool active){this->active = active;}
inline bool isSeparate(){return separate;}
inline bool isActive(){return active;}
inline vb01::Vector4 getColor(){return color;}
inline int getTrigger(){return trigger;}
void setColor(vb01::Vector4);
void setZOrder(float);
void setImage(std::string);
protected:
int trigger, initWindowSize[2];
bool separate, active = true, mouseOver = false;
vb01::Quad *rect;
vb01::Node *rectNode, *textNode = nullptr, *guiNode;
vb01::Vector2 pos, size;
vb01::Text *text = nullptr;
std::string name, imagePath, texUni = "texturingEnabled", diffColUni = "diffuseColor";
std::vector<vb01::Texture*> textures;
vb01::Vector4 color = vb01::Vector4(.6, .6, .6, 1);
};
}
#endif
+47
View File
@@ -0,0 +1,47 @@
#include "checkbox.h"
#include "text.h"
#include "node.h"
#include "material.h"
using namespace vb01;
using namespace std;
namespace vb01Gui{
Checkbox::CheckboxButton::CheckboxButton(Checkbox *ch, Vector2 pos, Vector2 size, string name, bool separate) : Button(pos, size, name, "", -1, separate) {
checkbox = ch;
}
void Checkbox::CheckboxButton::onClick() {
checkbox->check();
float col = (checkbox->isChecked() ? .6 : .2);
setColor(Vector4(col, col, col, 1));
}
Checkbox::Checkbox(Vector2 pos, string fontPath){
this->pos = pos;
checkboxButton = new CheckboxButton(this, pos, Vector2(length,length), "CheckboxButton", false);
/*
Root *root = Root::getSingleton();
checkNode = new Node();
Text *check = new Text(fontPath, L"X");
Material *mat = new Material(root->getLibPath() + "text");
mat->addBoolUniform("texturingEnabled", false);
mat->addVec4Uniform("diffuseColor", Vector4::VEC_IJKL);
check->setMaterial(mat);
checkNode->addText(check);
checkNode->setVisible(false);
root->getGuiNode()->attachChild(checkNode);
checkNode->setPosition(Vector3(pos.x, pos.y, 0.1f));
*/
}
Checkbox::~Checkbox() {
}
void Checkbox::check() {
checked = !checked;
//checkNode->setVisible(checked);
}
}
+39
View File
@@ -0,0 +1,39 @@
#ifndef CHECKBOX_H
#define CHECKBOX_H
#include "button.h"
namespace vb01{
class Quad;
class Node;
class Text;
}
namespace vb01Gui{
class Checkbox {
public:
Checkbox(vb01::Vector2, std::string);
~Checkbox();
void update(){}
virtual void check();
virtual bool isChecked(){return checked;}
private:
class CheckboxButton : public Button {
public:
CheckboxButton(Checkbox*, vb01::Vector2, vb01::Vector2, std::string, bool);
void onClick();
private:
Checkbox *checkbox = nullptr;
};
const int length = 15;
bool checked = false;
vb01::Vector2 pos;
CheckboxButton *checkboxButton;
vb01::Node *checkNode = nullptr;
public:
inline CheckboxButton* getCheckboxButton(){return checkboxButton;}
};
}
#endif
+234
View File
@@ -0,0 +1,234 @@
#include <glfw3.h>
#include "listbox.h"
#include "util.h"
#include "node.h"
#include "text.h"
#include "quad.h"
#include "root.h"
#include "material.h"
using namespace vb01;
using namespace std;
namespace vb01Gui{
Listbox::ListboxButton::ListboxButton(Listbox *l, Vector2 pos, Vector2 size, string name) : Button(pos, size, name, "", -1, false){listbox = l;}
void Listbox::ListboxButton::onClick(){
if(!listbox->isOpen())
listbox->openUp();
else{
Vector2 cursorPos = getCursorPos();
if(cursorPos.x < listbox->getScrollingButton()->getPos().x){
if(listbox->isCloseable())
listbox->close();
}
else
listbox->scrollToHeight(cursorPos.y);
}
}
Listbox::ScrollingButton::ScrollingButton(Vector2 pos, Vector2 size, string name) : Button(pos, size, name, "", -1, false){}
void Listbox::ScrollingButton::onClick(){}
Listbox::Listbox(Vector2 pos, Vector2 size, std::vector<string> &lines, int maxDisplay, string fontPath, bool closeable){
this->pos = pos;
this->size = size;
this->maxDisplay = maxDisplay;
this->fontPath = fontPath;
this->lineHeight = size.y;
this->closeable = closeable;
Root *root = Root::getSingleton();
Vector2 mousePos = getCursorPos();
guiNode = Root::getSingleton()->getGuiNode();
string texUni = "texturingEnabled", diffColUni = "diffuseColor";
for(int i = 0; i < lines.size(); i++){
Text *text = new Text(fontPath, stringToWstring(lines[i]));
text->setScale(.2);
Material *textMat = new Material(root->getLibPath() + "text");
textMat->addBoolUniform(texUni, false);
textMat->addVec4Uniform(diffColUni, Vector4::VEC_IJKL);
text->setMaterial(textMat);
Node *node = new Node(Vector3(pos.x, pos.y + size.y * (i + 1), textZCoord));
node->addText(text);
guiNode->attachChild(node);
node->setVisible(false);
this->lines.push_back(text);
}
this->lines[0]->getNode()->setVisible(true);
listboxButton = new ListboxButton(this, pos, size, "ListboxButton");
scrollingButton = new ScrollingButton(Vector2(pos.x + size.x - 20, pos.y + lineHeight), Vector2(20, lineHeight * (maxDisplay - 2) / (maxDisplay + 1)), "scrollingButton");
scrollingButton->setColor(Vector4(.2, .2, .2, 1));
scrollingButton->setZOrder(-.05);
scrollingButton->setActive(false);
Quad *selRect = new Quad(Vector3(size.x, size.y, 0), false);
selRectNode = new Node(Vector3(size.x, size.y, -.05));
Material *mat = new Material(root->getLibPath() + "gui");
mat->addBoolUniform(texUni, false);
mat->addVec4Uniform(diffColUni, Vector4(.6, .35, .05, 1));
selRect->setMaterial(mat);
selRectNode->attachMesh(selRect);
selRectNode->setVisible(false);
guiNode->attachChild(selRectNode);
if(!closeable)
openUp();
}
Listbox::~Listbox(){
while(!lines.empty()){
int id = lines.size() - 1;
Node *textNode = lines[id]->getNode();
guiNode->dettachChild(textNode);
delete textNode;
lines.pop_back();
}
guiNode->dettachChild(selRectNode);
delete selRectNode;
}
void Listbox::update(){
scrollingButton->update();
listboxButton->update();
if(open){
Vector2 mousePos = getCursorPos();
Vector2 p = pos;
if(mousePos.y > pos.y && mousePos.y < pos.y + size.y * maxDisplay){
selectedOption = scrollOffset + ((int)(mousePos.y - pos.y) / ((int)size.y));
p.y = pos.y + size.y * ((int)(mousePos.y - pos.y) / ((int)size.y));
}
else if(mousePos.y < pos.y){
selectedOption = 0;
p.y = pos.y;
}
else{
selectedOption = (maxDisplay + scrollOffset) - 1;
p.y = pos.y + size.y * (maxDisplay - 1);
}
selRectNode->setPosition(Vector3(p.x, p.y, -.05));
Vector2 scrollButtonPos = Vector2(pos.x + size.x - 20, pos.y + lineHeight + lineHeight * scrollOffset * (double(maxDisplay - 2) / (maxDisplay + 1)));
scrollingButton->setPos(scrollButtonPos);
}
}
void Listbox::scrollToHeight(float clickPos){
float clickHeight = clickPos - (pos.y + lineHeight);
int newOffset = clickHeight / (lineHeight * (maxDisplay - 2) / (maxDisplay + 1));
int diffOffset = scrollOffset - newOffset;
for(int i = 0; i < abs(diffOffset); ++i){
if(diffOffset > 0)
scrollUp();
else
scrollDown();
}
}
void Listbox::openUp(){
open = true;
lines[selectedOption]->getNode()->setPosition(Vector3(pos.x, pos.y + size.y * (selectedOption-scrollOffset + 1), textZCoord));
lines[selectedOption]->getNode()->setVisible(false);
Vector2 size = listboxButton->getSize();
size.y *= maxDisplay;
listboxButton->setSize(size);
selRectNode->setVisible(true);
scrollingButton->setActive(true);
for(int i = scrollOffset; i < scrollOffset + maxDisplay; i++)
lines[i]->getNode()->setVisible(true);
onOpen();
}
void Listbox::close(){
open = false;
Vector2 size = listboxButton->getSize();
size.y /= maxDisplay;
listboxButton->setSize(size);
selRectNode->setVisible(false);
scrollingButton->setActive(false);
for(int i = scrollOffset; i < scrollOffset + maxDisplay; i++)
lines[i]->getNode()->setVisible(false);
lines[selectedOption]->getNode()->setPosition(Vector3(pos.x, pos.y + size.y, textZCoord));
lines[selectedOption]->getNode()->setVisible(true);
onClose();
}
void Listbox::scrollUp(){
if(scrollOffset > 0){
scrollOffset--;
for(Text *l : lines){
Node *node = l->getNode();
Vector3 p = node->getPosition();
node->setPosition(Vector3(p.x, p.y + size.y, p.z));
if(node->getPosition().y > pos.y + size.y * maxDisplay)
node->setVisible(false);
else if(node->getPosition().y > pos.y)
node->setVisible(true);
}
}
}
void Listbox::scrollDown(){
if (scrollOffset < lines.size() - maxDisplay){
scrollOffset++;
for(Text *l : lines){
Node *node = l->getNode();
Vector3 p = node->getPosition();
node->setPosition(Vector3(p.x, p.y - size.y, p.z));
if(node->getPosition().y - size.y < pos.y)
node->setVisible(false);
else if(node->getPosition().y < pos.y + size.y * (maxDisplay + 1))
node->setVisible(true);
}
}
}
void Listbox::changeLine(int id, wstring change){
lines[id]->setText(change);
}
std::vector<wstring> Listbox::getContents(){
std::vector<wstring> lines;
for(Text *t : this->lines)
lines.push_back(t->getText());
return lines;
}
void Listbox::addLine(wstring line){
Text *t = new Text(fontPath, line);
Node *node = new Node(Vector3(pos.x, pos.y - size.y * lines.size(), textZCoord));
node->addText(t);
guiNode->attachChild(node);
lines.push_back(t);
}
string Listbox::convert(string str){
return str;
}
}
+75
View File
@@ -0,0 +1,75 @@
#ifndef LISTBOX_H
#define LISTBOX_H
#include <vector>
#include "button.h"
#include "vector.h"
namespace vb01{
class Node;
class Text;
}
namespace vb01Gui{
class Listbox{
public:
class ListboxButton : public Button{
public:
ListboxButton(Listbox*, vb01::Vector2, vb01::Vector2, std::string);
void onClick();
private:
Listbox *listbox = nullptr;
};
Listbox(vb01::Vector2, vb01::Vector2, std::vector<std::string>&, int, std::string, bool = true);
~Listbox();
void update();
void openUp();
void close();
void scrollUp();
void scrollDown();
void addLine(std::wstring);
void changeLine(int, std::wstring);
void scrollToHeight(float);
virtual void onOpen(){}
virtual void onClose(){}
inline int getScrollOffset(){return scrollOffset;}
inline float getLineHeight(){return lineHeight;}
inline bool isOpen(){return open;}
inline bool isCloseable(){return closeable;}
void appendLines(std::vector<std::wstring>&);
inline int getSelectedOption(){return selectedOption;}
inline int getMaxDisplay(){return maxDisplay;}
inline int getNumLines(){return lines.size();}
std::vector<std::wstring> getContents();
inline vb01::Vector2 getPos(){return pos;}
inline vb01::Vector2 getSize(){return size;}
private:
class ScrollingButton : public Button{
public:
ScrollingButton(vb01::Vector2, vb01::Vector2, std::string);
void onClick();
private:
};
std::string convert(std::string);
float textZCoord = -.3, lineHeight;
int maxDisplay, scrollOffset = 0;
bool open = false, closeable = false;
std::string fontPath;
vb01::Vector2 pos, size;
ListboxButton *listboxButton;
ScrollingButton *scrollingButton;
vb01::Node *selRectNode, *guiNode;
std::vector<vb01::Text*> lines;
protected:
int selectedOption = 0;
public:
inline ListboxButton* getListboxButton(){return listboxButton;}
inline ScrollingButton* getScrollingButton(){return scrollingButton;}
};
}
#endif
+78
View File
@@ -0,0 +1,78 @@
#include <glfw3.h>
#include <sstream>
#include <algorithm>
#include "slider.h"
#include "root.h"
#include "util.h"
using namespace std;
using namespace vb01;
namespace vb01Gui{
Slider::MovableSliderButton::MovableSliderButton(Slider *slider, Vector2 pos, Vector2 size, string name, bool separate) : Button(pos, size, name, "", -1, separate) {
this->slider = slider;
}
void Slider::MovableSliderButton::onClick() {
clicked = !clicked;
}
void Slider::MovableSliderButton::update() {
Vector2 cursorPos;
if (clicked && cursorPos.y > slider->getPos().y && cursorPos.y < slider->getPos().y + slider->getSize().y) {
if (cursorPos.x < slider->getPos().x)
cursorPos.x = slider->getPos().x;
else if (cursorPos.x > slider->getPos().x + slider->getSize().x)
cursorPos.x = slider->getPos().x + slider->getSize().x;
slider->setValue((((double) cursorPos.x - slider->getPos().x) / slider->getSize().x) * slider->getMaxValue());
}
}
Slider::StaticSliderButton::StaticSliderButton(Slider *slider, Vector2 pos, Vector2 size, string name, bool separate) : Button(pos, size, name, "", -1, separate) {
this->slider = slider;
}
void Slider::StaticSliderButton::onClick() {
Vector2 cursorPos = getCursorPos();
s16 buttonClickPoint = -slider->getPos().x + cursorPos.x;
slider->setValue(((double) buttonClickPoint / slider->getSize().x) * slider->getMaxValue());
}
Slider::Slider(Vector2 pos, Vector2 size, double minValue, double maxValue) {
this->pos = pos;
this->size = size;
this->minValue = minValue;
this->maxValue = maxValue;
staticSliderButton = new StaticSliderButton(this, pos, size, "StaticSliderButton", false);
movableSliderButton = new MovableSliderButton(this, Vector2(pos.x + staticSliderButton->getSize().x / 1, pos.y - 15), Vector2(10, 40), "MovableSliderButton", false);
value = (maxValue - minValue) / 2;
}
Slider::~Slider() {
}
void Slider::update() {
if (value < minValue)
value = minValue;
else if (value > maxValue)
value = maxValue;
Vector2 p = movableSliderButton->getPos(), s = movableSliderButton->getSize();
p.x = pos.x + (double) size.x / maxValue * value;
movableSliderButton->update();
movableSliderButton->setPos(p);
if(textbox && !textbox->isEnabled()){
ostringstream ss;
ss << value;
textbox->setEntry(stringToWstring(ss.str()));
}
}
}
+52
View File
@@ -0,0 +1,52 @@
#ifndef SLIDER_H
#define SLIDER_H
#include "vector.h"
#include "button.h"
#include "textbox.h"
namespace vb01Gui{
class Slider {
public:
Slider(vb01::Vector2, vb01::Vector2, double, double);
~Slider();
void update();
inline void setTextbox(Textbox *t){this->textbox=t;}
inline double getMinValue(){return minValue;}
inline double getValue(){return value;}
inline double getMaxValue(){return maxValue;}
inline void setValue(double v){this->value=v;}
inline vb01::Vector2 getPos(){return pos;}
inline vb01::Vector2 getSize(){return size;}
inline Textbox* getTextbox(){return textbox;}
private:
class MovableSliderButton : public Button {
public:
MovableSliderButton(Slider*, vb01::Vector2, vb01::Vector2, std::string, bool);
void onClick();
void update();
private:
Slider *slider;
bool clicked = false;
};
class StaticSliderButton : public Button {
public:
StaticSliderButton(Slider*, vb01::Vector2, vb01::Vector2, std::string, bool);
void onClick();
private:
Slider *slider;
};
MovableSliderButton *movableSliderButton = nullptr;
StaticSliderButton *staticSliderButton = nullptr;
double minValue, value, maxValue;
vb01::Vector2 pos, size;
Textbox *textbox = nullptr;
public:
inline MovableSliderButton* getMovableSliderButton(){return movableSliderButton;}
inline StaticSliderButton* getStaticSliderButton(){return staticSliderButton;}
};
}
#endif
+131
View File
@@ -0,0 +1,131 @@
#include <algorithm>
#include <sstream>
#include <ostream>
#include "textbox.h"
#include "slider.h"
#include "root.h"
#include "node.h"
#include "quad.h"
#include "material.h"
#include "util.h"
using namespace vb01;
using namespace std;
namespace vb01Gui{
Textbox::TextboxButton::TextboxButton(Textbox *t, Vector2 pos, Vector2 size, string name) : Button(pos, size, name, "", -1, false) {textbox = t;}
void Textbox::TextboxButton::onClick(){
if(!textbox->isEnabled())
textbox->enable();
else
textbox->disable();
}
Textbox::Textbox(Vector2 pos, Vector2 size, string fontPath, wstring entry){
this->pos = pos;
this->size = size;
this->fontPath = fontPath;
textboxButton = new TextboxButton(this, pos, size, "TextboxButton");
string libPath = Root::getSingleton()->getLibPath();
guiNode = Root::getSingleton()->getGuiNode();
text = new Text(fontPath, entry);
text->setScale(.5);
Material *textMat = new Material(libPath + "text");
textMat->addBoolUniform("texturingEnabled", false);
textMat->addVec4Uniform("diffuseColor", Vector4(1, 1, 1, 1));
text->setMaterial(textMat);
textNode = new Node(Vector3(pos.x, pos.y + size.y, -.1));
textNode->addText(text);
guiNode->attachChild(textNode);
cursorPosOffset = entry.length();
cursorRect = new Quad(Vector3(cursorWidth, size.y, 0), false);
cursorNode = new Node(Vector3(pos.x + text->getLength(), pos.y, cursorZCoord));
Material *mat = new Material(libPath + "gui");
mat->addBoolUniform("texturingEnabled", false);
mat->addVec4Uniform("diffuseColor", Vector4(1, 1, 1, 1));
cursorRect->setMaterial(mat);
cursorNode->attachMesh(cursorRect);
cursorNode->setVisible(false);
guiNode->attachChild(cursorNode);
}
Textbox::~Textbox(){
guiNode->dettachChild(textNode);
guiNode->dettachChild(cursorNode);
delete textNode;
delete cursorNode;
}
void Textbox::update(){
if(enabled){
if(canChangeCursor()){
canShowCursor = !canShowCursor;
lastBlinkTime = getTime();
cursorNode->setVisible(canShowCursor);
}
}
}
void Textbox::type(u32 c, bool capitalLetters){
entry += c;
text->setText(entry);
moveCursor(false, text->getGlyph(c)->size.x);
}
void Textbox::moveCursor(bool left, float charWidth){
Vector3 p = cursorNode->getPosition();
if(left && entry.size() - cursorPosOffset > 0){
cursorPosOffset--;
cursorNode->setPosition(Vector3(p.x - charWidth, p.y, p.z));
}
else if(!left){
cursorPosOffset++;
cursorNode->setPosition(Vector3(p.x + charWidth, p.y, p.z));
}
}
void Textbox::deleteCharacter(){
if(entry.length() > 0 && canDeleteChar()){
char c = entry.c_str()[entry.length() - 1];
entry = entry.substr(0, entry.length() - 1);
text->setText(entry);
moveCursor(true, text->getGlyph(c)->size.x);
lastDeleteTime = getTime();
}
}
void Textbox::enable(){
enabled = true;
lastBlinkTime = getTime();
cursorNode->setVisible(true);
}
void Textbox::disable(){
enabled = false;
cursorNode->setVisible(false);
if(slider){
float val = strtof(wstringToString(entry).c_str(), nullptr);
if(val < slider->getMinValue())
val = slider->getMinValue();
else if(val > slider->getMaxValue())
val = slider->getMaxValue();
slider->setValue(val);
}
}
void Textbox::setEntry(wstring entry){
this->entry = entry;
text->setText(entry);
cursorNode->setPosition(Vector3(pos.x + text->getLength(), pos.y, cursorZCoord));
cursorPosOffset = entry.length();
}
}
+59
View File
@@ -0,0 +1,59 @@
#ifndef TEXTBOX_H
#define TEXTBOX_H
#include "util.h"
#include "text.h"
#include "button.h"
namespace vb01{
class Node;
class Quad;
}
namespace vb01Gui{
class Slider;
class Textbox{
public:
Textbox(vb01::Vector2, vb01::Vector2, std::string, std::wstring = L"");
~Textbox();
void update();
void enable();
void disable();
void type(vb01::u32, bool = false);
void moveCursor(bool, float);
void deleteCharacter();
void setSlider(Slider *s){this->slider = s;}
void setEntry(std::wstring);
inline bool isEnabled(){return enabled;}
inline std::wstring getText(){return text->getText();}
void remove();
private:
class TextboxButton : public Button{
public:
TextboxButton(Textbox*, vb01::Vector2, vb01::Vector2, std::string);
void onClick();
private:
Textbox *textbox;
};
inline bool canChangeCursor(){return vb01::getTime() - lastBlinkTime > 250;}
inline bool canDeleteChar(){return vb01::getTime() - lastDeleteTime > 50;}
float cursorZCoord = -.2;
const int cursorWidth = 5;
vb01::Vector2 pos, size;
std::wstring entry = L"";
std::string fontPath = "";
bool enabled = false, canShowCursor = false, capitalLeters = false;
vb01::s64 lastBlinkTime = 0, lastDeleteTime = 0, cursorPosOffset = 0;
vb01::Quad *cursorRect;
vb01::Text *text;
vb01::Node *guiNode, *textNode, *cursorNode;
TextboxButton *textboxButton;
Slider *slider = nullptr;
public:
inline TextboxButton* getTextboxButton(){return textboxButton;}
};
}
#endif