SAM-Viewer/src/dialog.cpp

493 lines
15 KiB
C++

#include <stdlib.h>
#include <iostream>
#include <irrlicht.h>
#ifdef USE_CMAKE_CONFIG_H
#include "cmake_config.h"
#else
#define D_ABOUT_LINK_URL "https://github.com/stujones11/SAM-Viewer"
#define D_ABOUT_LINK_TEXT "github.com/stujones11/SAM-Viewer"
#define D_VERSION "0.0.0"
#endif
#include "config.h"
#include "scene.h"
#include "dialog.h"
static inline void open_url(std::string url)
{
system((std::string("xdg-open \"") + url + std::string("\"")).c_str());
}
HyperlinkCtrl::HyperlinkCtrl(IGUIEnvironment *env, IGUIElement *parent, s32 id,
const rect<s32> &rectangle, const wchar_t *title, std::string url) :
IGUIElement(EGUIET_ELEMENT, env, parent, id, rectangle),
url(url),
is_active(false)
{
IGUIStaticText *text = env->addStaticText(title,
rect<s32>(0,0,rectangle.getWidth(),20), false, false, this);
text->setOverrideColor(SColor(255,0,0,255));
text->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
}
void HyperlinkCtrl::draw()
{
if (is_active)
{
IVideoDriver *driver = Environment->getVideoDriver();
rect<s32> pos = getAbsolutePosition();
vector2di end = pos.LowerRightCorner;
vector2di start = end - vector2di(pos.getWidth(), 0);
driver->draw2DLine(start, end, SColor(255,0,0,255));
}
IGUIElement::draw();
}
bool HyperlinkCtrl::OnEvent(const SEvent &event)
{
if (event.EventType == EET_GUI_EVENT)
{
if (event.GUIEvent.EventType == EGET_ELEMENT_HOVERED)
is_active = true;
else if (event.GUIEvent.EventType == EGET_ELEMENT_LEFT)
is_active = false;
}
else if (is_active && event.EventType == EET_MOUSE_INPUT_EVENT &&
event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
{
open_url(url);
}
return IGUIElement::OnEvent(event);
}
static inline bool isValidHexString(std::string hex)
{
return (hex.length() == 6 &&
hex.find_first_not_of("0123456789abcdefABCDEF") == std::string::npos);
}
ColorCtrl::ColorCtrl(IGUIEnvironment *env, IGUIElement *parent, s32 id,
const rect<s32> &rectangle, const wchar_t *label) :
IGUIElement(EGUIET_ELEMENT, env, parent, id, rectangle)
{
IVideoDriver *driver = env->getVideoDriver();
IGUIStaticText *text = env->addStaticText(label, rect<s32>(0,0,160,20),
false, false, this);
IGUIEditBox *edit = env->addEditBox(L"", rect<s32>(180,0,250,20), true,
this, E_DIALOG_ID_COLOR_EDIT);
edit->setMax(6);
edit->setToolTipText(L"Hex color string RRGGBB");
ITexture *texture = driver->findTexture("color_preview");
if (!texture)
{
IImage *image = driver->createImage(ECF_A8R8G8B8, dimension2du(30,20));
image->fill(SColor(255,255,255,255));
texture = driver->addTexture("color_preview", image);
image->drop();
}
IGUIImage *preview = env->addImage(rect<s32>(270,0,300,20), this,
E_DIALOG_ID_COLOR_PREVIEW);
preview->setImage(texture);
}
void ColorCtrl::setColor(const std::string &hex)
{
if (!isValidHexString(hex))
return;
stringw text = hex.c_str();
IGUIEditBox *edit = (IGUIEditBox*)
getElementFromId(E_DIALOG_ID_COLOR_EDIT);
if (edit)
edit->setText(text.c_str());
IGUIImage *preview = (IGUIImage*)
getElementFromId(E_DIALOG_ID_COLOR_PREVIEW);
if (preview)
{
SColor color;
color.color = std::stoul(hex, nullptr, 16);
color.setAlpha(255);
preview->setColor(color);
}
}
std::string ColorCtrl::getColor() const
{
std::string hex = "";
IGUIEditBox *edit = (IGUIEditBox*)
getElementFromId(E_DIALOG_ID_COLOR_EDIT);
if (edit)
hex = stringc(edit->getText()).c_str();
return hex;
}
bool ColorCtrl::OnEvent(const SEvent &event)
{
if (event.EventType == EET_GUI_EVENT &&
event.GUIEvent.EventType == EGET_EDITBOX_CHANGED &&
event.GUIEvent.Caller->getID() == E_DIALOG_ID_COLOR_EDIT)
{
IGUIEditBox *edit = (IGUIEditBox*)event.GUIEvent.Caller;
std::string hex = stringc(edit->getText()).c_str();
setColor(hex);
}
return IGUIElement::OnEvent(event);
}
AboutDialog::AboutDialog(IGUIEnvironment *env, IGUIElement *parent,
s32 id, const rect<s32> &rectangle) :
IGUIElement(EGUIET_ELEMENT, env, parent, id, rectangle)
{
IVideoDriver *driver = env->getVideoDriver();
ITexture *icon = driver->findTexture("sam_icon_128.png");
if (!icon)
icon = driver->getTexture("sam_icon_128.png");
if (icon)
{
IGUIImage *image = env->addImage(rect<s32>(86,10,214,138), this);
image->setImage(icon);
}
ITexture *title = driver->findTexture("title.png");
if (!title)
title = driver->getTexture("title.png");
if (title)
{
IGUIImage *image = env->addImage(rect<s32>(50,140,250,170), this);
image->setImage(title);
}
stringw desc = stringw("Skin & Model Viewer - Version ") + D_VERSION;
IGUIStaticText *text;
text = env->addStaticText(desc.c_str(), rect<s32>(20,175,280,195),
false, false, this);
text->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
HyperlinkCtrl *link = new HyperlinkCtrl(env, this,
E_DIALOG_ID_ABOUT_LINK, rect<s32>(32,200,268,216),
stringw(D_ABOUT_LINK_TEXT).c_str(), D_ABOUT_LINK_URL);
link->drop();
IGUIButton *button = env->addButton(rect<s32>(110,235,190,265), this,
E_DIALOG_ID_ABOUT_OK, L"OK");
}
SettingsDialog::SettingsDialog(IGUIEnvironment *env, IGUIElement *parent,
s32 id, const rect<s32> &rectangle, Config *conf) :
IGUIElement(EGUIET_ELEMENT, env, parent, id, rectangle),
conf(conf)
{
IGUITabControl *tabs = env->addTabControl(rect<s32>(2,2,398,250),
this, true, true);
IGUITab *tab_general = tabs->addTab(L"General");
IGUITab *tab_debug = tabs->addTab(L"Debug");
IGUIStaticText *text;
IGUIEditBox *edit;
IGUISpinBox *spin;
IGUICheckBox *check;
IGUIButton *button;
ColorCtrl *color;
color = new ColorCtrl(env, tab_general, E_DIALOG_ID_BG_COLOR,
rect<s32>(20,20,320,40), L"Background Color:");
color->setColor(conf->get("bg_color"));
color->drop();
color = new ColorCtrl(env, tab_general, E_DIALOG_ID_GRID_COLOR,
rect<s32>(20,50,320,70), L"Grid Color:");
color->setColor(conf->get("grid_color"));
color->drop();
text = env->addStaticText(L"Wield Attachment Bone:", rect<s32>(20,80,180,100),
false, false, tab_general, -1);
stringw bone_name = conf->getCStr("wield_bone");
edit = env->addEditBox(bone_name.c_str(), rect<s32>(200,80,320,100),
true, tab_general, E_DIALOG_ID_WIELD_BONE);
text = env->addStaticText(L"Default Screen Width:",
rect<s32>(20,110,180,130), false, false, tab_general, -1);
spin = env->addSpinBox(L"", rect<s32>(200,110,270,130),
true, tab_general, E_DIALOG_ID_SCREEN_WIDTH);
spin->setValue(conf->getInt("screen_width"));
spin->setDecimalPlaces(0);
text = env->addStaticText(L"Default Screen Height:",
rect<s32>(20,140,180,160), false, false, tab_general, -1);
spin = env->addSpinBox(L"", rect<s32>(200,140,270,160),
true, tab_general, E_DIALOG_ID_SCREEN_HEIGHT);
spin->setValue(conf->getInt("screen_height"));
spin->setDecimalPlaces(0);
check = env->addCheckBox(false, rect<s32>(20,20,380,40), tab_debug,
E_DIALOG_ID_DEBUG_BBOX, L"Show bounding boxes");
check->setChecked(conf->getInt("debug_flags") & EDS_BBOX);
check = env->addCheckBox(false, rect<s32>(20,50,380,70), tab_debug,
E_DIALOG_ID_DEBUG_NORMALS, L"Show vertex normals");
check->setChecked(conf->getInt("debug_flags") & EDS_NORMALS);
check = env->addCheckBox(false, rect<s32>(20,80,380,100), tab_debug,
E_DIALOG_ID_DEBUG_SKELETON, L"Show skeleton");
check->setChecked(conf->getInt("debug_flags") & EDS_SKELETON);
check = env->addCheckBox(false, rect<s32>(20,110,380,130), tab_debug,
E_DIALOG_ID_DEBUG_WIREFRANE, L"Wireframe overaly");
check->setChecked(conf->getInt("debug_flags") & EDS_MESH_WIRE_OVERLAY);
check = env->addCheckBox(false, rect<s32>(20,140,380,160), tab_debug,
E_DIALOG_ID_DEBUG_ALPHA, L"Use transparent material");
check->setChecked(conf->getInt("debug_flags") & EDS_HALF_TRANSPARENCY);
check = env->addCheckBox(false, rect<s32>(20,170,380,190), tab_debug,
E_DIALOG_ID_DEBUG_BUFFERS, L"Show all mesh buffers");
check->setChecked(conf->getInt("debug_flags") & EDS_BBOX_BUFFERS);
button = env->addButton(rect<s32>(315,255,395,285), this,
E_DIALOG_ID_SETTINGS_OK, L"OK");
button = env->addButton(rect<s32>(230,255,310,285), this,
E_DIALOG_ID_SETTINGS_CANCEL, L"Cancel");
}
bool SettingsDialog::isBoxChecked(s32 id) const
{
IGUICheckBox *check = (IGUICheckBox*)getElementFromId(id, true);
if (check)
return check->isChecked();
return false;
}
bool SettingsDialog::OnEvent(const SEvent &event)
{
if (event.EventType == EET_GUI_EVENT &&
event.GUIEvent.EventType == EGET_BUTTON_CLICKED &&
event.GUIEvent.Caller->getID() == E_DIALOG_ID_SETTINGS_OK)
{
IGUIEditBox *edit;
IGUISpinBox *spin;
ColorCtrl *color;
color = (ColorCtrl*)getElementFromId(E_DIALOG_ID_BG_COLOR, true);
if (color)
{
const std::string hex = color->getColor();
if (isValidHexString(hex))
conf->set("bg_color", hex);
}
color = (ColorCtrl*)getElementFromId(E_DIALOG_ID_GRID_COLOR, true);
if (color)
{
const std::string hex = color->getColor();
if (isValidHexString(hex))
conf->set("grid_color", hex);
}
edit = (IGUIEditBox*)
getElementFromId(E_DIALOG_ID_WIELD_BONE, true);
std::string bone = stringc(edit->getText()).c_str();
conf->set("wield_bone", bone);
spin = (IGUISpinBox*)
getElementFromId(E_DIALOG_ID_SCREEN_WIDTH, true);
u32 width = spin->getValue();
conf->set("screen_width", std::to_string(width));
spin = (IGUISpinBox*)
getElementFromId(E_DIALOG_ID_SCREEN_HEIGHT, true);
u32 height = spin->getValue();
conf->set("screen_height", std::to_string(height));
u32 flags = 0;
if (isBoxChecked(E_DIALOG_ID_DEBUG_BBOX))
flags |= EDS_BBOX;
if (isBoxChecked(E_DIALOG_ID_DEBUG_NORMALS))
flags |= EDS_NORMALS;
if (isBoxChecked(E_DIALOG_ID_DEBUG_SKELETON))
flags |= EDS_SKELETON;
if (isBoxChecked(E_DIALOG_ID_DEBUG_WIREFRANE))
flags |= EDS_MESH_WIRE_OVERLAY;
if (isBoxChecked(E_DIALOG_ID_DEBUG_ALPHA))
flags |= EDS_HALF_TRANSPARENCY;
if (isBoxChecked(E_DIALOG_ID_DEBUG_BUFFERS))
flags |= EDS_BBOX_BUFFERS;
conf->set("debug_flags", std::to_string(flags));
}
return IGUIElement::OnEvent(event);
}
TexturesDialog::TexturesDialog(IGUIEnvironment *env, IGUIElement *parent,
s32 id, const rect<s32> &rectangle, Config *conf, ISceneManager *smgr) :
IGUIElement(EGUIET_ELEMENT, env, parent, id, rectangle),
conf(conf),
smgr(smgr)
{
IGUITabControl *tabs = env->addTabControl(rect<s32>(2,2,398,250), this,
true, true);
IGUITab *tab_model = tabs->addTab(L"Model");
IGUITab *tab_wield = tabs->addTab(L"Wield");
IGUIStaticText *text;
IGUIEditBox *edit;
IGUIButton *button;
stringw fn;
std::string key;
ITexture *image = getTexture("browse.png");
ISceneNode *model = smgr->getSceneNodeFromId(E_SCENE_ID_MODEL);
ISceneNode *wield = smgr->getSceneNodeFromId(E_SCENE_ID_WIELD);
u32 mc_model = (model) ? model->getMaterialCount() : 0;
u32 mc_wield = (wield) ? wield->getMaterialCount() : 0;
for (s32 i = 0; i < 6; ++i)
{
s32 top = i * 30 + 20;
stringw num = stringw(i + 1);
key = "model_texture_" + std::to_string(i + 1);
fn = conf->getCStr(key);
text = env->addStaticText(num.c_str(), rect<s32>(15,top,25,top+20),
false, false, tab_model, -1);
edit = env->addEditBox(fn.c_str(), rect<s32>(35,top,350,top+20),
true, tab_model, E_TEXTURE_ID_MODEL + i);
edit->setEnabled(i < mc_model);
edit->setOverrideColor(SColor(255,255,0,0));
edit->enableOverrideColor(false);
button = env->addButton(rect<s32>(360,top,380,top+20), tab_model,
E_BUTTON_ID_MODEL + i);
button->setToolTipText(L"Browse");
if (image)
{
button->setImage(image);
button->setUseAlphaChannel(true);
button->setDrawBorder(false);
}
button->setEnabled(i < mc_model);
key = "wield_texture_" + std::to_string(i + 1);
fn = conf->getCStr(key);
text = env->addStaticText(num.c_str(), rect<s32>(15,top,25,top+20),
false, false, tab_wield, -1);
edit = env->addEditBox(fn.c_str(), rect<s32>(35,top,350,top+20),
true, tab_wield, E_TEXTURE_ID_WIELD + i);
edit->setEnabled(i < mc_wield);
edit->setOverrideColor(SColor(255,255,0,0));
edit->enableOverrideColor(false);
button = env->addButton(rect<s32>(360,top,380,top+20), tab_wield,
E_BUTTON_ID_WIELD + i);
if (image)
{
button->setImage(image);
button->setUseAlphaChannel(true);
button->setDrawBorder(false);
}
button->setEnabled(i < mc_wield);
}
button = env->addButton(rect<s32>(315,255,395,285), this,
E_DIALOG_ID_TEXTURES_OK, L"OK");
button = env->addButton(rect<s32>(230,255,310,285), this,
E_DIALOG_ID_TEXTURES_CANCEL, L"Cancel");
}
ITexture *TexturesDialog::getTexture(const io::path &filename)
{
IVideoDriver *driver = Environment->getVideoDriver();
ITexture *texture = driver->findTexture(filename);
if (!texture)
texture = driver->getTexture(filename);
return texture;
}
bool TexturesDialog::OnEvent(const SEvent &event)
{
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
{
if (event.GUIEvent.Caller->getType() == EGUIET_EDIT_BOX)
{
IGUIEditBox *edit = (IGUIEditBox*)event.GUIEvent.Caller;
if (edit)
{
stringc fn = stringc(edit->getText()).c_str();
edit->enableOverrideColor(!(getTexture(fn)));
}
}
}
else if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
{
if (id == E_DIALOG_ID_TEXTURES_OK)
{
ISceneNode *model = smgr->getSceneNodeFromId(E_SCENE_ID_MODEL);
ISceneNode *wield = smgr->getSceneNodeFromId(E_SCENE_ID_WIELD);
IGUIEditBox *edit;
for (s32 i = 0; i < 6; ++i)
{
std::string idx = std::to_string(i + 1);
edit = (IGUIEditBox*)
getElementFromId(E_TEXTURE_ID_MODEL + i, true);
if (edit && model && i < model->getMaterialCount())
{
stringc fn = stringc(edit->getText()).c_str();
ITexture *texture = getTexture(fn);
if (texture)
{
std::string key = "model_texture_" + idx;
conf->set(key, fn.c_str());
SMaterial &material = model->getMaterial(i);
material.TextureLayer[0].Texture = texture;
}
}
edit = (IGUIEditBox*)
getElementFromId(E_TEXTURE_ID_WIELD + i, true);
if (edit && wield && i < wield->getMaterialCount())
{
stringc fn = stringc(edit->getText()).c_str();
ITexture *texture = getTexture(fn);
if (texture)
{
std::string key = "wield_texture_" + idx;
conf->set(key, fn.c_str());
SMaterial &material = wield->getMaterial(i);
material.TextureLayer[0].Texture = texture;
}
}
}
}
else
{
for (s32 i = 0; i < 6; ++i)
{
if (id == E_BUTTON_ID_MODEL + i)
{
Environment->addFileOpenDialog(L"Open Image File",
true, this, E_TEXTURE_ID_MODEL + i);
break;
}
else if (id == E_BUTTON_ID_WIELD + i)
{
Environment->addFileOpenDialog(L"Open Image File",
true, this, E_TEXTURE_ID_WIELD + i);
break;
}
}
}
}
else if (event.GUIEvent.EventType == EGET_FILE_SELECTED)
{
IGUIFileOpenDialog *dialog =
(IGUIFileOpenDialog*)event.GUIEvent.Caller;
stringw fn = stringw(dialog->getFileName());
if (!fn.empty())
{
s32 id = dialog->getID();
IGUIEditBox *edit = (IGUIEditBox*)getElementFromId(id, true);
if (edit)
{
edit->setText(fn.c_str());
edit->enableOverrideColor(!(getTexture(fn)));
}
}
}
}
return IGUIElement::OnEvent(event);
}