Commit 7446ed97 authored by engineer_apple's avatar engineer_apple

Changes in 1.7.1 (05.07.2010) TA

	- BurningVideo 
		- add Normalmap Rendering ( one light only), pushed Burningvideo to 0.46
		- internal vertexformat changed
		- changed fixpoint from 9 to 10 bit fract resolution
		- renamed createBurningVideoDriver to createBurningVideoDriver and uses SIrrlichtCreationParameters like opengl
		- internal interfaces for the trianglerenders unified.
		
	- Example 11.
		changed the light billboards to use the light color. ( green light, green particle, red light red particle )
		allow to disable the bump/parallax on the earth like in the room ( with transparency )


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3333 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 715b14c6
-----------------------------
Changes in 1.7.1 (05.07.2010) TA
- BurningVideo
- add Normalmap Rendering ( one light only), pushed Burningvideo to 0.46
- internal vertexformat changed
- changed fixpoint from 9 to 10 bit fract resolution
- renamed createBurningVideoDriver to createBurningVideoDriver and uses SIrrlichtCreationParameters like opengl
- internal interfaces for the trianglerenders unified.
- Example 11.
changed the light billboards to use the light color. ( green light, green particle, red light red particle )
allow to disable the bump/parallax on the earth like in the room ( with transparency )
--------------------------------------
- In IGUITreeView "clearChilds" and "hasChilds" deprecated for "clearChildren" and "hasChildren" (thx @Greenya for noticing) - In IGUITreeView "clearChilds" and "hasChilds" deprecated for "clearChildren" and "hasChildren" (thx @Greenya for noticing)
- add dimension2d::operator- - add dimension2d::operator-
......
...@@ -28,11 +28,12 @@ class MyEventReceiver : public IEventReceiver ...@@ -28,11 +28,12 @@ class MyEventReceiver : public IEventReceiver
{ {
public: public:
MyEventReceiver(scene::ISceneNode* room, MyEventReceiver(scene::ISceneNode* room,scene::ISceneNode* earth,
gui::IGUIEnvironment* env, video::IVideoDriver* driver) gui::IGUIEnvironment* env, video::IVideoDriver* driver)
{ {
// store pointer to room so we can change its drawing mode // store pointer to room so we can change its drawing mode
Room = room; Room = room;
Earth = earth;
Driver = driver; Driver = driver;
// set a nicer font // set a nicer font
...@@ -120,6 +121,19 @@ private: ...@@ -120,6 +121,19 @@ private:
Room->setMaterialType(type); Room->setMaterialType(type);
// change material setting
switch(ListBox->getSelected())
{
case 0: type = video::EMT_TRANSPARENT_VERTEX_ALPHA;
break;
case 1: type = video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA;
break;
case 2: type = video::EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA;
break;
}
Earth->setMaterialType(type);
/* /*
We need to add a warning if the materials will not be able to We need to add a warning if the materials will not be able to
be displayed 100% correctly. This is no problem, they will be be displayed 100% correctly. This is no problem, they will be
...@@ -137,6 +151,10 @@ private: ...@@ -137,6 +151,10 @@ private:
ProblemText->setVisible(true); ProblemText->setVisible(true);
else else
ProblemText->setVisible(false); ProblemText->setVisible(false);
} }
private: private:
...@@ -145,6 +163,7 @@ private: ...@@ -145,6 +163,7 @@ private:
gui::IGUIListBox* ListBox; gui::IGUIListBox* ListBox;
scene::ISceneNode* Room; scene::ISceneNode* Room;
scene::ISceneNode* Earth;
video::IVideoDriver* Driver; video::IVideoDriver* Driver;
}; };
...@@ -203,7 +222,7 @@ int main() ...@@ -203,7 +222,7 @@ int main()
driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
// add irrlicht logo // add irrlicht logo
env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"), env->addImage(driver->getTexture("../../media/irrlichtlogo3.png"),
core::position2d<s32>(10,10)); core::position2d<s32>(10,10));
// add camera // add camera
...@@ -236,9 +255,14 @@ int main() ...@@ -236,9 +255,14 @@ int main()
scene::IAnimatedMesh* roomMesh = smgr->getMesh( scene::IAnimatedMesh* roomMesh = smgr->getMesh(
"../../media/room.3ds"); "../../media/room.3ds");
scene::ISceneNode* room = 0; scene::ISceneNode* room = 0;
scene::ISceneNode* earth = 0;
if (roomMesh) if (roomMesh)
{ {
/*
The Room Mesh doesn't have proper Texture Mapping on the floor,
so we can recreate them on runtime
*/
smgr->getMeshManipulator()->makePlanarTextureMapping( smgr->getMeshManipulator()->makePlanarTextureMapping(
roomMesh->getMesh(0), 0.003f); roomMesh->getMesh(0), 0.003f);
...@@ -263,7 +287,11 @@ int main() ...@@ -263,7 +287,11 @@ int main()
if (normalMap) if (normalMap)
driver->makeNormalMapTexture(normalMap, 9.0f); driver->makeNormalMapTexture(normalMap, 9.0f);
/*
// The Normal Map and the displacement map/height map in the alpha channel
video::ITexture* normalMap =
driver->getTexture("../../media/rockwall_NRM.tga");
*/
/* /*
But just setting color and normal map is not everything. The But just setting color and normal map is not everything. The
material we want to use needs some additional informations per material we want to use needs some additional informations per
...@@ -285,12 +313,14 @@ int main() ...@@ -285,12 +313,14 @@ int main()
driver->getTexture("../../media/rockwall.jpg")); driver->getTexture("../../media/rockwall.jpg"));
room->setMaterialTexture(1, normalMap); room->setMaterialTexture(1, normalMap);
// Stones don't glitter..
room->getMaterial(0).SpecularColor.set(0,0,0,0); room->getMaterial(0).SpecularColor.set(0,0,0,0);
room->getMaterial(0).Shininess = 0.f;
room->setMaterialFlag(video::EMF_FOG_ENABLE, true); room->setMaterialFlag(video::EMF_FOG_ENABLE, true);
room->setMaterialType(video::EMT_PARALLAX_MAP_SOLID); room->setMaterialType(video::EMT_PARALLAX_MAP_SOLID);
// adjust height for parallax effect // adjust height for parallax effect
room->getMaterial(0).MaterialTypeParam = 0.035f; room->getMaterial(0).MaterialTypeParam = 1.f / 64.f;
// drop mesh because we created it with a create.. call. // drop mesh because we created it with a create.. call.
tangentMesh->drop(); tangentMesh->drop();
...@@ -326,26 +356,26 @@ int main() ...@@ -326,26 +356,26 @@ int main()
m.setScale ( core::vector3df(50,50,50) ); m.setScale ( core::vector3df(50,50,50) );
manipulator->transformMesh( tangentSphereMesh, m ); manipulator->transformMesh( tangentSphereMesh, m );
scene::ISceneNode *sphere = smgr->addMeshSceneNode(tangentSphereMesh); earth = smgr->addMeshSceneNode(tangentSphereMesh);
sphere->setPosition(core::vector3df(-70,130,45)); earth->setPosition(core::vector3df(-70,130,45));
// load heightmap, create normal map from it and set it // load heightmap, create normal map from it and set it
video::ITexture* earthNormalMap = driver->getTexture("../../media/earthbump.jpg"); video::ITexture* earthNormalMap = driver->getTexture("../../media/earthbump.jpg");
if (earthNormalMap) if (earthNormalMap)
{ {
driver->makeNormalMapTexture(earthNormalMap, 20.0f); driver->makeNormalMapTexture(earthNormalMap, 20.0f);
sphere->setMaterialTexture(1, earthNormalMap); earth->setMaterialTexture(1, earthNormalMap);
sphere->setMaterialType(video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA); earth->setMaterialType(video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA);
} }
// adjust material settings // adjust material settings
sphere->setMaterialFlag(video::EMF_FOG_ENABLE, true); earth->setMaterialFlag(video::EMF_FOG_ENABLE, true);
// add rotation animator // add rotation animator
scene::ISceneNodeAnimator* anim = scene::ISceneNodeAnimator* anim =
smgr->createRotationAnimator(core::vector3df(0,0.1f,0)); smgr->createRotationAnimator(core::vector3df(0,0.1f,0));
sphere->addAnimator(anim); earth->addAnimator(anim);
anim->drop(); anim->drop();
// drop mesh because we created it with a create.. call. // drop mesh because we created it with a create.. call.
...@@ -360,7 +390,7 @@ int main() ...@@ -360,7 +390,7 @@ int main()
attached. attached.
*/ */
// add light 1 (nearly red) // add light 1 (more green)
scene::ILightSceneNode* light1 = scene::ILightSceneNode* light1 =
smgr->addLightSceneNode(0, core::vector3df(0,0,0), smgr->addLightSceneNode(0, core::vector3df(0,0,0),
video::SColorf(0.5f, 1.0f, 0.5f, 0.0f), 800.0f); video::SColorf(0.5f, 1.0f, 0.5f, 0.0f), 800.0f);
...@@ -381,7 +411,7 @@ int main() ...@@ -381,7 +411,7 @@ int main()
bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_LIGHTING, false);
bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
bill->setMaterialTexture(0, driver->getTexture("../../media/particlered.bmp")); bill->setMaterialTexture(0, driver->getTexture("../../media/particlegreen.jpg"));
/* /*
Now the same again, with the second light. The difference is that we Now the same again, with the second light. The difference is that we
...@@ -395,8 +425,8 @@ int main() ...@@ -395,8 +425,8 @@ int main()
walls. But of course, this will change in future versions of Irrlicht walls. But of course, this will change in future versions of Irrlicht
where higher versions of pixel/vertex shaders will be implemented too. where higher versions of pixel/vertex shaders will be implemented too.
*/ */
#if 0
// add light 2 (gray) // add light 2 (red)
scene::ISceneNode* light2 = scene::ISceneNode* light2 =
smgr->addLightSceneNode(0, core::vector3df(0,0,0), smgr->addLightSceneNode(0, core::vector3df(0,0,0),
video::SColorf(1.0f, 0.2f, 0.2f, 0.0f), 800.0f); video::SColorf(1.0f, 0.2f, 0.2f, 0.0f), 800.0f);
...@@ -412,7 +442,7 @@ int main() ...@@ -412,7 +442,7 @@ int main()
bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_LIGHTING, false);
bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
bill->setMaterialTexture(0, driver->getTexture("../../media/particlewhite.bmp")); bill->setMaterialTexture(0, driver->getTexture("../../media/particlered.bmp"));
// add particle system // add particle system
scene::IParticleSystemSceneNode* ps = scene::IParticleSystemSceneNode* ps =
...@@ -441,9 +471,9 @@ int main() ...@@ -441,9 +471,9 @@ int main()
ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
ps->setMaterialTexture(0, driver->getTexture("../../media/fireball.bmp")); ps->setMaterialTexture(0, driver->getTexture("../../media/fireball.bmp"));
ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA); ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);
#endif
MyEventReceiver receiver(room, earth, env, driver);
MyEventReceiver receiver(room, env, driver);
device->setEventReceiver(&receiver); device->setEventReceiver(&receiver);
/* /*
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
Version="9,00" Version="9,00"
Name="17.HelloWorld for Windows Mobile on PC" Name="17.HelloWorld_Mobile_v9"
ProjectGUID="{2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}" ProjectGUID="{2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}"
RootNamespace="My17HelloWorldforWindowsMobileonPC" RootNamespace="My17HelloWorldforWindowsMobileonPC"
Keyword="Win32Proj" Keyword="Win32Proj"
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
RuntimeLibrary="3" RuntimeLibrary="3"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4" DebugInformationFormat="4"
/> />
<Tool <Tool
...@@ -122,6 +123,7 @@ ...@@ -122,6 +123,7 @@
RuntimeLibrary="2" RuntimeLibrary="2"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3" DebugInformationFormat="3"
/> />
<Tool <Tool
......
<?xml version="1.0" encoding="Windows-1252"?> <?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
Version="8.00" Version="8,00"
Name="18.SplitScreen_vc8" Name="18.SplitScreen_vc8"
ProjectGUID="{EB3B38EA-5CE7-4983-845B-880661E69D09}" ProjectGUID="{E6F60924-57CD-47F9-A485-853A3BA08FBD}"
Keyword="Win32Proj" Keyword="Win32Proj"
> >
<Platforms> <Platforms>
...@@ -129,7 +129,6 @@ ...@@ -129,7 +129,6 @@
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="true"
DebugInformationFormat="0" DebugInformationFormat="0"
CallingConvention="1"
/> />
<Tool <Tool
Name="VCManagedResourceCompilerTool" Name="VCManagedResourceCompilerTool"
......
...@@ -73,7 +73,7 @@ VideoDriver, load an animated mesh from .md2 and a map from ...@@ -73,7 +73,7 @@ VideoDriver, load an animated mesh from .md2 and a map from
.pk3. Because that's old stuff, I won't explain every step. .pk3. Because that's old stuff, I won't explain every step.
Just take care of the maps position. Just take care of the maps position.
*/ */
int main(int argc, char** argv) int main()
{ {
// ask user for driver // ask user for driver
video::E_DRIVER_TYPE driverType=driverChoiceConsole(); video::E_DRIVER_TYPE driverType=driverChoiceConsole();
......
 
Microsoft Visual Studio Solution File, Format Version 10.00 Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008 # Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "01.HelloWorld_vc9", "01.HelloWorld\HelloWorld_vc9.vcproj", "{5AD4C95C-BA38-4692-BA4B-8C25A86208F9}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "01.HelloWorld_vc9", "01.HelloWorld\HelloWorld_vc9.vcproj", "{5AD4C95C-BA38-4692-BA4B-8C25A86208F9}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F}
...@@ -118,7 +118,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "23.SMeshHandling_vc9", "23. ...@@ -118,7 +118,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "23.SMeshHandling_vc9", "23.
{E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17.HelloWorld for Windows Mobile on PC", "17.HelloWorld_Mobile\17. HelloWorld for Windows Mobile on PC_v9.vcproj", "{2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17.HelloWorld_Mobile_v9", "17.HelloWorld_Mobile\17. HelloWorld for Windows Mobile on PC_v9.vcproj", "{2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F}
EndProjectSection EndProjectSection
......
...@@ -359,7 +359,7 @@ void CDemo::loadSceneData() ...@@ -359,7 +359,7 @@ void CDemo::loadSceneData()
core::matrix4 m; core::matrix4 m;
m.setTranslation(core::vector3df(-1300,-70,-1249)); m.setTranslation(core::vector3df(-1300,-70,-1249));
for ( i = 0; i!= scene::quake3::E_Q3_MESH_SIZE; ++i ) for ( i = 0; i != scene::quake3::E_Q3_MESH_SIZE; ++i )
sm->getMeshManipulator()->transform(quakeLevelMesh->getMesh(i), m); sm->getMeshManipulator()->transform(quakeLevelMesh->getMesh(i), m);
quakeLevelNode = sm->addOctreeSceneNode( quakeLevelNode = sm->addOctreeSceneNode(
......
...@@ -63,7 +63,7 @@ bool CMainMenu::run(bool& outFullscreen, bool& outMusic, bool& outShadows, ...@@ -63,7 +63,7 @@ bool CMainMenu::run(bool& outFullscreen, bool& outMusic, bool& outShadows,
box->addItem(L"OpenGL 1.5"); box->addItem(L"OpenGL 1.5");
box->addItem(L"Direct3D 8.1"); box->addItem(L"Direct3D 8.1");
box->addItem(L"Direct3D 9.0c"); box->addItem(L"Direct3D 9.0c");
box->addItem(L"Burning's Video 0.44"); box->addItem(L"Burning's Video 0.46");
box->addItem(L"Irrlicht Software Renderer 1.0"); box->addItem(L"Irrlicht Software Renderer 1.0");
box->setSelected(selected); box->setSelected(selected);
......
...@@ -117,7 +117,7 @@ headers, e.g. Summer 2004. This is a Microsoft issue, not an Irrlicht one. ...@@ -117,7 +117,7 @@ headers, e.g. Summer 2004. This is a Microsoft issue, not an Irrlicht one.
#if defined(_IRR_WINDOWS_API_) && (!defined(__GNUC__) || defined(IRR_COMPILE_WITH_DX9_DEV_PACK)) #if defined(_IRR_WINDOWS_API_) && (!defined(__GNUC__) || defined(IRR_COMPILE_WITH_DX9_DEV_PACK))
//! Only define _IRR_COMPILE_WITH_DIRECT3D_8_ if you have an appropriate DXSDK, e.g. Summer 2004 //! Only define _IRR_COMPILE_WITH_DIRECT3D_8_ if you have an appropriate DXSDK, e.g. Summer 2004
//#define _IRR_COMPILE_WITH_DIRECT3D_8_ #define _IRR_COMPILE_WITH_DIRECT3D_8_
#define _IRR_COMPILE_WITH_DIRECT3D_9_ #define _IRR_COMPILE_WITH_DIRECT3D_9_
#endif #endif
......
...@@ -217,6 +217,7 @@ namespace core ...@@ -217,6 +217,7 @@ namespace core
//! An alternate transform vector method, writing into an array of 4 floats //! An alternate transform vector method, writing into an array of 4 floats
void transformVect(T *out,const core::vector3df &in) const; void transformVect(T *out,const core::vector3df &in) const;
void transformVec3(T *out, const T * in) const;
//! Translate a vector by the translation part of this matrix. //! Translate a vector by the translation part of this matrix.
void translateVect( vector3df& vect ) const; void translateVect( vector3df& vect ) const;
...@@ -947,6 +948,18 @@ namespace core ...@@ -947,6 +948,18 @@ namespace core
if (definitelyIdentityMatrix) if (definitelyIdentityMatrix)
return true; return true;
#endif #endif
if (!core::equals( M[12], (T)0 ) || !core::equals( M[13], (T)0 ) || !core::equals( M[14], (T)0 ) || !core::equals( M[15], (T)1 ))
return false;
if (!core::equals( M[ 0], (T)1 ) || !core::equals( M[ 1], (T)0 ) || !core::equals( M[ 2], (T)0 ) || !core::equals( M[ 3], (T)0 ))
return false;
if (!core::equals( M[ 4], (T)0 ) || !core::equals( M[ 5], (T)1 ) || !core::equals( M[ 6], (T)0 ) || !core::equals( M[ 7], (T)0 ))
return false;
if (!core::equals( M[ 8], (T)0 ) || !core::equals( M[ 9], (T)0 ) || !core::equals( M[10], (T)1 ) || !core::equals( M[11], (T)0 ))
return false;
/*
if (!core::equals( M[ 0], (T)1 ) || if (!core::equals( M[ 0], (T)1 ) ||
!core::equals( M[ 5], (T)1 ) || !core::equals( M[ 5], (T)1 ) ||
!core::equals( M[10], (T)1 ) || !core::equals( M[10], (T)1 ) ||
...@@ -957,7 +970,7 @@ namespace core ...@@ -957,7 +970,7 @@ namespace core
for (s32 j=0; j<4; ++j) for (s32 j=0; j<4; ++j)
if ((j != i) && (!iszero((*this)(i,j)))) if ((j != i) && (!iszero((*this)(i,j))))
return false; return false;
*/
#if defined ( USE_MATRIX_TEST ) #if defined ( USE_MATRIX_TEST )
definitelyIdentityMatrix=true; definitelyIdentityMatrix=true;
#endif #endif
...@@ -1097,6 +1110,14 @@ namespace core ...@@ -1097,6 +1110,14 @@ namespace core
out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15]; out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15];
} }
template <class T>
inline void CMatrix4<T>::transformVec3(T *out, const T * in) const
{
out[0] = in[0]*M[0] + in[1]*M[4] + in[2]*M[8] + M[12];
out[1] = in[0]*M[1] + in[1]*M[5] + in[2]*M[9] + M[13];
out[2] = in[0]*M[2] + in[1]*M[6] + in[2]*M[10] + M[14];
}
//! Transforms a plane by this matrix //! Transforms a plane by this matrix
template <class T> template <class T>
......
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