diff --git a/README.md b/README.md index d63f873..591ae02 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,6 @@ Controls To Do ----- -* Basic lighting. * Image capture tools. Screenshot diff --git a/src/controls.cpp b/src/controls.cpp index bb01e24..721b562 100644 --- a/src/controls.cpp +++ b/src/controls.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include "controls.h" @@ -67,6 +68,14 @@ VectorCtrl::VectorCtrl(IGUIEnvironment *env, IGUIElement *parent, s32 id, z->drop(); } +std::string VectorCtrl::getString() const +{ + std::ostringstream ss; + ss << vector.X << "," << vector.Y << "," << vector.Z; + std::string str(ss.str()); + return str; +} + void VectorCtrl::setVector(const vector3df &vec) { vector = vec; @@ -250,9 +259,10 @@ ColorCtrl::ColorCtrl(IGUIEnvironment *env, IGUIElement *parent, s32 id, IGUIElement(EGUIET_ELEMENT, env, parent, id, rectangle) { IVideoDriver *driver = env->getVideoDriver(); + s32 x = rectangle.getWidth() - 140; env->addStaticText(label, rect(0,0,160,20), false, false, this); - IGUIEditBox *edit = env->addEditBox(L"", rect(180,0,250,20), true, + IGUIEditBox *edit = env->addEditBox(L"", rect(x,0,x+70,20), true, this, E_CTRL_ID_COLOR_EDIT); edit->setMax(6); edit->setToolTipText(L"Hex color RRGGBB"); @@ -265,7 +275,7 @@ ColorCtrl::ColorCtrl(IGUIEnvironment *env, IGUIElement *parent, s32 id, texture = driver->addTexture("color_preview", image); image->drop(); } - IGUIImage *preview = env->addImage(rect(270,0,300,20), this, + IGUIImage *preview = env->addImage(rect(x+90,0,x+120,20), this, E_CTRL_ID_COLOR_PREVIEW); preview->setImage(texture); } @@ -291,7 +301,7 @@ void ColorCtrl::setColor(const std::string &hex) } } -std::string ColorCtrl::getColor() const +std::string ColorCtrl::getString() const { std::string hex = ""; IGUIEditBox *edit = (IGUIEditBox*) @@ -301,6 +311,13 @@ std::string ColorCtrl::getColor() const return hex; } +SColor ColorCtrl::getColor() const +{ + IGUIImage *image = (IGUIImage*) + getElementFromId(E_CTRL_ID_COLOR_PREVIEW); + return image->getColor(); +} + bool ColorCtrl::isValidHexString(std::string hex) { return (hex.length() == 6 && diff --git a/src/controls.h b/src/controls.h index 20dee8f..7739dc0 100644 --- a/src/controls.h +++ b/src/controls.h @@ -9,7 +9,7 @@ using namespace video; enum { - E_CTRL_ID_VERTEX, + E_CTRL_ID_VERTEX = 0x3000, E_CTRL_ID_VECTOR_X, E_CTRL_ID_VECTOR_Y, E_CTRL_ID_VECTOR_Z, @@ -45,6 +45,7 @@ public: virtual ~VectorCtrl() {} virtual bool OnEvent(const SEvent &event); vector3df getVector() const { return vector; } + std::string getString() const; void setVector(const vector3df &vec); private: @@ -87,9 +88,9 @@ public: virtual ~ColorCtrl() {} virtual bool OnEvent(const SEvent &event); void setColor(const std::string &hex); - std::string getColor() const; + std::string getString() const; + SColor getColor() const; bool isValidHexString(std::string hex); }; - #endif // D_CONTROLS_H \ No newline at end of file diff --git a/src/dialog.cpp b/src/dialog.cpp index 74e78b8..d4bc7ed 100644 --- a/src/dialog.cpp +++ b/src/dialog.cpp @@ -9,7 +9,6 @@ #include "tinyfiledialogs.h" #include "dialog.h" - #ifdef USE_CMAKE_CONFIG_H #include "cmake_config.h" #else @@ -194,14 +193,14 @@ bool SettingsDialog::OnEvent(const SEvent &event) color = (ColorCtrl*)getElementFromId(E_DIALOG_ID_BG_COLOR, true); if (color) { - const std::string hex = color->getColor(); + const std::string hex = color->getString(); if (color->isValidHexString(hex)) conf->set("bg_color", hex); } color = (ColorCtrl*)getElementFromId(E_DIALOG_ID_GRID_COLOR, true); if (color) { - const std::string hex = color->getColor(); + const std::string hex = color->getString(); if (color->isValidHexString(hex)) conf->set("grid_color", hex); } @@ -464,4 +463,139 @@ bool TexturesDialog::OnEvent(const SEvent &event) } } return IGUIElement::OnEvent(event); +} + +LightsDialog::LightsDialog(IGUIEnvironment *env, IGUIElement *parent, + s32 id, const rect &rectangle, Config *conf, ISceneManager *smgr) : + IGUIElement(EGUIET_ELEMENT, env, parent, id, rectangle), + conf(conf), + smgr(smgr) +{ + IGUITabControl *tabs = env->addTabControl(rect(2,2,398,310), + this, true, true); + for (int i = 0; i < 3; ++i) + { + stringw label = "Light "; + label.append(stringw(i + 1)); + IGUITab *tab_light = tabs->addTab(label.c_str()); + IGUISpinBox *spin; + ColorCtrl *color; + VectorCtrl *position; + + env->addStaticText(L"Type:", rect(20,20,80,40), false, false, + tab_light); + IGUIComboBox *combo = env->addComboBox(rect(80,20,200,40), + tab_light, E_DIALOG_ID_LIGHT_TYPE + i); + combo->addItem(L"Point", ELT_POINT); + combo->addItem(L"Spot", ELT_SPOT); + combo->addItem(L"Directional", ELT_DIRECTIONAL); + env->addStaticText(L"Radius:", rect(240,20,300,40), false, false, + tab_light, -1); + spin = env->addSpinBox(L"", rect(300,20,370,40), + true, tab_light, E_DIALOG_ID_LIGHT_RADIUS + i); + spin->setDecimalPlaces(0); + color = new ColorCtrl(env, tab_light, E_DIALOG_ID_LIGHT_DIFFUSE + i, + rect(20,50,270,70), L"Diffuse Color:"); + color->drop(); + color = new ColorCtrl(env, tab_light, E_DIALOG_ID_LIGHT_AMBIENT + i, + rect(20,80,270,100), L"Ambient Color:"); + color->drop(); + color = new ColorCtrl(env, tab_light, E_DIALOG_ID_LIGHT_SPECULAR + i, + rect(20,110,270,130), L"Specular Color:"); + color->drop(); + position = new VectorCtrl(env, tab_light, E_DIALOG_ID_LIGHT_POS + i, + rect(10,140,150,250), 1.0, L"Position:"); + position->drop(); + position = new VectorCtrl(env, tab_light, E_DIALOG_ID_LIGHT_ROT + i, + rect(240,140,380,250), 1.0, L"Rotation:"); + position->drop(); + } + env->addButton(rect(5,315,85,345), this, + E_DIALOG_ID_LIGHTS_PREVIEW, L"Preview"); + env->addButton(rect(315,315,395,345), this, + E_DIALOG_ID_LIGHTS_OK, L"OK"); + env->addButton(rect(230,315,310,345), this, + E_DIALOG_ID_LIGHTS_CANCEL, L"Cancel"); + + setLights(E_DIALOG_ID_LIGHTS_INIT); +} + +void LightsDialog::setLights(s32 id) +{ + for (int i = 0; i < 3; ++i) + { + std::string n = std::to_string(i + 1); + IGUIComboBox *combo = (IGUIComboBox*) + getElementFromId(E_DIALOG_ID_LIGHT_TYPE + i, true); + s32 index = combo->getSelected(); + E_LIGHT_TYPE light_type = (E_LIGHT_TYPE)combo->getItemData(index); + ColorCtrl *diffuse = (ColorCtrl*) + getElementFromId(E_DIALOG_ID_LIGHT_DIFFUSE + i, true); + ColorCtrl *ambient = (ColorCtrl*) + getElementFromId(E_DIALOG_ID_LIGHT_AMBIENT + i, true); + ColorCtrl *specular = (ColorCtrl*) + getElementFromId(E_DIALOG_ID_LIGHT_SPECULAR + i, true); + IGUISpinBox *radius = (IGUISpinBox*) + getElementFromId(E_DIALOG_ID_LIGHT_RADIUS + i, true); + VectorCtrl *position = (VectorCtrl*) + getElementFromId(E_DIALOG_ID_LIGHT_POS + i, true); + VectorCtrl *rotation = (VectorCtrl*) + getElementFromId(E_DIALOG_ID_LIGHT_ROT + i, true); + if (id == E_DIALOG_ID_LIGHTS_OK) + { + conf->set("light_type_" + n, std::to_string(light_type)); + conf->set("light_color_diffuse_" + n, diffuse->getString()); + conf->set("light_color_ambient_" + n, ambient->getString()); + conf->set("light_color_specular_" + n, specular->getString()); + conf->set("light_position_" + n, position->getString()); + conf->set("light_rotation_" + n, rotation->getString()); + conf->set("light_radius_" + n, std::to_string(radius->getValue())); + } + else if (id != E_DIALOG_ID_LIGHTS_PREVIEW) + { + light_type = (E_LIGHT_TYPE)conf->getInt("light_type_" + n); + index = combo->getIndexForItemData(light_type); + combo->setSelected(index); + diffuse->setColor(conf->get("light_color_diffuse_" + n)); + ambient->setColor(conf->get("light_color_ambient_" + n)); + specular->setColor(conf->get("light_color_specular_" + n)); + Vector pos = conf->getVector("light_position_" + n); + position->setVector(vector3df(pos.x, pos.y, pos.z)); + Vector rot = conf->getVector("light_rotation_" + n); + rotation->setVector(vector3df(rot.x, rot.y, rot.z)); + radius->setValue(conf->getInt("light_radius_" + n)); + } + LightSource *light = (LightSource*) + smgr->getSceneNodeFromId(E_SCENE_ID_LIGHT + i); + if (light) + { + LightSpec lightspec; + lightspec.type = light_type; + lightspec.position = position->getVector(); + lightspec.rotation = rotation->getVector(); + lightspec.radius = radius->getValue(); + lightspec.color.diffuse = diffuse->getColor(); + lightspec.color.ambient = ambient->getColor(); + lightspec.color.specular = specular->getColor(); + light->setLight(lightspec); + } + } +} + +bool LightsDialog::OnEvent(const SEvent &event) +{ + if (event.EventType == EET_GUI_EVENT) + { + if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) + { + s32 id = event.GUIEvent.Caller->getID(); + if (id == E_DIALOG_ID_LIGHTS_OK || + id == E_DIALOG_ID_LIGHTS_CANCEL || + id == E_DIALOG_ID_LIGHTS_PREVIEW) + { + setLights(id); + } + } + } + return IGUIElement::OnEvent(event); } \ No newline at end of file diff --git a/src/dialog.h b/src/dialog.h index f0a4586..d842267 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -30,7 +30,12 @@ enum E_DIALOG_ID_TEXTURES_1_MODEL, E_DIALOG_ID_TEXTURES_1_WIELD, E_DIALOG_ID_TEXTURES_OK, - E_DIALOG_ID_TEXTURES_CANCEL + E_DIALOG_ID_TEXTURES_CANCEL, + E_DIALOG_ID_LIGHTS, + E_DIALOG_ID_LIGHTS_INIT, + E_DIALOG_ID_LIGHTS_PREVIEW, + E_DIALOG_ID_LIGHTS_OK, + E_DIALOG_ID_LIGHTS_CANCEL }; enum @@ -38,7 +43,14 @@ enum E_TEXTURE_ID_MODEL = 0x2000, E_TEXTURE_ID_WIELD = 0x2010, E_BUTTON_ID_MODEL = 0x2020, - E_BUTTON_ID_WIELD = 0x2030 + E_BUTTON_ID_WIELD = 0x2030, + E_DIALOG_ID_LIGHT_TYPE = 0x2040, + E_DIALOG_ID_LIGHT_POS = 0x2050, + E_DIALOG_ID_LIGHT_ROT = 0x2060, + E_DIALOG_ID_LIGHT_DIFFUSE = 0x2070, + E_DIALOG_ID_LIGHT_AMBIENT = 0x2080, + E_DIALOG_ID_LIGHT_SPECULAR = 0x2090, + E_DIALOG_ID_LIGHT_RADIUS = 0x2100 }; namespace dialog @@ -105,4 +117,19 @@ private: ISceneManager *smgr; }; +class LightsDialog : public IGUIElement +{ +public: + LightsDialog(IGUIEnvironment *env, IGUIElement *parent, s32 id, + const rect &rectangle, Config *conf, ISceneManager *smgr); + virtual ~LightsDialog() {} + virtual bool OnEvent(const SEvent &event); + +private: + void setLights(s32 id); + + Config *conf; + ISceneManager *smgr; +}; + #endif // D_DIALOG_H \ No newline at end of file diff --git a/src/gui.cpp b/src/gui.cpp index f71df9a..a0645df 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -175,9 +175,10 @@ void GUI::initMenu() submenu->addItem(L"Quit", E_GUI_ID_QUIT); submenu = menu->getSubMenu(1); - submenu->addItem(L"Textures", E_GUI_ID_TEXTURES_DIALOG); + submenu->addItem(L"Textures", E_DIALOG_ID_TEXTURES); + submenu->addItem(L"Lights", E_DIALOG_ID_LIGHTS); submenu->addSeparator(); - submenu->addItem(L"Preferences", E_GUI_ID_SETTINGS_DIALOG); + submenu->addItem(L"Preferences", E_DIALOG_ID_SETTINGS); submenu = menu->getSubMenu(2); submenu->addItem(L"Model Toolbox", E_GUI_ID_TOOLBOX_MODEL, true, false, @@ -189,25 +190,30 @@ void GUI::initMenu() true, true); submenu->addItem(L"Show Axes", E_GUI_ID_SHOW_AXES, true, false, true, true); + submenu->addItem(L"Show Lights", E_GUI_ID_SHOW_LIGHTS, + conf->getBool("lighting"), false, true, true); submenu->addSeparator(); submenu->addItem(L"Projection", -1, true, true); submenu->addItem(L"Filters", -1, true, true); + submenu->addItem(L"Lights", -1, conf->getBool("lighting"), true); submenu->addSeparator(); submenu->addItem(L"Show Wield Item", E_GUI_ID_ENABLE_WIELD, true, false, conf->getBool("wield_show"), true); submenu->addItem(L"Backface Culling", E_GUI_ID_BACK_FACE_CULL, true, false, conf->getBool("backface_cull"), true); + submenu->addItem(L"Lighting", E_GUI_ID_LIGHTING, true, false, + conf->getBool("lighting"), true); submenu->addSeparator(); submenu->addItem(L"Model Debug Info", E_GUI_ID_DEBUG_INFO, true, false, conf->getBool("debug_info"), true); - submenu = menu->getSubMenu(2)->getSubMenu(6); + submenu = menu->getSubMenu(2)->getSubMenu(7); submenu->addItem(L"Perspective", E_GUI_ID_PERSPECTIVE, true, false, !conf->getBool("ortho"), true); submenu->addItem(L"Orthogonal", E_GUI_ID_ORTHOGONAL, true, false, conf->getBool("ortho"), true); - submenu = menu->getSubMenu(2)->getSubMenu(7); + submenu = menu->getSubMenu(2)->getSubMenu(8); submenu->addItem(L"Bilinear", E_GUI_ID_BILINEAR, true, false, conf->getBool("bilinear"), true); submenu->addItem(L"Trilinear", E_GUI_ID_TRILINEAR, true, false, @@ -215,6 +221,14 @@ void GUI::initMenu() submenu->addItem(L"Anisotropic", E_GUI_ID_ANISOTROPIC, true, false, conf->getBool("anisotropic"), true); + submenu = menu->getSubMenu(2)->getSubMenu(9); + submenu->addItem(L"Light 1", E_GUI_ID_LIGHT, true, false, + conf->getBool("light_enabled_1"), true); + submenu->addItem(L"Light 2", E_GUI_ID_LIGHT + 1, true, false, + conf->getBool("light_enabled_2"), true); + submenu->addItem(L"Light 3", E_GUI_ID_LIGHT + 2, true, false, + conf->getBool("light_enabled_3"), true); + submenu = menu->getSubMenu(3); submenu->addItem(L"About", E_DIALOG_ID_ABOUT); } @@ -363,6 +377,18 @@ void GUI::showAboutDialog() dialog->drop(); } +void GUI::showLightsDialog() +{ + IGUIEnvironment *env = device->getGUIEnvironment(); + ISceneManager *smgr = device->getSceneManager(); + IGUIWindow *window = env->addWindow(getWindowRect(400, 370), + true, L"Lights"); + + LightsDialog *dialog = new LightsDialog(env, window, + E_DIALOG_ID_LIGHTS, rect(0,20,400,370), conf, smgr); + dialog->drop(); +} + IGUIElement *GUI::getElement(s32 id) { IGUIEnvironment *env = device->getGUIEnvironment(); diff --git a/src/gui.h b/src/gui.h index be51662..628c601 100644 --- a/src/gui.h +++ b/src/gui.h @@ -15,14 +15,14 @@ enum E_GUI_ID_LOAD_WIELD_MESH, E_GUI_ID_SAVE_CONFIG, E_GUI_ID_QUIT, - E_GUI_ID_TEXTURES_DIALOG, - E_GUI_ID_SETTINGS_DIALOG, E_GUI_ID_TOOLBOX_MODEL, E_GUI_ID_TOOLBOX_WIELD, E_GUI_ID_SHOW_GRID, E_GUI_ID_SHOW_AXES, + E_GUI_ID_SHOW_LIGHTS, E_GUI_ID_ENABLE_WIELD, E_GUI_ID_BACK_FACE_CULL, + E_GUI_ID_LIGHTING, E_GUI_ID_ORTHOGONAL, E_GUI_ID_PERSPECTIVE, E_GUI_ID_BILINEAR, @@ -40,6 +40,11 @@ enum E_GUI_ID_ANIM_SPEED, }; +enum +{ + E_GUI_ID_LIGHT = 0x4100 +}; + class Config; class ToolBox : public IGUIElement @@ -71,6 +76,7 @@ public: void showTexturesDialog(); void showSettingsDialog(); void showAboutDialog(); + void showLightsDialog(); private: const rect getWindowRect(const u32 &width, const u32 &height) const; diff --git a/src/main.cpp b/src/main.cpp index f58ec55..6e4776f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,6 +35,31 @@ int main() {"wield_texture_5", "blank.png"}, {"wield_texture_6", "blank.png"}, {"wield_texture_single", "false"}, + {"lighting", "false"}, + {"light_type_1", "0"}, + {"light_enabled_1" , "true"}, + {"light_color_diffuse_1", "FFFFFF"}, + {"light_color_ambient_1", "111111"}, + {"light_color_specular_1", "000000"}, + {"light_position_1", "0,15,0"}, + {"light_rotation_1", "90,45,0"}, + {"light_radius_1", "100"}, + {"light_type_2", "1"}, + {"light_enabled_2" , "true"}, + {"light_color_diffuse_2", "AAAAFF"}, + {"light_color_ambient_2", "000000"}, + {"light_color_specular_2", "000000"}, + {"light_position_2", "15,15,15"}, + {"light_rotation_2", "150,45,0"}, + {"light_radius_2", "50"}, + {"light_type_3", "2"}, + {"light_enabled_3" , "true"}, + {"light_color_diffuse_3", "220000"}, + {"light_color_ambient_3", "070000"}, + {"light_color_specular_3", "000000"}, + {"light_position_3", "-15,15,15"}, + {"light_rotation_3", "150,-45,0"}, + {"light_radius_3", "100"}, {"anim_start", "168"}, {"anim_end", "187"}, {"anim_speed", "15"}, diff --git a/src/scene.cpp b/src/scene.cpp index bbad013..5ec727a 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -5,6 +5,87 @@ #include "config.h" #include "scene.h" +LightSource::LightSource(ISceneNode *parent, ISceneManager *smgr, s32 id, + LightSpec lightspec, const wchar_t *text, SColor text_color) : + ISceneNode(parent, smgr, id), + light(0), + marker(0), + label(0) +{ + line_color = text_color; + line_color.setAlpha(64); + text_color.setAlpha(255); + texture_name = "light_"; + texture_name.append(text); + + material.Lighting = false; + material.MaterialType = EMT_TRANSPARENT_ALPHA_CHANNEL; + material.BackfaceCulling = false; + + IVideoDriver *driver = SceneManager->getVideoDriver(); + ITexture *texture = driver->addTexture(dimension2d(1,1), + texture_name.c_str()); + + marker = smgr->addSphereSceneNode(0.75f, 12, this); + marker->setMaterialFlag(EMF_LIGHTING, false); + marker->setMaterialTexture(0, texture); + + IGUIEnvironment *env = smgr->getGUIEnvironment(); + IGUIFont *font = env->getFont("fontlucida.png"); + label = smgr->addTextSceneNode(font, text, text_color, this); + label->setMaterialFlag(EMF_LIGHTING, false); + + light = smgr->addLightSceneNode(this); + setLight(lightspec); +} + +void LightSource::setLight(LightSpec lightspec) +{ + setPosition(lightspec.position); + setRotation(lightspec.rotation); + SLight data; + data.DiffuseColor = lightspec.color.diffuse; + data.AmbientColor = lightspec.color.ambient; + data.SpecularColor = lightspec.color.specular; + light->setLightData(data); + light->setLightType(lightspec.type); + light->setRadius(lightspec.radius); + + IVideoDriver *driver = SceneManager->getVideoDriver(); + ITexture *texture = driver->getTexture(texture_name.c_str()); + if (texture) + { + s32 *p = (s32*)texture->lock(); + p[0] = lightspec.color.diffuse.color; + texture->unlock(); + } +} + +void LightSource::setMarker(const bool &is_visible) +{ + marker->setVisible(is_visible); + label->setVisible(is_visible); +} + +void LightSource::OnRegisterSceneNode() +{ + if (IsVisible) + SceneManager->registerNodeForRendering(this); + + ISceneNode::OnRegisterSceneNode(); +} + +void LightSource::render() +{ + if (!marker->isVisible()) + return; + + IVideoDriver *driver = SceneManager->getVideoDriver(); + driver->setMaterial(material); + driver->setTransform(ETS_WORLD, AbsoluteTransformation); + driver->draw3DLine(vector3df(0,0,0), vector3df(0,0,100), line_color); +} + Scene::Scene(ISceneNode *parent, ISceneManager *smgr, s32 id) : ISceneNode(parent, smgr, id), conf(0), @@ -27,6 +108,8 @@ bool Scene::load(Config *config) loadWieldMesh(conf->getCStr("wield_mesh")); setBackFaceCulling(conf->getBool("backface_cull")); setGridColor(conf->getHex("grid_color")); + addLights(); + setLighting(conf->getBool("lighting")); return true; } @@ -59,7 +142,8 @@ bool Scene::loadModelMesh(const io::path &filename) f32 s = (f32)conf->getInt("model_scale") / 100; u32 mat = conf->getInt("model_material"); - model->setMaterialFlag(EMF_LIGHTING, false); + model->setMaterialFlag(EMF_LIGHTING, conf->getBool("lighting")); + model->setMaterialFlag(EMF_NORMALIZE_NORMALS, true); model->setPosition(vector3df(pos.x, pos.y, pos.z)); model->setRotation(vector3df(rot.x, rot.y, rot.z)); model->setScale(vector3df(s,s,s)); @@ -105,7 +189,8 @@ bool Scene::loadWieldMesh(const io::path &filename) f32 s = (f32)conf->getInt("wield_scale") / 100; u32 mat = conf->getInt("wield_material"); - wield->setMaterialFlag(EMF_LIGHTING, false); + wield->setMaterialFlag(EMF_LIGHTING, conf->getBool("lighting")); + wield->setMaterialFlag(EMF_NORMALIZE_NORMALS, true); wield->setPosition(vector3df(pos.x, pos.y, pos.z)); wield->setRotation(vector3df(rot.x, rot.y, rot.z)); wield->setScale(vector3df(s,s,s)); @@ -124,6 +209,61 @@ bool Scene::loadWieldMesh(const io::path &filename) return true; } +void Scene::addLights() +{ + for (int i = 0; i < 3; ++i) + { + std::string n = std::to_string(i + 1); + Vector pos = conf->getVector("light_position_" + n); + Vector rot = conf->getVector("light_rotation_" + n); + LightSpec lightspec; + lightspec.type = (E_LIGHT_TYPE)conf->getInt("light_type_" + n); + lightspec.position = vector3df(pos.x, pos.y, pos.z); + lightspec.rotation = vector3df(rot.x, rot.y, rot.z); + lightspec.color.diffuse = conf->getHex("light_color_diffuse_" + n); + lightspec.color.ambient = conf->getHex("light_color_ambient_" + n); + lightspec.color.specular = conf->getHex("light_color_specular_" + n); + lightspec.radius = conf->getInt("light_radius_" + n); + SColor text_color = conf->getHex("grid_color"); + stringw label = n.c_str(); + LightSource *light = new LightSource(this, SceneManager, + E_SCENE_ID_LIGHT + i, lightspec, label.c_str(), text_color); + light->drop(); + } +} + +void Scene::setLighting(const bool &is_enabled) +{ ISceneNode *model = getNode(E_SCENE_ID_MODEL); + if (model) + model->setMaterialFlag(EMF_LIGHTING, is_enabled); + + ISceneNode *wield = getNode(E_SCENE_ID_WIELD); + if (wield) + wield->setMaterialFlag(EMF_LIGHTING, is_enabled); + for (int i = 0; i < 3; ++i) + { + std::string key = "light_enabled_" + std::to_string(i + 1); + setLightEnabled(i, conf->getBool(key) && is_enabled); + } +} + +void Scene::setLightsVisible(const bool &is_visible) +{ + for (int i = 0; i < 3; ++i) + { + LightSource *light = (LightSource*) + SceneManager->getSceneNodeFromId(E_SCENE_ID_LIGHT + i); + light->setMarker(is_visible); + } +} + +void Scene::setLightEnabled(s32 index, const bool &is_enabled) +{ + LightSource *light = (LightSource*) + SceneManager->getSceneNodeFromId(E_SCENE_ID_LIGHT + index); + light->setVisible(is_enabled); +} + void Scene::clearTextures(ISceneNode *node, const std::string &prefix) { for (u32 i = 0; i < node->getMaterialCount(); ++i) diff --git a/src/scene.h b/src/scene.h index 01454da..c84eb62 100644 --- a/src/scene.h +++ b/src/scene.h @@ -15,14 +15,62 @@ enum E_SCENE_AXIS_Z }; +enum +{ + E_SCENE_ID_LIGHT = 0x4000 +}; + using namespace irr; using namespace core; using namespace scene; using namespace gui; using namespace video; +struct ColorSpec +{ + SColor diffuse; + SColor ambient; + SColor specular; +}; + + +struct LightSpec +{ + E_LIGHT_TYPE type; + vector3df position; + vector3df rotation; + f32 radius; + ColorSpec color; +}; + class Config; +class LightSource : public ISceneNode +{ +public: + LightSource(ISceneNode *parent, ISceneManager *smgr, s32 id, + LightSpec lightspec, const wchar_t *text, SColor text_color); + ~LightSource() {} + void setLight(LightSpec lightspec); + void setMarker(const bool &is_visible); + + virtual void OnRegisterSceneNode(); + virtual const aabbox3d &getBoundingBox() const { return box; } + virtual SMaterial &getMaterial(u32 i) { return material; } + virtual u32 getMaterialCount() const { return 1; } + virtual void render(); + +private: + ILightSceneNode *light; + IMeshSceneNode *marker; + ITextSceneNode *label; + stringw texture_name; + SColor line_color; + + aabbox3d box; + SMaterial material; +}; + class Scene : public ISceneNode { public: @@ -39,6 +87,9 @@ public: void setGridColor(SColor color) { grid_color = color; } void setGridVisible(const bool &is_visible) { show_grid = is_visible; } void setAxesVisible(const bool &is_visible) { show_axes = is_visible; } + void setLighting(const bool &is_enabled); + void setLightsVisible(const bool &is_visible); + void setLightEnabled(s32 index, const bool &is_enabled); void setDebugInfo(const bool &is_visible); void rotate(s32 axis, const f32 &step); void refresh(); @@ -51,6 +102,7 @@ public: virtual void render(); private: + void addLights(); void loadTextures(ISceneNode *node, const std::string &prefix); void clearTextures(ISceneNode *node, const std::string &prefix); diff --git a/src/viewer.cpp b/src/viewer.cpp index f2a446f..b6e4012 100644 --- a/src/viewer.cpp +++ b/src/viewer.cpp @@ -184,12 +184,15 @@ bool Viewer::OnEvent(const SEvent &event) case E_GUI_ID_QUIT: device->closeDevice(); break; - case E_GUI_ID_TEXTURES_DIALOG: + case E_DIALOG_ID_TEXTURES: gui->showTexturesDialog(); break; - case E_GUI_ID_SETTINGS_DIALOG: + case E_DIALOG_ID_SETTINGS: gui->showSettingsDialog(); break; + case E_DIALOG_ID_LIGHTS: + gui->showLightsDialog(); + break; case E_GUI_ID_TOOLBOX_MODEL: { if (menu->isItemChecked(item)) @@ -213,6 +216,9 @@ bool Viewer::OnEvent(const SEvent &event) case E_GUI_ID_SHOW_AXES: scene->setAxesVisible(menu->isItemChecked(item)); break; + case E_GUI_ID_SHOW_LIGHTS: + scene->setLightsVisible(menu->isItemChecked(item)); + break; case E_GUI_ID_BILINEAR: scene->setFilter(EMF_BILINEAR_FILTER, menu->isItemChecked(item)); @@ -246,6 +252,21 @@ bool Viewer::OnEvent(const SEvent &event) conf->set("backface_cull", boolToString(menu->isItemChecked(item))); break; + case E_GUI_ID_LIGHT: + case E_GUI_ID_LIGHT + 1: + case E_GUI_ID_LIGHT + 2: + scene->setLightEnabled(menu->getSelectedItem(), + menu->isItemChecked(item)); + conf->set("light_enabled_" + + std::to_string(menu->getSelectedItem() + 1), + boolToString(menu->isItemChecked(item))); + break; + case E_GUI_ID_LIGHTING: + scene->setLighting(menu->isItemChecked(item)); + conf->set("lighting", boolToString(menu->isItemChecked(item))); + menu->setItemEnabled(5, menu->isItemChecked(item)); + menu->setItemEnabled(9, menu->isItemChecked(item)); + break; case E_GUI_ID_DEBUG_INFO: scene->setDebugInfo(menu->isItemChecked(item)); conf->set("debug_info", @@ -401,6 +422,8 @@ bool Viewer::OnEvent(const SEvent &event) break; case E_DIALOG_ID_SETTINGS_CANCEL: case E_DIALOG_ID_TEXTURES_CANCEL: + case E_DIALOG_ID_LIGHTS_CANCEL: + case E_DIALOG_ID_LIGHTS_OK: case E_DIALOG_ID_ABOUT_OK: event.GUIEvent.Caller->getParent()->getParent()->remove(); gui->setFocused(false);