You need to sign in or sign up before continuing.
Commit 1c9b2014 authored by cutealien's avatar cutealien

Cleaning up Meshviewer example. That was too confusing to use and the code got...

Cleaning up Meshviewer example. That was too confusing to use and the code got too long for one file.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4951 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 38d83734
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
<Add library="Irrlicht" /> <Add library="Irrlicht" />
</Linker> </Linker>
<Unit filename="main.cpp" /> <Unit filename="main.cpp" />
<Unit filename="main.h" />
<Extensions> <Extensions>
<code_completion /> <code_completion />
<debugger /> <debugger />
......
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
This example can be used to play around with material settings and watch the results. This example can be used to play around with material settings and watch the results.
Only the default non-shader materials are used in here. Only the default non-shader materials are used in here.
You have two nodes to make it easier to see which difference your settings will make. You have a node witha mesh, one dynamic light and global ambient light to play around with.
Additionally you have one lightscenenode and you can set the global ambient values.
*/ */
#include <irrlicht.h> #include <irrlicht.h>
#include "driverChoice.h" #include "driverChoice.h"
#include "main.h"
using namespace irr; using namespace irr;
...@@ -122,909 +122,757 @@ video::E_VERTEX_TYPE getVertexTypeForMaterialType(video::E_MATERIAL_TYPE materia ...@@ -122,909 +122,757 @@ video::E_VERTEX_TYPE getVertexTypeForMaterialType(video::E_MATERIAL_TYPE materia
/* /*
Custom GUI-control to edit colorvalues. Custom GUI-control to edit colorvalues.
*/ */
class CColorControl : public gui::IGUIElement // Constructor
CColorControl::CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, IGUIElement* parent, s32 id)
: gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos, pos+core::dimension2d<s32>(80, 75)))
, DirtyFlag(true)
, ColorStatic(0)
, EditAlpha(0)
, EditRed(0)
, EditGreen(0)
, EditBlue(0)
{ {
public: using namespace gui;
// Constructor ButtonSetId = makeUniqueId();
CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, IGUIElement* parent, s32 id=-1 )
: gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos, pos+core::dimension2d<s32>(80, 75)))
, DirtyFlag(true)
, ColorStatic(0)
, EditAlpha(0)
, EditRed(0)
, EditGreen(0)
, EditBlue(0)
{
using namespace gui;
ButtonSetId = makeUniqueId();
const core::rect< s32 > rectControls(0,0,AbsoluteRect.getWidth(),AbsoluteRect.getHeight() );
IGUIStaticText * groupElement = guiEnv->addStaticText (L"", rectControls, true, false, this, -1, false);
groupElement->setNotClipped(true);
guiEnv->addStaticText (text, core::rect<s32>(0,0,80,15), false, false, groupElement, -1, false); const core::rect< s32 > rectControls(0,0,AbsoluteRect.getWidth(),AbsoluteRect.getHeight() );
IGUIStaticText * groupElement = guiEnv->addStaticText (L"", rectControls, true, false, this, -1, false);
groupElement->setNotClipped(true);
EditAlpha = addEditForNumbers(guiEnv, core::position2d<s32>(0,15), L"a", -1, groupElement ); guiEnv->addStaticText (text, core::rect<s32>(0,0,80,15), false, false, groupElement, -1, false);
EditRed = addEditForNumbers(guiEnv, core::position2d<s32>(0,30), L"r", -1, groupElement );
EditGreen = addEditForNumbers(guiEnv, core::position2d<s32>(0,45), L"g", -1, groupElement );
EditBlue = addEditForNumbers(guiEnv, core::position2d<s32>(0,60), L"b", -1, groupElement );
ColorStatic = guiEnv->addStaticText (L"", core::rect<s32>(60,15,80,75), true, false, groupElement, -1, true); EditAlpha = addEditForNumbers(guiEnv, core::position2d<s32>(0,15), L"a", -1, groupElement );
EditRed = addEditForNumbers(guiEnv, core::position2d<s32>(0,30), L"r", -1, groupElement );
EditGreen = addEditForNumbers(guiEnv, core::position2d<s32>(0,45), L"g", -1, groupElement );
EditBlue = addEditForNumbers(guiEnv, core::position2d<s32>(0,60), L"b", -1, groupElement );
guiEnv->addButton (core::rect<s32>(60,35,80,50), groupElement, ButtonSetId, L"set"); ColorStatic = guiEnv->addStaticText (L"", core::rect<s32>(60,15,80,75), true, false, groupElement, -1, true);
SetEditsFromColor(Color);
}
// event receiver
virtual bool OnEvent(const SEvent &event)
{
if ( event.EventType != EET_GUI_EVENT )
return false;
if ( event.GUIEvent.Caller->getID() == ButtonSetId && event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) guiEnv->addButton (core::rect<s32>(60,35,80,50), groupElement, ButtonSetId, L"set");
{ setEditsFromColor(Color);
Color = GetColorFromEdits(); }
SetEditsFromColor(Color);
}
// event receiver
bool CColorControl::OnEvent(const SEvent &event)
{
if ( event.EventType != EET_GUI_EVENT )
return false; return false;
}
// set the color values if ( event.GUIEvent.Caller->getID() == ButtonSetId && event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
void setColor(const video::SColor& col)
{ {
DirtyFlag = true; Color = getColorFromEdits();
Color = col; setEditsFromColor(Color);
SetEditsFromColor(Color);
} }
// get the color values return false;
const video::SColor& getColor() const }
{
return Color;
}
// To reset the dirty flag // set the color values
void resetDirty() void CColorControl::setColor(const video::SColor& col)
{ {
DirtyFlag = false; DirtyFlag = true;
} Color = col;
setEditsFromColor(Color);
}
// when the color was changed the dirty flag is set // Add a staticbox for a description + an editbox so users can enter numbers
bool isDirty() const gui::IGUIEditBox* CColorControl::addEditForNumbers(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, s32 id, gui::IGUIElement * parent)
{ {
return DirtyFlag; using namespace gui;
};
core::rect< s32 > rect(pos, pos+core::dimension2d<s32>(10, 15));
guiEnv->addStaticText (text, rect, false, false, parent, -1, false);
rect += core::position2d<s32>( 20, 0 );
rect.LowerRightCorner.X += 20;
gui::IGUIEditBox* edit = guiEnv->addEditBox(L"0", rect, true, parent, id);
return edit;
}
protected: // Get the color value from the editfields
video::SColor CColorControl::getColorFromEdits()
{
video::SColor col;
// Add a staticbox for a description + an editbox so users can enter numbers if (EditAlpha)
gui::IGUIEditBox* addEditForNumbers(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, s32 id, gui::IGUIElement * parent)
{ {
using namespace gui; u32 alpha = core::strtoul10(core::stringc(EditAlpha->getText()).c_str());
if (alpha > 255)
core::rect< s32 > rect(pos, pos+core::dimension2d<s32>(10, 15)); alpha = 255;
guiEnv->addStaticText (text, rect, false, false, parent, -1, false); col.setAlpha(alpha);
rect += core::position2d<s32>( 20, 0 );
rect.LowerRightCorner.X += 20;
gui::IGUIEditBox* edit = guiEnv->addEditBox(L"0", rect, true, parent, id);
return edit;
} }
// Get the color value from the editfields if (EditRed)
video::SColor GetColorFromEdits()
{ {
video::SColor col; u32 red = core::strtoul10(core::stringc(EditRed->getText()).c_str());
if (red > 255)
if (EditAlpha) red = 255;
{ col.setRed(red);
u32 alpha = core::strtoul10(core::stringc(EditAlpha->getText()).c_str()); }
if (alpha > 255)
alpha = 255;
col.setAlpha(alpha);
}
if (EditRed)
{
u32 red = core::strtoul10(core::stringc(EditRed->getText()).c_str());
if (red > 255)
red = 255;
col.setRed(red);
}
if (EditGreen)
{
u32 green = core::strtoul10(core::stringc(EditGreen->getText()).c_str());
if (green > 255)
green = 255;
col.setGreen(green);
}
if (EditBlue)
{
u32 blue = core::strtoul10(core::stringc(EditBlue->getText()).c_str());
if (blue > 255)
blue = 255;
col.setBlue(blue);
}
return col; if (EditGreen)
{
u32 green = core::strtoul10(core::stringc(EditGreen->getText()).c_str());
if (green > 255)
green = 255;
col.setGreen(green);
} }
// Fill the editfields with the value for the given color if (EditBlue)
void SetEditsFromColor(video::SColor col)
{ {
DirtyFlag = true; u32 blue = core::strtoul10(core::stringc(EditBlue->getText()).c_str());
if ( EditAlpha ) if (blue > 255)
EditAlpha->setText( core::stringw(col.getAlpha()).c_str() ); blue = 255;
if ( EditRed ) col.setBlue(blue);
EditRed->setText( core::stringw(col.getRed()).c_str() );
if ( EditGreen )
EditGreen->setText( core::stringw(col.getGreen()).c_str() );
if ( EditBlue )
EditBlue->setText( core::stringw(col.getBlue()).c_str() );
if ( ColorStatic )
ColorStatic->setBackgroundColor(col);
} }
private: return col;
}
bool DirtyFlag; // Fill the editfields with the value for the given color
video::SColor Color; void CColorControl::setEditsFromColor(video::SColor col)
s32 ButtonSetId; {
gui::IGUIStaticText * ColorStatic; DirtyFlag = true;
gui::IGUIEditBox * EditAlpha; if ( EditAlpha )
gui::IGUIEditBox * EditRed; EditAlpha->setText( core::stringw(col.getAlpha()).c_str() );
gui::IGUIEditBox * EditGreen; if ( EditRed )
gui::IGUIEditBox * EditBlue; EditRed->setText( core::stringw(col.getRed()).c_str() );
}; if ( EditGreen )
EditGreen->setText( core::stringw(col.getGreen()).c_str() );
if ( EditBlue )
EditBlue->setText( core::stringw(col.getBlue()).c_str() );
if ( ColorStatic )
ColorStatic->setBackgroundColor(col);
}
/* /*
Custom GUI-control for to edit all colors typically used in materials and lights Custom GUI-control for to edit all colors typically used in materials and lights
*/ */
class CAllColorsControl : public gui::IGUIElement // Constructor
CTypicalColorsControl::CTypicalColorsControl(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, bool hasEmissive, IGUIElement* parent, s32 id)
: gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect<s32>(pos,pos+core::dimension2d<s32>(60,250)))
, ControlAmbientColor(0), ControlDiffuseColor(0), ControlSpecularColor(0), ControlEmissiveColor(0)
{ {
public: ControlAmbientColor = new CColorControl( guiEnv, core::position2d<s32>(0, 0), L"Ambient", this);
// Constructor ControlDiffuseColor = new CColorControl( guiEnv, core::position2d<s32>(0, 75), L"Diffuse", this );
CAllColorsControl(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t * description, bool hasEmissive, IGUIElement* parent, s32 id=-1) ControlSpecularColor = new CColorControl( guiEnv, core::position2d<s32>(0, 150), L"Specular", this );
: gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect<s32>(pos,pos+core::dimension2d<s32>(60,250))) if ( hasEmissive )
, ControlAmbientColor(0), ControlDiffuseColor(0), ControlSpecularColor(0), ControlEmissiveColor(0)
{
core::rect<s32> rect(0, 0, 60, 15);
guiEnv->addStaticText (description, rect, false, false, this, -1, false);
createColorControls(guiEnv, core::position2d<s32>(0, 15), hasEmissive);
}
// Destructor
virtual ~CAllColorsControl()
{ {
ControlAmbientColor->drop(); ControlEmissiveColor = new CColorControl( guiEnv, core::position2d<s32>(0, 225), L"Emissive", this );
ControlDiffuseColor->drop();
if ( ControlEmissiveColor )
ControlEmissiveColor->drop();
ControlSpecularColor->drop();
} }
}
// Set the color values to those within the material // Destructor
void setColorsToMaterialColors(const video::SMaterial & material) CTypicalColorsControl::~CTypicalColorsControl()
{ {
ControlAmbientColor->setColor(material.AmbientColor); ControlAmbientColor->drop();
ControlDiffuseColor->setColor(material.DiffuseColor); ControlDiffuseColor->drop();
ControlEmissiveColor->setColor(material.EmissiveColor); if ( ControlEmissiveColor )
ControlSpecularColor->setColor(material.SpecularColor); ControlEmissiveColor->drop();
} ControlSpecularColor->drop();
}
// Update all changed colors in the material // Set the color values to those within the material
void updateMaterialColors(video::SMaterial & material) void CTypicalColorsControl::setColorsToMaterialColors(const video::SMaterial & material)
{ {
if ( ControlAmbientColor->isDirty() ) ControlAmbientColor->setColor(material.AmbientColor);
material.AmbientColor = ControlAmbientColor->getColor(); ControlDiffuseColor->setColor(material.DiffuseColor);
if ( ControlDiffuseColor->isDirty() ) ControlEmissiveColor->setColor(material.EmissiveColor);
material.DiffuseColor = ControlDiffuseColor->getColor(); ControlSpecularColor->setColor(material.SpecularColor);
if ( ControlEmissiveColor->isDirty() ) }
material.EmissiveColor = ControlEmissiveColor->getColor();
if ( ControlSpecularColor->isDirty() )
material.SpecularColor = ControlSpecularColor->getColor();
}
// Set the color values to those from the light data // Update all changed colors in the material
void setColorsToLightDataColors(const video::SLight & lightData) void CTypicalColorsControl::updateMaterialColors(video::SMaterial & material)
{ {
ControlAmbientColor->setColor(lightData.AmbientColor.toSColor()); if ( ControlAmbientColor->isDirty() )
ControlAmbientColor->setColor(lightData.DiffuseColor.toSColor()); material.AmbientColor = ControlAmbientColor->getColor();
ControlAmbientColor->setColor(lightData.SpecularColor.toSColor()); if ( ControlDiffuseColor->isDirty() )
} material.DiffuseColor = ControlDiffuseColor->getColor();
if ( ControlEmissiveColor->isDirty() )
material.EmissiveColor = ControlEmissiveColor->getColor();
if ( ControlSpecularColor->isDirty() )
material.SpecularColor = ControlSpecularColor->getColor();
}
// Update all changed colors in the light data // Set the color values to those from the light data
void updateLightColors(video::SLight & lightData) void CTypicalColorsControl::setColorsToLightDataColors(const video::SLight & lightData)
{ {
if ( ControlAmbientColor->isDirty() ) ControlAmbientColor->setColor(lightData.AmbientColor.toSColor());
lightData.AmbientColor = video::SColorf( ControlAmbientColor->getColor() ); ControlAmbientColor->setColor(lightData.DiffuseColor.toSColor());
if ( ControlDiffuseColor->isDirty() ) ControlAmbientColor->setColor(lightData.SpecularColor.toSColor());
lightData.DiffuseColor = video::SColorf( ControlDiffuseColor->getColor() ); }
if ( ControlSpecularColor->isDirty() )
lightData.SpecularColor = video::SColorf(ControlSpecularColor->getColor() );
}
// To reset the dirty flags // Update all changed colors in the light data
void resetDirty() void CTypicalColorsControl::updateLightColors(video::SLight & lightData) const
{ {
ControlAmbientColor->resetDirty(); if ( ControlAmbientColor->isDirty() )
ControlDiffuseColor->resetDirty(); lightData.AmbientColor = video::SColorf( ControlAmbientColor->getColor() );
ControlSpecularColor->resetDirty(); if ( ControlDiffuseColor->isDirty() )
if ( ControlEmissiveColor ) lightData.DiffuseColor = video::SColorf( ControlDiffuseColor->getColor() );
ControlEmissiveColor->resetDirty(); if ( ControlSpecularColor->isDirty() )
} lightData.SpecularColor = video::SColorf(ControlSpecularColor->getColor() );
}
protected: // To reset the dirty flags
void createColorControls(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, bool hasEmissive) void CTypicalColorsControl::resetDirty()
{ {
ControlAmbientColor = new CColorControl( guiEnv, pos, L"ambient", this); ControlAmbientColor->resetDirty();
ControlDiffuseColor = new CColorControl( guiEnv, pos + core::position2d<s32>(0, 75), L"diffuse", this ); ControlDiffuseColor->resetDirty();
ControlSpecularColor = new CColorControl( guiEnv, pos + core::position2d<s32>(0, 150), L"specular", this ); ControlSpecularColor->resetDirty();
if ( hasEmissive ) if ( ControlEmissiveColor )
{ ControlEmissiveColor->resetDirty();
ControlEmissiveColor = new CColorControl( guiEnv, pos + core::position2d<s32>(0, 225), L"emissive", this ); }
}
}
private:
CColorControl* ControlAmbientColor;
CColorControl* ControlDiffuseColor;
CColorControl* ControlSpecularColor;
CColorControl* ControlEmissiveColor;
};
/* /*
GUI-Control to offer a selection of available textures. GUI-Control to offer a selection of available textures.
*/ */
class CTextureControl : public gui::IGUIElement CTextureControl::CTextureControl(gui::IGUIEnvironment* guiEnv, video::IVideoDriver * driver, const core::position2d<s32> & pos, IGUIElement* parent, s32 id)
: gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect<s32>(pos,pos+core::dimension2d<s32>(150,15)))
, DirtyFlag(true), ComboTexture(0)
{ {
public: core::rect<s32> rectCombo(0, 0, AbsoluteRect.getWidth(),AbsoluteRect.getHeight());
CTextureControl(gui::IGUIEnvironment* guiEnv, video::IVideoDriver * driver, const core::position2d<s32> & pos, IGUIElement* parent, s32 id=-1) ComboTexture = guiEnv->addComboBox (rectCombo, this);
: gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect<s32>(pos,pos+core::dimension2d<s32>(100,15))) updateTextures(driver);
, DirtyFlag(true), ComboTexture(0) }
{
core::rect<s32> rectCombo(0, 0, AbsoluteRect.getWidth(),AbsoluteRect.getHeight());
ComboTexture = guiEnv->addComboBox (rectCombo, this);
updateTextures(driver);
}
virtual bool OnEvent(const SEvent &event)
{
if ( event.EventType != EET_GUI_EVENT )
return false;
if ( event.GUIEvent.Caller == ComboTexture && event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED )
{
DirtyFlag = true;
}
bool CTextureControl::OnEvent(const SEvent &event)
{
if ( event.EventType != EET_GUI_EVENT )
return false; return false;
}
// Workaround for a problem with comboboxes. if ( event.GUIEvent.Caller == ComboTexture && event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED )
// We have to get in front when the combobox wants to get in front or combobox-list might be drawn below other elements.
virtual bool bringToFront(IGUIElement* element)
{ {
bool result = gui::IGUIElement::bringToFront(element); DirtyFlag = true;
if ( Parent && element == ComboTexture )
result &= Parent->bringToFront(this);
return result;
} }
// return selected texturename (if any, otherwise 0) return false;
const wchar_t * getSelectedTextureName() const }
{
s32 selected = ComboTexture->getSelected();
if ( selected < 0 )
return 0;
return ComboTexture->getItem(selected);
}
// reset the dirty flag // Workaround for a problem with comboboxes.
void resetDirty() // We have to get in front when the combobox wants to get in front or combobox-list might be drawn below other elements.
{ bool CTextureControl::bringToFront(IGUIElement* element)
DirtyFlag = false; {
} bool result = gui::IGUIElement::bringToFront(element);
if ( Parent && element == ComboTexture )
result &= Parent->bringToFront(this);
return result;
}
// when the texture was changed the dirty flag is set // return selected texturename (if any, otherwise 0)
bool isDirty() const const wchar_t * CTextureControl::getSelectedTextureName() const
{ {
return DirtyFlag; s32 selected = ComboTexture->getSelected();
}; if ( selected < 0 )
return 0;
return ComboTexture->getItem(selected);
}
// Put the names of all currently loaded textures in a combobox void CTextureControl::selectTextureByName(const irr::core::stringw& name)
void updateTextures(video::IVideoDriver * driver) {
for (u32 i=0; i< ComboTexture->getItemCount(); ++i)
{ {
s32 oldSelected = ComboTexture->getSelected(); if ( name == ComboTexture->getItem(i))
s32 selectNew = -1;
core::stringw oldTextureName;
if ( oldSelected >= 0 )
{ {
oldTextureName = ComboTexture->getItem(oldSelected); ComboTexture->setSelected(i);
} DirtyFlag = true;
ComboTexture->clear(); return;
for ( u32 i=0; i < driver->getTextureCount(); ++i )
{
video::ITexture * texture = driver->getTextureByIndex(i);
core::stringw name( texture->getName() );
ComboTexture->addItem( name.c_str() );
if ( !oldTextureName.empty() && selectNew < 0 && name == oldTextureName )
selectNew = i;
} }
}
}
// add another name which can be used to clear the texture // Put the names of all currently loaded textures in a combobox
ComboTexture->addItem( CLEAR_TEXTURE.c_str() ); void CTextureControl::updateTextures(video::IVideoDriver * driver)
if ( CLEAR_TEXTURE == oldTextureName ) {
selectNew = ComboTexture->getItemCount()-1; s32 oldSelected = ComboTexture->getSelected();
s32 selectNew = -1;
core::stringw oldTextureName;
if ( oldSelected >= 0 )
{
oldTextureName = ComboTexture->getItem(oldSelected);
}
ComboTexture->clear();
for ( u32 i=0; i < driver->getTextureCount(); ++i )
{
video::ITexture * texture = driver->getTextureByIndex(i);
core::stringw name( texture->getName() );
ComboTexture->addItem( name.c_str() );
if ( !oldTextureName.empty() && selectNew < 0 && name == oldTextureName )
selectNew = i;
}
if ( selectNew >= 0 ) // add another name which can be used to clear the texture
ComboTexture->setSelected(selectNew); ComboTexture->addItem( CLEAR_TEXTURE.c_str() );
if ( CLEAR_TEXTURE == oldTextureName )
selectNew = ComboTexture->getItemCount()-1;
DirtyFlag = true; if ( selectNew >= 0 )
} ComboTexture->setSelected(selectNew);
private: DirtyFlag = true;
bool DirtyFlag; }
gui::IGUIComboBox * ComboTexture;
};
/* /*
Control which allows setting some of the material values for a meshscenenode Control which allows setting some of the material values for a meshscenenode
*/ */
struct SMeshNodeControl void SMaterialControl::init(scene::IMeshSceneNode* node, IrrlichtDevice * device, const core::position2d<s32> & pos, const wchar_t * description)
{ {
// constructor if ( Initialized || !node || !device) // initializing twice or with invalid data not allowed
SMeshNodeControl() return;
: Initialized(false), Driver(0), MeshManipulator(0), SceneNode(0), SceneNode2T(0), SceneNodeTangents(0)
, AllColorsControl(0), ButtonLighting(0), InfoLighting(0), ComboMaterial(0), TextureControl1(0), TextureControl2(0), ControlVertexColors(0)
{
}
// Destructor Driver = device->getVideoDriver ();
virtual ~SMeshNodeControl() gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment();
{ scene::ISceneManager* smgr = device->getSceneManager();
if ( TextureControl1 ) const video::SMaterial & material = node->getMaterial(0);
TextureControl1->drop();
if ( TextureControl2 )
TextureControl2->drop();
if ( ControlVertexColors )
ControlVertexColors->drop();
if ( AllColorsControl )
AllColorsControl->drop();
}
void init(scene::IMeshSceneNode* node, IrrlichtDevice * device, const core::position2d<s32> & pos, const wchar_t * description) s32 top = pos.Y;
{
if ( Initialized || !node || !device) // initializing twice or with invalid data not allowed
return;
Driver = device->getVideoDriver (); // Description
gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment(); guiEnv->addStaticText(description, core::rect<s32>(pos.X, top, pos.X+60, top+15), false, false, 0, -1, false);
scene::ISceneManager* smgr = device->getSceneManager(); top += 15;
MeshManipulator = smgr->getMeshManipulator();
SceneNode = node;
scene::IMeshManipulator * meshManip = smgr->getMeshManipulator();
scene::IMesh * mesh2T = meshManip->createMeshWith2TCoords(node->getMesh());
SceneNode2T = smgr->addMeshSceneNode(mesh2T, 0, -1, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
mesh2T->drop();
scene::IMesh * meshTangents = meshManip->createMeshWithTangents(node->getMesh(), false, false, false);
SceneNodeTangents = smgr->addMeshSceneNode(meshTangents, 0, -1
, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
meshTangents->drop();
video::SMaterial & material = SceneNode->getMaterial(0);
material.Lighting = true;
AllColorsControl = new CAllColorsControl(guiEnv, pos, description, true, guiEnv->getRootGUIElement());
AllColorsControl->setColorsToMaterialColors(material);
core::rect<s32> rectBtn(pos + core::position2d<s32>(0, 320), core::dimension2d<s32>(60, 15));
ButtonLighting = guiEnv->addButton (rectBtn, 0, -1, L"Lighting");
ButtonLighting->setIsPushButton(true);
ButtonLighting->setPressed(material.Lighting);
core::rect<s32> rectInfo( rectBtn.LowerRightCorner.X, rectBtn.UpperLeftCorner.Y, rectBtn.LowerRightCorner.X+40, rectBtn.UpperLeftCorner.Y+15 );
InfoLighting = guiEnv->addStaticText(L"", rectInfo, true, false );
InfoLighting->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER );
core::rect<s32> rectCombo(pos.X, rectBtn.LowerRightCorner.Y, pos.X+100, rectBtn.LowerRightCorner.Y+15);
ComboMaterial = guiEnv->addComboBox (rectCombo);
for ( int i=0; i <= (int)video::EMT_ONETEXTURE_BLEND; ++i )
{
ComboMaterial->addItem( core::stringw(video::sBuiltInMaterialTypeNames[i]).c_str() );
}
ComboMaterial->setSelected( (s32)material.MaterialType );
core::position2d<s32> posTex(rectCombo.UpperLeftCorner.X,rectCombo.LowerRightCorner.Y); // Control for material type
TextureControl1 = new CTextureControl(guiEnv, Driver, posTex, guiEnv->getRootGUIElement()); core::rect<s32> rectCombo(pos.X, top, 150, top+15);
posTex.Y += 15; top += 15;
TextureControl2 = new CTextureControl(guiEnv, Driver, posTex, guiEnv->getRootGUIElement()); ComboMaterial = guiEnv->addComboBox (rectCombo);
for ( int i=0; i <= (int)video::EMT_ONETEXTURE_BLEND; ++i )
{
ComboMaterial->addItem( core::stringw(video::sBuiltInMaterialTypeNames[i]).c_str() );
}
ComboMaterial->setSelected( (s32)material.MaterialType );
core::position2d<s32> posVertexColors( posTex.X, posTex.Y + 15); // Control to enable/disabling material lighting
ControlVertexColors = new CColorControl( guiEnv, posVertexColors, L"Vertex colors", guiEnv->getRootGUIElement()); core::rect<s32> rectBtn(core::position2d<s32>(pos.X, top), core::dimension2d<s32>(100, 15));
top += 15;
ButtonLighting = guiEnv->addButton (rectBtn, 0, -1, L"Lighting");
ButtonLighting->setIsPushButton(true);
ButtonLighting->setPressed(material.Lighting);
core::rect<s32> rectInfo( rectBtn.LowerRightCorner.X, rectBtn.UpperLeftCorner.Y, rectBtn.LowerRightCorner.X+40, rectBtn.UpperLeftCorner.Y+15 );
InfoLighting = guiEnv->addStaticText(L"", rectInfo, true, false );
InfoLighting->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER );
video::S3DVertex * vertices = (video::S3DVertex *)node->getMesh()->getMeshBuffer(0)->getVertices(); // Controls for colors
if ( vertices ) TypicalColorsControl = new CTypicalColorsControl(guiEnv, core::position2d<s32>(pos.X, top), true, guiEnv->getRootGUIElement());
{ top += 300;
ControlVertexColors->setColor(vertices[0].Color); TypicalColorsControl->setColorsToMaterialColors(material);
}
Initialized = true; // Controls for selecting the material textures
guiEnv->addStaticText(L"Textures", core::rect<s32>(pos.X, top, pos.X+60, top+15), false, false, 0, -1, false);
top += 15;
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
{
TextureControls[i] = new CTextureControl(guiEnv, Driver, core::position2di(pos.X, top), guiEnv->getRootGUIElement());
top += 15;
} }
void update() Initialized = true;
{ }
if ( !Initialized )
return;
video::SMaterial & material = SceneNode->getMaterial(0); void SMaterialControl::update(scene::IMeshSceneNode* sceneNode, scene::IMeshSceneNode* sceneNode2T, scene::IMeshSceneNode* sceneNodeTangents)
video::SMaterial & material2T = SceneNode2T->getMaterial(0); {
video::SMaterial & materialTangents = SceneNodeTangents->getMaterial(0); if ( !Initialized )
return;
video::SMaterial & material = sceneNode->getMaterial(0);
video::SMaterial & material2T = sceneNode2T->getMaterial(0);
video::SMaterial & materialTangents = sceneNodeTangents->getMaterial(0);
s32 selectedMaterial = ComboMaterial->getSelected(); s32 selectedMaterial = ComboMaterial->getSelected();
if ( selectedMaterial >= (s32)video::EMT_SOLID && selectedMaterial <= (s32)video::EMT_ONETEXTURE_BLEND) if ( selectedMaterial >= (s32)video::EMT_SOLID && selectedMaterial <= (s32)video::EMT_ONETEXTURE_BLEND)
{
// Show the node which has a mesh to work with the currently selected material
video::E_VERTEX_TYPE vertexType = getVertexTypeForMaterialType((video::E_MATERIAL_TYPE)selectedMaterial);
switch ( vertexType )
{ {
video::E_VERTEX_TYPE vertexType = getVertexTypeForMaterialType((video::E_MATERIAL_TYPE)selectedMaterial); case video::EVT_STANDARD:
switch ( vertexType ) material.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial;
{ sceneNode->setVisible(true);
case video::EVT_STANDARD: sceneNode2T->setVisible(false);
material.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; sceneNodeTangents->setVisible(false);
SceneNode->setVisible(true); break;
SceneNode2T->setVisible(false); case video::EVT_2TCOORDS:
SceneNodeTangents->setVisible(false); material2T.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial;
break; sceneNode->setVisible(false);
case video::EVT_2TCOORDS: sceneNode2T->setVisible(true);
material2T.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; sceneNodeTangents->setVisible(false);
SceneNode->setVisible(false); break;
SceneNode2T->setVisible(true); case video::EVT_TANGENTS:
SceneNodeTangents->setVisible(false); materialTangents.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial;
break; sceneNode->setVisible(false);
case video::EVT_TANGENTS: sceneNode2T->setVisible(false);
materialTangents.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; sceneNodeTangents->setVisible(true);
SceneNode->setVisible(false); break;
SceneNode2T->setVisible(false);
SceneNodeTangents->setVisible(true);
break;
}
} }
}
updateMaterial(material); // Always update materials of all nodes, otherwise the tool is confusing to use.
updateMaterial(material2T); updateMaterial(material);
updateMaterial(materialTangents); updateMaterial(material2T);
updateMaterial(materialTangents);
if ( ButtonLighting->isPressed() ) if ( ButtonLighting->isPressed() )
InfoLighting->setText(L"on"); InfoLighting->setText(L"is on");
else else
InfoLighting->setText(L"off"); InfoLighting->setText(L"is off");
AllColorsControl->resetDirty(); TypicalColorsControl->resetDirty();
TextureControl1->resetDirty();
TextureControl2->resetDirty();
ControlVertexColors->resetDirty();
}
void updateTextures() for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
{ TextureControls[i]->resetDirty();
TextureControl1->updateTextures(Driver); }
TextureControl2->updateTextures(Driver);
}
protected: void SMaterialControl::updateTextures()
{
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
TextureControls[i]->updateTextures(Driver);
}
void SMaterialControl::selectTextures(const irr::core::stringw& name)
{
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
TextureControls[i]->selectTextureByName(name);
}
void updateMaterial(video::SMaterial & material) void SMaterialControl::updateMaterial(video::SMaterial & material)
{
TypicalColorsControl->updateMaterialColors(material);
material.Lighting = ButtonLighting->isPressed();
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
{ {
AllColorsControl->updateMaterialColors(material); if ( TextureControls[i]->isDirty() )
material.Lighting = ButtonLighting->isPressed();
if ( TextureControl1->isDirty() )
{
material.TextureLayer[0].Texture = Driver->getTexture( io::path(TextureControl1->getSelectedTextureName()) );
}
if ( TextureControl2->isDirty() )
{
material.TextureLayer[1].Texture = Driver->getTexture( io::path(TextureControl2->getSelectedTextureName()) );
}
if ( ControlVertexColors->isDirty() )
{ {
MeshManipulator->setVertexColors (SceneNode->getMesh(), ControlVertexColors->getColor()); material.TextureLayer[i].Texture = Driver->getTexture( io::path(TextureControls[i]->getSelectedTextureName()) );
MeshManipulator->setVertexColors (SceneNode2T->getMesh(), ControlVertexColors->getColor());
MeshManipulator->setVertexColors (SceneNodeTangents->getMesh(), ControlVertexColors->getColor());
} }
} }
}
bool Initialized;
video::IVideoDriver * Driver;
scene::IMeshManipulator* MeshManipulator;
scene::IMeshSceneNode* SceneNode;
scene::IMeshSceneNode* SceneNode2T;
scene::IMeshSceneNode* SceneNodeTangents;
CAllColorsControl* AllColorsControl;
gui::IGUIButton * ButtonLighting;
gui::IGUIStaticText* InfoLighting;
gui::IGUIComboBox * ComboMaterial;
CTextureControl* TextureControl1;
CTextureControl* TextureControl2;
CColorControl* ControlVertexColors;
};
/* /*
Control to allow setting the color values of a lightscenenode. Control to allow setting the color values of a lightscenenode.
*/ */
struct SLightNodeControl
{
// constructor
SLightNodeControl() : Initialized(false), SceneNode(0), AllColorsControl(0)
{
}
virtual ~SLightNodeControl()
{
if ( AllColorsControl )
AllColorsControl->drop();
}
void init(scene::ILightSceneNode* node, gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t * description) void SLightNodeControl::init(scene::ILightSceneNode* node, gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t * description)
{ {
if ( Initialized || !node || !guiEnv) // initializing twice or with invalid data not allowed if ( Initialized || !node || !guiEnv) // initializing twice or with invalid data not allowed
return; return;
SceneNode = node;
AllColorsControl = new CAllColorsControl(guiEnv, pos, description, false, guiEnv->getRootGUIElement()); guiEnv->addStaticText(description, core::rect<s32>(pos.X, pos.Y, pos.X+70, pos.Y+15), false, false, 0, -1, false);
const video::SLight & lightData = SceneNode->getLightData(); TypicalColorsControl = new CTypicalColorsControl(guiEnv, core::position2d<s32>(pos.X, pos.Y+15), false, guiEnv->getRootGUIElement());
AllColorsControl->setColorsToLightDataColors(lightData); const video::SLight & lightData = node->getLightData();
Initialized = true; TypicalColorsControl->setColorsToLightDataColors(lightData);
} Initialized = true;
}
void update()
{
if ( !Initialized )
return;
video::SLight & lightData = SceneNode->getLightData(); void SLightNodeControl::update(scene::ILightSceneNode* node)
AllColorsControl->updateLightColors(lightData); {
} if ( !Initialized )
return;
protected: video::SLight & lightData = node->getLightData();
bool Initialized; TypicalColorsControl->updateLightColors(lightData);
scene::ILightSceneNode* SceneNode; }
CAllColorsControl* AllColorsControl;
};
/* /*
Application configuration Main application class
*/ */
struct SConfig
{
SConfig()
: RenderInBackground(true)
, DriverType(video::EDT_BURNINGSVIDEO)
, ScreenSize(640, 480)
{
}
bool RenderInBackground;
video::E_DRIVER_TYPE DriverType;
core::dimension2d<u32> ScreenSize;
};
/* /*
Main application class Event handler
*/ */
class CApp : public IEventReceiver bool CApp::OnEvent(const SEvent &event)
{ {
friend int main(int argc, char *argv[]); if (event.EventType == EET_GUI_EVENT)
public:
// constructor
CApp()
: IsRunning(false)
, Device(0)
, Camera(0)
, GlobalAmbient(0)
{ {
} gui::IGUIEnvironment* env = Device->getGUIEnvironment();
// destructor
~CApp()
{
}
// stop running - will quit at end of mainloop switch(event.GUIEvent.EventType)
void stopApp()
{
IsRunning = false;
}
// Event handler
virtual bool OnEvent(const SEvent &event)
{
if (event.EventType == EET_GUI_EVENT)
{ {
gui::IGUIEnvironment* env = Device->getGUIEnvironment(); case gui::EGET_MENU_ITEM_SELECTED:
switch(event.GUIEvent.EventType)
{ {
case gui::EGET_MENU_ITEM_SELECTED: gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)event.GUIEvent.Caller;
{ s32 id = menu->getItemCommandId(menu->getSelectedItem());
gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)event.GUIEvent.Caller;
s32 id = menu->getItemCommandId(menu->getSelectedItem());
switch(id)
{
case GUI_ID_OPEN_TEXTURE: // File -> Open Texture
env->addFileOpenDialog(L"Please select a texture file to open");
break;
case GUI_ID_QUIT: // File -> Quit
stopApp();
break;
}
}
break;
case gui::EGET_FILE_SELECTED: switch(id)
{ {
// load the model file, selected in the file open dialog case GUI_ID_OPEN_TEXTURE: // File -> Open Texture
gui::IGUIFileOpenDialog* dialog = env->addFileOpenDialog(L"Please select a texture file to open");
(gui::IGUIFileOpenDialog*)event.GUIEvent.Caller; break;
loadTexture(io::path(dialog->getFileName()).c_str()); case GUI_ID_QUIT: // File -> Quit
setRunning(false);
break;
} }
break; }
break;
default: case gui::EGET_FILE_SELECTED:
break; {
// load the model file, selected in the file open dialog
gui::IGUIFileOpenDialog* dialog =
(gui::IGUIFileOpenDialog*)event.GUIEvent.Caller;
loadTexture(io::path(dialog->getFileName()).c_str());
} }
} break;
return false; default:
break;
}
} }
protected: return false;
}
// Application initialization // Application initialization
// returns true when it was successful initialized, otherwise false. // returns true when it was successful initialized, otherwise false.
bool init(int argc, char *argv[]) bool CApp::init(int argc, char *argv[])
{ {
// ask user for driver // ask user for driver
Config.DriverType=driverChoiceConsole(); Config.DriverType=driverChoiceConsole();
if (Config.DriverType==video::EDT_COUNT) if (Config.DriverType==video::EDT_COUNT)
return false; return false;
// create the device with the settings from our config
Device = createDevice(Config.DriverType, Config.ScreenSize);
if (!Device)
return false;
Device->setWindowCaption( core::stringw(video::DRIVER_TYPE_NAMES[Config.DriverType]).c_str() );
Device->setEventReceiver(this);
scene::ISceneManager* smgr = Device->getSceneManager(); // create the device with the settings from our config
video::IVideoDriver * driver = Device->getVideoDriver (); Device = createDevice(Config.DriverType, Config.ScreenSize);
gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment(); if (!Device)
return false;
Device->setWindowCaption( core::stringw(video::DRIVER_TYPE_NAMES[Config.DriverType]).c_str() );
Device->setEventReceiver(this);
scene::ISceneManager* smgr = Device->getSceneManager();
video::IVideoDriver * driver = Device->getVideoDriver ();
gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
MeshManipulator = smgr->getMeshManipulator();
// set a nicer font
gui::IGUISkin* skin = guiEnv->getSkin();
gui::IGUIFont* font = guiEnv->getFont("../../media/fonthaettenschweiler.bmp");
if (font)
skin->setFont(font);
// remove some alpha value because it makes those menus harder to read otherwise
video::SColor col3dHighLight( skin->getColor(gui::EGDC_APP_WORKSPACE) );
col3dHighLight.setAlpha(255);
video::SColor colHighLight( col3dHighLight );
skin->setColor(gui::EGDC_HIGH_LIGHT, colHighLight );
skin->setColor(gui::EGDC_3D_HIGH_LIGHT, col3dHighLight );
// Add some textures which are useful to test material settings
createDefaultTextures(driver);
// create a menu
gui::IGUIContextMenu * menuBar = guiEnv->addMenu();
menuBar->addItem(L"File", -1, true, true);
gui::IGUIContextMenu* subMenuFile = menuBar->getSubMenu(0);
subMenuFile->addItem(L"Open texture ...", GUI_ID_OPEN_TEXTURE);
subMenuFile->addSeparator();
subMenuFile->addItem(L"Quit", GUI_ID_QUIT);
const s32 controlsTop = 20;
// a static camera
Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 40, -40),
core::vector3df(0, 10, 0),
-1);
// add the nodes which are used to show the materials
SceneNode = smgr->addCubeSceneNode (30.0f, 0, -1,
core::vector3df(0, 0, 0),
core::vector3df(0.f, 45.f, 0.f),
core::vector3df(1.0f, 1.0f, 1.0f));
MeshMaterialControl.init( SceneNode, Device, core::position2d<s32>(10,controlsTop), L"Material" );
MeshMaterialControl.selectTextures(core::stringw("CARO_A8R8G8B8")); // set a useful default texture
// create nodes with other vertex types
scene::IMesh * mesh2T = MeshManipulator->createMeshWith2TCoords(SceneNode->getMesh());
SceneNode2T = smgr->addMeshSceneNode(mesh2T, 0, -1, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
mesh2T->drop();
scene::IMesh * meshTangents = MeshManipulator->createMeshWithTangents(SceneNode->getMesh(), false, false, false);
SceneNodeTangents = smgr->addMeshSceneNode(meshTangents, 0, -1
, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
meshTangents->drop();
// add one light
NodeLight = smgr->addLightSceneNode(0, Camera->getPosition(),
video::SColorf(1.0f, 1.0f, 1.0f),
35.0f);
LightControl.init(NodeLight, guiEnv, core::position2d<s32>(550,controlsTop), L"Dynamic light" );
// one large cube around everything. That's mainly to make the light more obvious.
scene::IMeshSceneNode* backgroundCube = smgr->addCubeSceneNode (200.0f, 0, -1, core::vector3df(0, 0, 0),
core::vector3df(45, 0, 0),
core::vector3df(1.0f, 1.0f, 1.0f));
backgroundCube->getMaterial(0).BackfaceCulling = false; // we are within the cube, so we have to disable backface culling to see it
backgroundCube->getMaterial(0).EmissiveColor.set(255,50,50,50); // we keep some self lighting to keep texts visible
// Add a the mesh vertex color control
guiEnv->addStaticText(L"Mesh", core::rect<s32>(200, controlsTop, 270, controlsTop+15), false, false, 0, -1, false);
ControlVertexColors = new CColorControl( guiEnv, core::position2d<s32>(200, controlsTop+15), L"Vertex colors", guiEnv->getRootGUIElement());
video::S3DVertex * vertices = (video::S3DVertex *)SceneNode->getMesh()->getMeshBuffer(0)->getVertices();
if ( vertices )
{
ControlVertexColors->setColor(vertices[0].Color);
}
// Add a control for ambient light
GlobalAmbient = new CColorControl( guiEnv, core::position2d<s32>(550, 300), L"Global ambient", guiEnv->getRootGUIElement());
GlobalAmbient->setColor( smgr->getAmbientLight().toSColor() );
return true;
}
// set a nicer font /*
gui::IGUISkin* skin = guiEnv->getSkin(); Update one frame
gui::IGUIFont* font = guiEnv->getFont("../../media/fonthaettenschweiler.bmp"); */
if (font) bool CApp::update()
skin->setFont(font); {
using namespace irr;
// remove some alpha value because it makes those menus harder to read otherwise
video::SColor col3dHighLight( skin->getColor(gui::EGDC_APP_WORKSPACE) );
col3dHighLight.setAlpha(255);
video::SColor colHighLight( col3dHighLight );
skin->setColor(gui::EGDC_HIGH_LIGHT, colHighLight );
skin->setColor(gui::EGDC_3D_HIGH_LIGHT, col3dHighLight );
// Add some textures which are useful to test material settings
createDefaultTextures(driver);
// create a menu
gui::IGUIContextMenu * menuBar = guiEnv->addMenu();
menuBar->addItem(L"File", -1, true, true);
gui::IGUIContextMenu* subMenuFile = menuBar->getSubMenu(0);
subMenuFile->addItem(L"Open texture ...", GUI_ID_OPEN_TEXTURE);
subMenuFile->addSeparator();
subMenuFile->addItem(L"Quit", GUI_ID_QUIT);
// a static camera
Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 0, 0),
core::vector3df(0, 0, 100),
-1);
// add the nodes which are used to show the materials
scene::IMeshSceneNode* nodeL = smgr->addCubeSceneNode (30.0f, 0, -1,
core::vector3df(-35, 0, 100),
core::vector3df(0, 0, 0),
core::vector3df(1.0f, 1.0f, 1.0f));
NodeLeft.init( nodeL, Device, core::position2d<s32>(10,20), L"left node" );
scene::IMeshSceneNode* nodeR = smgr->addCubeSceneNode (30.0f, 0, -1,
core::vector3df(35, 0, 100),
core::vector3df(0, 0, 0),
core::vector3df(1.0f, 1.0f, 1.0f));
NodeRight.init( nodeR, Device, core::position2d<s32>(530,20), L"right node" );
// add one light
scene::ILightSceneNode* nodeLight = smgr->addLightSceneNode(0, core::vector3df(0, 0, 0),
video::SColorf(1.0f, 1.0f, 1.0f),
100.0f);
LightControl.init(nodeLight, guiEnv, core::position2d<s32>(270,20), L"light" );
// one large cube around everything. That's mainly to make the light more obvious.
scene::IMeshSceneNode* backgroundCube = smgr->addCubeSceneNode (200.0f, 0, -1, core::vector3df(0, 0, 0),
core::vector3df(45, 0, 0),
core::vector3df(1.0f, 1.0f, 1.0f));
backgroundCube->getMaterial(0).BackfaceCulling = false; // we are within the cube, so we have to disable backface culling to see it
backgroundCube->getMaterial(0).EmissiveColor.set(255,50,50,50); // we keep some self lighting to keep texts visible
// set the ambient light value
GlobalAmbient = new CColorControl( guiEnv, core::position2d<s32>(270, 300), L"global ambient", guiEnv->getRootGUIElement());
GlobalAmbient->setColor( smgr->getAmbientLight().toSColor() );
return true;
}
// Update one frame video::IVideoDriver* videoDriver = Device->getVideoDriver();
bool update() if ( !Device->run() )
return false;
if ( Device->isWindowActive() || Config.RenderInBackground )
{ {
using namespace irr; gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
scene::ISceneManager* smgr = Device->getSceneManager();
gui::IGUISkin * skin = guiEnv->getSkin();
video::IVideoDriver* videoDriver = Device->getVideoDriver(); // update our controls
if ( !Device->run() ) MeshMaterialControl.update(SceneNode, SceneNode2T, SceneNodeTangents);
return false; LightControl.update(NodeLight);
if ( Device->isWindowActive() || Config.RenderInBackground ) // Update vertices
if ( ControlVertexColors->isDirty() )
{ {
gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment(); MeshManipulator->setVertexColors (SceneNode->getMesh(), ControlVertexColors->getColor());
scene::ISceneManager* smgr = Device->getSceneManager(); MeshManipulator->setVertexColors (SceneNode2T->getMesh(), ControlVertexColors->getColor());
gui::IGUISkin * skin = guiEnv->getSkin(); MeshManipulator->setVertexColors (SceneNodeTangents->getMesh(), ControlVertexColors->getColor());
ControlVertexColors->resetDirty();
// update our controls }
NodeLeft.update();
NodeRight.update();
LightControl.update();
// update ambient light settings
if ( GlobalAmbient->isDirty() )
{
smgr->setAmbientLight( GlobalAmbient->getColor() );
GlobalAmbient->resetDirty();
}
// draw everything // update ambient light settings
video::SColor bkColor( skin->getColor(gui::EGDC_APP_WORKSPACE) ); if ( GlobalAmbient->isDirty() )
videoDriver->beginScene(true, true, bkColor); {
smgr->setAmbientLight( GlobalAmbient->getColor() );
GlobalAmbient->resetDirty();
}
smgr->drawAll(); // draw everything
guiEnv->drawAll(); video::SColor bkColor( skin->getColor(gui::EGDC_APP_WORKSPACE) );
videoDriver->beginScene(true, true, bkColor);
videoDriver->endScene(); smgr->drawAll();
} guiEnv->drawAll();
return true; videoDriver->endScene();
} }
// Run the application. Our main loop. // be nice
void run() Device->sleep( 5 );
{
IsRunning = true;
if ( !Device ) return true;
return; }
// main application loop
while(IsRunning)
{
if ( !update() )
break;
Device->sleep( 5 ); // Close down the application
} void CApp::quit()
{
IsRunning = false;
if ( ControlVertexColors )
{
ControlVertexColors->drop();
ControlVertexColors = NULL;
} }
if ( GlobalAmbient )
// Close down the application
void quit()
{ {
IsRunning = false;
GlobalAmbient->drop(); GlobalAmbient->drop();
GlobalAmbient = NULL; GlobalAmbient = NULL;
if ( Device )
{
Device->closeDevice();
Device->drop();
Device = NULL;
}
} }
if ( Device )
{
Device->closeDevice();
Device->drop();
Device = NULL;
}
}
// Create some useful textures. // Create some useful textures.
void CApp::createDefaultTextures(video::IVideoDriver * driver)
{
const u32 width = 256;
const u32 height = 256;
video::IImage * imageA8R8G8B8 = driver->createImage (video::ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
if ( !imageA8R8G8B8 )
return;
const u32 pitch = imageA8R8G8B8->getPitch();
// Some nice square-pattern with 9 typical colors
// Note that the function put readability over speed, you shouldn't use setPixel at runtime but for initialization it's nice. // Note that the function put readability over speed, you shouldn't use setPixel at runtime but for initialization it's nice.
void createDefaultTextures(video::IVideoDriver * driver) for ( u32 y = 0; y < height; ++ y )
{ {
const u32 width = 256; for ( u32 x = 0; x < pitch; ++x )
const u32 height = 256;
video::IImage * imageA8R8G8B8 = driver->createImage (video::ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
if ( !imageA8R8G8B8 )
return;
const u32 pitch = imageA8R8G8B8->getPitch();
// some nice square-pattern with 9 typical colors
for ( u32 y = 0; y < height; ++ y )
{ {
for ( u32 x = 0; x < pitch; ++x ) if ( y < height/3 )
{ {
if ( y < height/3 ) if ( x < width/3 )
{ imageA8R8G8B8->setPixel (x, y, SCOL_BLACK);
if ( x < width/3 ) else if ( x < 2*width/3 )
imageA8R8G8B8->setPixel (x, y, SCOL_BLACK); imageA8R8G8B8->setPixel (x, y, SCOL_BLUE);
else if ( x < 2*width/3 )
imageA8R8G8B8->setPixel (x, y, SCOL_BLUE);
else
imageA8R8G8B8->setPixel (x, y, SCOL_CYAN);
}
else if ( y < 2*height/3 )
{
if ( x < width/3 )
imageA8R8G8B8->setPixel (x, y, SCOL_GRAY);
else if ( x < 2*width/3 )
imageA8R8G8B8->setPixel (x, y, SCOL_GREEN);
else
imageA8R8G8B8->setPixel (x, y, SCOL_MAGENTA);
}
else else
{ imageA8R8G8B8->setPixel (x, y, SCOL_CYAN);
if ( x < width/3 ) }
imageA8R8G8B8->setPixel (x, y, SCOL_RED); else if ( y < 2*height/3 )
else if ( x < 2*width/3 ) {
imageA8R8G8B8->setPixel (x, y, SCOL_YELLOW); if ( x < width/3 )
else imageA8R8G8B8->setPixel (x, y, SCOL_GRAY);
imageA8R8G8B8->setPixel (x, y, SCOL_WHITE); else if ( x < 2*width/3 )
} imageA8R8G8B8->setPixel (x, y, SCOL_GREEN);
else
imageA8R8G8B8->setPixel (x, y, SCOL_MAGENTA);
}
else
{
if ( x < width/3 )
imageA8R8G8B8->setPixel (x, y, SCOL_RED);
else if ( x < 2*width/3 )
imageA8R8G8B8->setPixel (x, y, SCOL_YELLOW);
else
imageA8R8G8B8->setPixel (x, y, SCOL_WHITE);
} }
} }
driver->addTexture (io::path("CARO_A8R8G8B8"), imageA8R8G8B8); }
driver->addTexture (io::path("CARO_A8R8G8B8"), imageA8R8G8B8);
// all white // all white
imageA8R8G8B8->fill(SCOL_WHITE); imageA8R8G8B8->fill(SCOL_WHITE);
driver->addTexture (io::path("WHITE_A8R8G8B8"), imageA8R8G8B8); driver->addTexture (io::path("WHITE_A8R8G8B8"), imageA8R8G8B8);
// all black // all black
imageA8R8G8B8->fill(SCOL_BLACK); imageA8R8G8B8->fill(SCOL_BLACK);
driver->addTexture (io::path("BLACK_A8R8G8B8"), imageA8R8G8B8); driver->addTexture (io::path("BLACK_A8R8G8B8"), imageA8R8G8B8);
// gray-scale // gray-scale
for ( u32 y = 0; y < height; ++ y ) for ( u32 y = 0; y < height; ++ y )
{
for ( u32 x = 0; x < pitch; ++x )
{ {
for ( u32 x = 0; x < pitch; ++x ) imageA8R8G8B8->setPixel (x, y, video::SColor(y, x,x,x) );
{
imageA8R8G8B8->setPixel (x, y, video::SColor(y, x,x,x) );
}
} }
driver->addTexture (io::path("GRAYSCALE_A8R8G8B8"), imageA8R8G8B8);
imageA8R8G8B8->drop();
} }
driver->addTexture (io::path("GRAYSCALE_A8R8G8B8"), imageA8R8G8B8);
// Load a texture and make sure nodes know it when more textures are available. imageA8R8G8B8->drop();
void loadTexture(const io::path &name) }
{
Device->getVideoDriver()->getTexture(name);
NodeLeft.updateTextures();
NodeRight.updateTextures();
}
private: // Load a texture and make sure nodes know it when more textures are available.
SConfig Config; void CApp::loadTexture(const io::path &name)
volatile bool IsRunning; {
IrrlichtDevice * Device; Device->getVideoDriver()->getTexture(name);
scene::ICameraSceneNode * Camera; MeshMaterialControl.updateTextures();
SMeshNodeControl NodeLeft; }
SMeshNodeControl NodeRight;
SLightNodeControl LightControl;
CColorControl * GlobalAmbient;
};
/* /*
A very short main as we do everything else in classes. Short main as most is done in classes.
*/ */
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
...@@ -1033,10 +881,21 @@ int main(int argc, char *argv[]) ...@@ -1033,10 +881,21 @@ int main(int argc, char *argv[])
if ( !APP.init(argc, argv) ) if ( !APP.init(argc, argv) )
{ {
printf("init failed\n"); printf("init failed\n");
APP.quit();
return 1; return 1;
} }
APP.run(); APP.setRunning(true);
/*
main application loop
*/
while(APP.isRunning())
{
if ( !APP.update() )
break;
}
APP.quit(); APP.quit();
return 0; return 0;
......
#ifndef EXAMPLE22_MATERIAL_VIEWER_MAIN_H
#define EXAMPLE22_MATERIAL_VIEWER_MAIN_H
#include <irrlicht.h>
// Helper control to allow setting colors
class CColorControl : public irr::gui::IGUIElement
{
public:
CColorControl(irr::gui::IGUIEnvironment* guiEnv, const irr::core::position2d<irr::s32> & pos, const wchar_t *text, irr::gui::IGUIElement* parent, irr::s32 id=-1);
// Event receiver
virtual bool OnEvent(const irr::SEvent &event);
// Set the color values
void setColor(const irr::video::SColor& col);
// Get the color values
const irr::video::SColor& getColor() const
{
return Color;
}
// To reset the dirty flag
void resetDirty()
{
DirtyFlag = false;
}
// when the color was changed the dirty flag is set
bool isDirty() const
{
return DirtyFlag;
};
protected:
// Add a staticbox for a description + an editbox so users can enter numbers
irr::gui::IGUIEditBox* addEditForNumbers(irr::gui::IGUIEnvironment* guiEnv, const irr::core::position2d<irr::s32> & pos, const wchar_t *text, irr::s32 id, irr::gui::IGUIElement * parent);
// Get the color value from the editfields
irr::video::SColor getColorFromEdits();
// Fill the editfields with the value for the given color
void setEditsFromColor(irr::video::SColor col);
private:
bool DirtyFlag;
irr::video::SColor Color;
irr::s32 ButtonSetId;
irr::gui::IGUIStaticText * ColorStatic;
irr::gui::IGUIEditBox * EditAlpha;
irr::gui::IGUIEditBox * EditRed;
irr::gui::IGUIEditBox * EditGreen;
irr::gui::IGUIEditBox * EditBlue;
};
/*
Custom GUI-control for to edit all colors typically used in materials and lights
*/
class CTypicalColorsControl : public irr::gui::IGUIElement
{
public:
// Constructor
CTypicalColorsControl(irr::gui::IGUIEnvironment* guiEnv, const irr::core::position2d<irr::s32> & pos, bool hasEmissive, irr::gui::IGUIElement* parent, irr::s32 id=-1);
// Destructor
virtual ~CTypicalColorsControl();
// Set the color values to those within the material
void setColorsToMaterialColors(const irr::video::SMaterial & material);
// Update all changed colors in the material
void updateMaterialColors(irr::video::SMaterial & material);
// Set the color values to those from the light data
void setColorsToLightDataColors(const irr::video::SLight & lightData);
// Update all changed colors in the light data
void updateLightColors(irr::video::SLight & lightData) const;
// To reset the dirty flags
void resetDirty();
private:
CColorControl* ControlAmbientColor;
CColorControl* ControlDiffuseColor;
CColorControl* ControlSpecularColor;
CColorControl* ControlEmissiveColor;
};
/*
GUI-Control to offer a selection of available textures.
*/
class CTextureControl : public irr::gui::IGUIElement
{
public:
CTextureControl(irr::gui::IGUIEnvironment* guiEnv, irr::video::IVideoDriver * driver, const irr::core::position2d<irr::s32> & pos, irr::gui::IGUIElement* parent, irr::s32 id=-1);
virtual bool OnEvent(const irr::SEvent &event);
// Workaround for a problem with comboboxes.
// We have to get in front when the combobox wants to get in front or combobox-list might be drawn below other elements.
virtual bool bringToFront(irr::gui::IGUIElement* element);
// Return selected texturename (if any, otherwise 0)
const wchar_t * getSelectedTextureName() const;
// Change active selectionbased on the texture name
void selectTextureByName(const irr::core::stringw& name);
// Reset the dirty flag
void resetDirty()
{
DirtyFlag = false;
}
// When the texture was changed the dirty flag is set
bool isDirty() const
{
return DirtyFlag;
};
// Put the names of all currently loaded textures in a combobox
void updateTextures(irr::video::IVideoDriver * driver);
private:
bool DirtyFlag;
irr::gui::IGUIComboBox * ComboTexture;
};
/*
Control which allows setting some of the material values for a meshscenenode
*/
struct SMaterialControl
{
// constructor
SMaterialControl()
: Initialized(false), Driver(0)
, TypicalColorsControl(0), ButtonLighting(0), InfoLighting(0), ComboMaterial(0)
{
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
TextureControls[i] = 0;
}
// Destructor
~SMaterialControl()
{
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
{
if (TextureControls[i] )
TextureControls[i]->drop();
}
if ( TypicalColorsControl )
TypicalColorsControl->drop();
}
void init(irr::scene::IMeshSceneNode* node, irr::IrrlichtDevice * device, const irr::core::position2d<irr::s32> & pos, const wchar_t * description);
void update(irr::scene::IMeshSceneNode* sceneNode, irr::scene::IMeshSceneNode* sceneNode2T, irr::scene::IMeshSceneNode* sceneNodeTangents);
void updateTextures();
void selectTextures(const irr::core::stringw& name);
protected:
void updateMaterial(irr::video::SMaterial & material);
bool Initialized;
irr::video::IVideoDriver * Driver;
CTypicalColorsControl* TypicalColorsControl;
irr::gui::IGUIButton * ButtonLighting;
irr::gui::IGUIStaticText* InfoLighting;
irr::gui::IGUIComboBox * ComboMaterial;
CTextureControl* TextureControls[irr::video::MATERIAL_MAX_TEXTURES];
};
/*
Control to allow setting the color values of a lightscenenode.
*/
struct SLightNodeControl
{
// constructor
SLightNodeControl() : Initialized(false), TypicalColorsControl(0)
{}
~SLightNodeControl()
{
if ( TypicalColorsControl )
TypicalColorsControl->drop();
}
void init(irr::scene::ILightSceneNode* node, irr::gui::IGUIEnvironment* guiEnv, const irr::core::position2d<irr::s32> & pos, const wchar_t * description);
void update(irr::scene::ILightSceneNode* node);
protected:
bool Initialized;
CTypicalColorsControl* TypicalColorsControl;
};
/*
Application configuration
*/
struct SConfig
{
SConfig()
: RenderInBackground(true)
, DriverType(irr::video::EDT_NULL)
, ScreenSize(640, 480)
{
}
bool RenderInBackground;
irr::video::E_DRIVER_TYPE DriverType;
irr::core::dimension2d<irr::u32> ScreenSize;
};
/*
Main application class
*/
class CApp : public irr::IEventReceiver
{
friend int main(int argc, char *argv[]);
public:
// constructor
CApp()
: IsRunning(false)
, Device(0)
, MeshManipulator(0)
, Camera(0)
, SceneNode(0), SceneNode2T(0), SceneNodeTangents(0), NodeLight(0)
, ControlVertexColors(0)
, GlobalAmbient(0)
{
}
// destructor
~CApp()
{
}
// Tell it to stop running
void setRunning(bool appRuns)
{
IsRunning = appRuns;
}
// Check if it should continue running
bool isRunning() const
{
return IsRunning;
}
// Event handler
virtual bool OnEvent(const irr::SEvent &event);
protected:
// Application initialization
// returns true when it was successful initialized, otherwise false.
bool init(int argc, char *argv[]);
// Update one frame
bool update();
// Run the application. Our main loop.
void run();
// Close down the application
void quit();
// Create some useful textures.
void createDefaultTextures(irr::video::IVideoDriver * driver);
// Load a texture and make sure nodes know it when more textures are available.
void loadTexture(const irr::io::path &name);
private:
SConfig Config;
bool IsRunning;
irr::IrrlichtDevice * Device;
irr::scene::IMeshManipulator* MeshManipulator;
irr::scene::ICameraSceneNode * Camera;
irr::scene::IMeshSceneNode* SceneNode;
irr::scene::IMeshSceneNode* SceneNode2T;
irr::scene::IMeshSceneNode* SceneNodeTangents;
irr::scene::ILightSceneNode* NodeLight;
SMaterialControl MeshMaterialControl;
SLightNodeControl LightControl;
CColorControl* ControlVertexColors;
CColorControl* GlobalAmbient;
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment