Merge revisions r5604 through r5621 from trunk to ogl-es.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@5622 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2018-06-17 20:01:00 +00:00
parent 67d3ffbc1f
commit bdb412cd44
29 changed files with 2040 additions and 292 deletions

View File

@ -9,6 +9,22 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point)
-------------------------- --------------------------
Changes in 1.9 (not yet released) Changes in 1.9 (not yet released)
- CGUIComboBox uses now EGDS_SCROLLBAR_SIZE instead of EGDS_WINDOW_BUTTON_WIDTH for the width of the listbox button to allow changing that without changing window topbar height.
Thanks @LunaRebirth for reporting. (Forum: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=1&t=52297&p=303682#p303682)
- CGUIListbox, CGUITreeView and CGUITable now resize scrollbars when EGDS_SCROLLBAR_SIZE in the skin changes without having to re-create the elements.
This also fixes the problem that drawing looked wrong when this value got changed after the elements were created.
Thanks @LunaRebirth for reporting. (Forum: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=1&t=52297&p=303682#p303682)
- Scrollbar buttons can no longer get larger than half the ScrollBar element to avoid them overlapping.
- Add IVideoDriver::swapMaterialRenderers to allow swapping the renderer used to render a certain material.
- IMeshManipulator functions createMeshWith1TCoords, createMeshWith2TCoords and createMeshWithTangents no longer weld vertices while converting meshes. Use IMeshManipulator::createMeshWelded if you need that welding.
- Add ITerrainSceneNode::setFixedBorderLOD to handle connecting terrain nodes without gaps. Thanks @diho for the bugreport, testcase and a patch proposal (http://irrlicht.sourceforge.net/forum/viewtopic.php?f=9&t=51220).
- PLY loader now works with files which use "st" instead of "uv" for texture coordinates (like generated from Blender or Assimp). Thanks @JLouisB for patch (http://irrlicht.sourceforge.net/forum/viewtopic.php?f=9&t=52261).
- STL writer does now also write binary files when EMWF_WRITE_BINARY flag is used. Based on patch from JLouisB (http://irrlicht.sourceforge.net/forum/viewtopic.php?f=9&t=52261).
(EMWF_WRITE_COMPRESSED also still works for downward compatibility)
- Improved PLY exporter. Thanks for Patch from JLouisB. (Forum: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=9&t=52261):
- Support for UV and vertex colors.
- Support for binary PLY files export with the EMWF_WRITE_BINARY flag
- Fix for the meshes with 32 bits index
- Fix wrong colors on big endian platforms with burnings renders. Thx @kas1e for reporting and @curaga for the patch (#318). Forum bug discussion at http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=52177. - Fix wrong colors on big endian platforms with burnings renders. Thx @kas1e for reporting and @curaga for the patch (#318). Forum bug discussion at http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=52177.
- Fix bug #440 where OpenGL driver enabled second texture for single-texture materials when setMaterial was called twice. Thx@ "number Zero" for bugreport and test-case. - Fix bug #440 where OpenGL driver enabled second texture for single-texture materials when setMaterial was called twice. Thx@ "number Zero" for bugreport and test-case.
- Irrlicht icon now loaded with LR_DEFAULTSIZE to better support larger icon requests. Thx@ luthyr for report and bugfix. - Irrlicht icon now loaded with LR_DEFAULTSIZE to better support larger icon requests. Thx@ luthyr for report and bugfix.

View File

@ -29,7 +29,7 @@ using namespace gui;
Some global variables used later on Some global variables used later on
*/ */
IrrlichtDevice *Device = 0; IrrlichtDevice *Device = 0;
core::stringc StartUpModelFile; io::path StartUpModelFile;
core::stringw MessageText; core::stringw MessageText;
core::stringw Caption; core::stringw Caption;
scene::ISceneNode* Model = 0; scene::ISceneNode* Model = 0;
@ -166,10 +166,8 @@ Function loadModel() loads a model and displays it using an
addAnimatedMeshSceneNode and the scene manager. Nothing difficult. It also addAnimatedMeshSceneNode and the scene manager. Nothing difficult. It also
displays a short message box, if the model could not be loaded. displays a short message box, if the model could not be loaded.
*/ */
void loadModel(const c8* fn) void loadModel(const io::path& filename)
{ {
io::path filename(fn);
io::path extension; io::path extension;
core::getFileNameExtension(extension, filename); core::getFileNameExtension(extension, filename);
extension.make_lower(); extension.make_lower();
@ -440,7 +438,7 @@ public:
// load the model file, selected in the file open dialog // load the model file, selected in the file open dialog
IGUIFileOpenDialog* dialog = IGUIFileOpenDialog* dialog =
(IGUIFileOpenDialog*)event.GUIEvent.Caller; (IGUIFileOpenDialog*)event.GUIEvent.Caller;
loadModel(core::stringc(dialog->getFileName()).c_str()); loadModel(dialog->getFileNameP());
} }
break; break;

View File

@ -45,9 +45,12 @@ namespace scene
EMWF_NONE = 0, EMWF_NONE = 0,
//! write lightmap textures out if possible //! write lightmap textures out if possible
//! Currently not used by any Irrlicht mesh-writer
// (Note: User meshwriters can still use it)
EMWF_WRITE_LIGHTMAPS = 0x1, EMWF_WRITE_LIGHTMAPS = 0x1,
//! write in a way that consumes less disk space //! write in a way that consumes less disk space
// (Note: Mainly there for user meshwriters)
EMWF_WRITE_COMPRESSED = 0x2, EMWF_WRITE_COMPRESSED = 0x2,
//! write in binary format rather than text //! write in binary format rather than text

View File

@ -149,11 +149,11 @@ namespace gui
//! Enumeration for default sizes. //! Enumeration for default sizes.
enum EGUI_DEFAULT_SIZE enum EGUI_DEFAULT_SIZE
{ {
//! default with / height of scrollbar //! default with / height of scrollbar. Also width of drop-down button in comboboxes.
EGDS_SCROLLBAR_SIZE = 0, EGDS_SCROLLBAR_SIZE = 0,
//! height of menu //! height of menu
EGDS_MENU_HEIGHT, EGDS_MENU_HEIGHT,
//! width of a window button //! width and height of a window titlebar button (like minimize/maximize/close buttons). The titlebar height is also calculated from that.
EGDS_WINDOW_BUTTON_WIDTH, EGDS_WINDOW_BUTTON_WIDTH,
//! width of a checkbox check //! width of a checkbox check
EGDS_CHECK_BOX_WIDTH, EGDS_CHECK_BOX_WIDTH,
@ -163,7 +163,7 @@ namespace gui
EGDS_MESSAGE_BOX_HEIGHT, EGDS_MESSAGE_BOX_HEIGHT,
//! width of a default button //! width of a default button
EGDS_BUTTON_WIDTH, EGDS_BUTTON_WIDTH,
//! height of a default button //! height of a default button (OK and cancel buttons)
EGDS_BUTTON_HEIGHT, EGDS_BUTTON_HEIGHT,
//! distance for text from background //! distance for text from background
EGDS_TEXT_DISTANCE_X, EGDS_TEXT_DISTANCE_X,

View File

@ -100,7 +100,9 @@ namespace scene
virtual s32 getCurrentLODOfPatches(core::array<s32>& LODs) const =0; virtual s32 getCurrentLODOfPatches(core::array<s32>& LODs) const =0;
//! Manually sets the LOD of a patch //! Manually sets the LOD of a patch
/** \param patchX Patch x coordinate. /** NOTE: Any values set here are overwritten again in the automatic
recalculations when the camera changes.
\param patchX Patch x coordinate.
\param patchZ Patch z coordinate. \param patchZ Patch z coordinate.
\param LOD The level of detail to set the patch to. */ \param LOD The level of detail to set the patch to. */
virtual void setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD=0) =0; virtual void setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD=0) =0;
@ -172,6 +174,12 @@ namespace scene
video::SColor vertexColor=video::SColor(255,255,255,255), video::SColor vertexColor=video::SColor(255,255,255,255),
s32 smoothFactor=0) =0; s32 smoothFactor=0) =0;
//! Force node to use a fixed LOD level at the borders of the terrain.
/** This can be useful when several TerrainSceneNodes are connected.
\param borderLOD When >= 0 all patches at the 4 borders will use the
given LOD. When < 0 borders are just regular patches (that's default). */
virtual void setFixedBorderLOD(irr::s32 borderLOD=0) = 0;
}; };
} // end namespace scene } // end namespace scene

View File

@ -501,11 +501,15 @@ namespace video
bool zeroTexels = false) const =0; bool zeroTexels = false) const =0;
//! Creates a normal map from a height map texture. //! Creates a normal map from a height map texture.
/** If the target texture has 32 bit, the height value is /** As input is considered to be a height map the texture is read like:
stored in the alpha component of the texture as addition. This - For a 32-bit texture only the red channel is regarded
value is used by the video::EMT_PARALLAX_MAP_SOLID material and - For a 16-bit texture the rgb-values are averaged.
similar materials. Output channels red/green for X/Y and blue for up (Z).
\param texture Texture whose alpha channel is modified. For a 32-bit texture we store additionally the height value in the
alpha channel. This value is used by the video::EMT_PARALLAX_MAP_SOLID
material and similar materials.
On the borders the texture is considered to repeat.
\param texture Height map texture which is converted to a normal map.
\param amplitude Constant value by which the height \param amplitude Constant value by which the height
information is multiplied.*/ information is multiplied.*/
virtual void makeNormalMapTexture(video::ITexture* texture, f32 amplitude=1.0f) const =0; virtual void makeNormalMapTexture(video::ITexture* texture, f32 amplitude=1.0f) const =0;
@ -1327,6 +1331,16 @@ namespace video
\param name: New name of the material renderer. */ \param name: New name of the material renderer. */
virtual void setMaterialRendererName(s32 idx, const c8* name) =0; virtual void setMaterialRendererName(s32 idx, const c8* name) =0;
//! Swap the material renderers used for certain id's
/** Swap the IMaterialRenderers responsible for rendering specific
material-id's. This means every SMaterial using a MaterialType
with one of the indices involved here will now render differently.
\param idx1 First material index to swap. It must already exist or nothing happens.
\param idx2 Second material index to swap. It must already exist or nothing happens.
\param swapNames When true the renderer names also swap
When false the names will stay at the original index */
virtual void swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames=true) = 0;
//! Creates material attributes list from a material //! Creates material attributes list from a material
/** This method is useful for serialization and more. /** This method is useful for serialization and more.
Please note that the video driver will use the material Please note that the video driver will use the material

View File

@ -25,7 +25,9 @@ enum E_VERTEX_TYPE
EVT_2TCOORDS, EVT_2TCOORDS,
//! Vertex with a tangent and binormal vector, video::S3DVertexTangents. //! Vertex with a tangent and binormal vector, video::S3DVertexTangents.
/** Usually used for tangent space normal mapping. */ /** Usually used for tangent space normal mapping.
Usually tangent and binormal get send to shaders as texture coordinate sets 1 and 2.
*/
EVT_TANGENTS EVT_TANGENTS
}; };
@ -181,7 +183,9 @@ struct S3DVertex2TCoords : public S3DVertex
//! Vertex with a tangent and binormal vector. //! Vertex with a tangent and binormal vector.
/** Usually used for tangent space normal mapping. */ /** Usually used for tangent space normal mapping.
Usually tangent and binormal get send to shaders as texture coordinate sets 1 and 2.
*/
struct S3DVertexTangents : public S3DVertex struct S3DVertexTangents : public S3DVertex
{ {
//! default constructor //! default constructor

View File

@ -440,7 +440,7 @@ namespace video
f32 BlendFactor; f32 BlendFactor;
//! Factor specifying how far the polygon offset should be made //! Factor specifying how far the polygon offset should be made
/** Specifying 0 disables the polygon offset. The direction is specified spearately. /** Specifying 0 disables the polygon offset. The direction is specified separately.
The factor can be from 0 to 7.*/ The factor can be from 0 to 7.*/
u8 PolygonOffsetFactor:3; u8 PolygonOffsetFactor:3;

View File

@ -236,22 +236,24 @@ namespace irr
if (!Surface[i] && Texture[i]) if (!Surface[i] && Texture[i])
{ {
IDirect3DTexture9* currentTexture = static_cast<CD3D9Texture*>(Texture[i])->getDX9Texture(); IDirect3DTexture9* currentTexture = static_cast<CD3D9Texture*>(Texture[i])->getDX9Texture();
if ( currentTexture )
IDirect3DSurface9* currentSurface = 0; {
currentTexture->GetSurfaceLevel(0, &currentSurface); IDirect3DSurface9* currentSurface = 0;
currentTexture->GetSurfaceLevel(0, &currentSurface);
Surface[i] = currentSurface; Surface[i] = currentSurface;
}
} }
} }
if (!DepthStencilSurface && DepthStencil) if (!DepthStencilSurface && DepthStencil)
{ {
IDirect3DTexture9* currentTexture = static_cast<CD3D9Texture*>(DepthStencil)->getDX9Texture(); IDirect3DTexture9* currentTexture = static_cast<CD3D9Texture*>(DepthStencil)->getDX9Texture();
if ( currentTexture )
IDirect3DSurface9* currentSurface = 0; {
currentTexture->GetSurfaceLevel(0, &currentSurface); IDirect3DSurface9* currentSurface = 0;
currentTexture->GetSurfaceLevel(0, &currentSurface);
DepthStencilSurface = currentSurface; DepthStencilSurface = currentSurface;
}
} }
} }
} }

View File

@ -353,13 +353,13 @@ void CD3D9Texture::generateRenderTarget()
if (FAILED(hr)) if (FAILED(hr))
{ {
if (D3DERR_INVALIDCALL == hr) if (D3DERR_INVALIDCALL == hr)
os::Printer::log("Could not create render target texture", "Invalid Call"); os::Printer::log("Could not create render target texture", "Invalid Call", irr::ELL_ERROR);
else if (D3DERR_OUTOFVIDEOMEMORY == hr) else if (D3DERR_OUTOFVIDEOMEMORY == hr)
os::Printer::log("Could not create render target texture", "Out of Video Memory"); os::Printer::log("Could not create render target texture", "Out of Video Memory", irr::ELL_ERROR);
else if (E_OUTOFMEMORY == hr) else if (E_OUTOFMEMORY == hr)
os::Printer::log("Could not create render target texture", "Out of Memory"); os::Printer::log("Could not create render target texture", "Out of Memory", irr::ELL_ERROR);
else else
os::Printer::log("Could not create render target texture"); os::Printer::log("Could not create render target texture", irr::ELL_ERROR);
} }
} }
} }

View File

@ -33,18 +33,7 @@ CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
IGUISkin* skin = Environment->getSkin(); IGUISkin* skin = Environment->getSkin();
s32 width = 15; ListButton = Environment->addButton(core::recti(0,0,1,1), this, -1, L"");
if (skin)
width = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
core::rect<s32> r;
r.UpperLeftCorner.X = rectangle.getWidth() - width - 2;
r.LowerRightCorner.X = rectangle.getWidth() - 2;
r.UpperLeftCorner.Y = 2;
r.LowerRightCorner.Y = rectangle.getHeight() - 2;
ListButton = Environment->addButton(r, this, -1, L"");
if (skin && skin->getSpriteBank()) if (skin && skin->getSpriteBank())
{ {
ListButton->setSpriteBank(skin->getSpriteBank()); ListButton->setSpriteBank(skin->getSpriteBank());
@ -55,12 +44,7 @@ CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
ListButton->setSubElement(true); ListButton->setSubElement(true);
ListButton->setTabStop(false); ListButton->setTabStop(false);
r.UpperLeftCorner.X = 2; SelectedText = Environment->addStaticText(L"", core::recti(0,0,1,1), false, false, this, -1, false);
r.UpperLeftCorner.Y = 2;
r.LowerRightCorner.X = RelativeRect.getWidth() - (ListButton->getAbsolutePosition().getWidth() + 2);
r.LowerRightCorner.Y = RelativeRect.getHeight() - 2;
SelectedText = Environment->addStaticText(L"", r, false, false, this, -1, false);
SelectedText->setSubElement(true); SelectedText->setSubElement(true);
SelectedText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); SelectedText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
SelectedText->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_CENTER); SelectedText->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_CENTER);
@ -68,6 +52,8 @@ CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
SelectedText->setOverrideColor(skin->getColor(EGDC_BUTTON_TEXT)); SelectedText->setOverrideColor(skin->getColor(EGDC_BUTTON_TEXT));
SelectedText->enableOverrideColor(true); SelectedText->enableOverrideColor(true);
updateListButtonWidth(skin ? skin->getSize(EGDS_SCROLLBAR_SIZE) : 15);
// this element can be tabbed to // this element can be tabbed to
setTabStop(true); setTabStop(true);
setTabOrder(-1); setTabOrder(-1);
@ -377,6 +363,24 @@ void CGUIComboBox::sendSelectionChangedEvent()
} }
} }
void CGUIComboBox::updateListButtonWidth(s32 width)
{
if (ListButton->getRelativePosition().getWidth() != width)
{
core::rect<s32> r;
r.UpperLeftCorner.X = RelativeRect.getWidth() - width - 2;
r.LowerRightCorner.X = RelativeRect.getWidth() - 2;
r.UpperLeftCorner.Y = 2;
r.LowerRightCorner.Y = RelativeRect.getHeight() - 2;
ListButton->setRelativePosition(r);
r.UpperLeftCorner.X = 2;
r.UpperLeftCorner.Y = 2;
r.LowerRightCorner.X = RelativeRect.getWidth() - (width + 2);
r.LowerRightCorner.Y = RelativeRect.getHeight() - 2;
SelectedText->setRelativePosition(r);
}
}
//! draws the element and its children //! draws the element and its children
void CGUIComboBox::draw() void CGUIComboBox::draw()
@ -386,6 +390,8 @@ void CGUIComboBox::draw()
IGUISkin* skin = Environment->getSkin(); IGUISkin* skin = Environment->getSkin();
updateListButtonWidth(skin->getSize(EGDS_SCROLLBAR_SIZE));
// font changed while the listbox is open? // font changed while the listbox is open?
if ( ActiveFont != skin->getFont() && ListBox ) if ( ActiveFont != skin->getFont() && ListBox )
{ {

View File

@ -84,6 +84,7 @@ namespace gui
void openCloseMenu(); void openCloseMenu();
void sendSelectionChangedEvent(); void sendSelectionChangedEvent();
void updateListButtonWidth(s32 width);
IGUIButton* ListButton; IGUIButton* ListButton;
IGUIStaticText* SelectedText; IGUIStaticText* SelectedText;

View File

@ -34,10 +34,9 @@ CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent,
#endif #endif
IGUISkin* skin = Environment->getSkin(); IGUISkin* skin = Environment->getSkin();
const s32 s = skin->getSize(EGDS_SCROLLBAR_SIZE);
ScrollBar = new CGUIScrollBar(false, Environment, this, -1, ScrollBar = new CGUIScrollBar(false, Environment, this, -1,
core::rect<s32>(RelativeRect.getWidth() - s, 0, RelativeRect.getWidth(), RelativeRect.getHeight()), core::recti(0, 0, 1, 1),
!clip); !clip);
ScrollBar->setSubElement(true); ScrollBar->setSubElement(true);
ScrollBar->setTabStop(false); ScrollBar->setTabStop(false);
@ -45,6 +44,8 @@ CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent,
ScrollBar->setVisible(false); ScrollBar->setVisible(false);
ScrollBar->setPos(0); ScrollBar->setPos(0);
updateScrollBarSize(skin->getSize(EGDS_SCROLLBAR_SIZE));
setNotClipped(!clip); setNotClipped(!clip);
// this element can be tabbed to // this element can be tabbed to
@ -149,8 +150,7 @@ void CGUIListBox::clear()
ItemsIconWidth = 0; ItemsIconWidth = 0;
Selected = -1; Selected = -1;
if (ScrollBar) ScrollBar->setPos(0);
ScrollBar->setPos(0);
recalculateItemHeight(); recalculateItemHeight();
} }
@ -190,7 +190,6 @@ void CGUIListBox::recalculateItemHeight()
ScrollBar->setVisible(true); ScrollBar->setVisible(true);
} }
//! returns id of selected item. returns -1 if no item is selected. //! returns id of selected item. returns -1 if no item is selected.
s32 CGUIListBox::getSelected() const s32 CGUIListBox::getSelected() const
{ {
@ -495,6 +494,7 @@ void CGUIListBox::draw()
recalculateItemHeight(); // if the font changed recalculateItemHeight(); // if the font changed
IGUISkin* skin = Environment->getSkin(); IGUISkin* skin = Environment->getSkin();
updateScrollBarSize(skin->getSize(EGDS_SCROLLBAR_SIZE));
core::rect<s32>* clipRect = 0; core::rect<s32>* clipRect = 0;
@ -507,7 +507,7 @@ void CGUIListBox::draw()
clientClip.UpperLeftCorner.Y += 1; clientClip.UpperLeftCorner.Y += 1;
clientClip.UpperLeftCorner.X += 1; clientClip.UpperLeftCorner.X += 1;
if (ScrollBar->isVisible()) if (ScrollBar->isVisible())
clientClip.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE); clientClip.LowerRightCorner.X -= ScrollBar->getRelativePosition().getWidth();
clientClip.LowerRightCorner.Y -= 1; clientClip.LowerRightCorner.Y -= 1;
clientClip.clipAgainst(AbsoluteClippingRect); clientClip.clipAgainst(AbsoluteClippingRect);
@ -520,7 +520,7 @@ void CGUIListBox::draw()
frameRect = AbsoluteRect; frameRect = AbsoluteRect;
frameRect.UpperLeftCorner.X += 1; frameRect.UpperLeftCorner.X += 1;
if (ScrollBar->isVisible()) if (ScrollBar->isVisible())
frameRect.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE); frameRect.LowerRightCorner.X -= ScrollBar->getRelativePosition().getWidth();
frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight; frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight;
@ -637,6 +637,14 @@ void CGUIListBox::recalculateScrollPos()
} }
} }
void CGUIListBox::updateScrollBarSize(s32 size)
{
if ( size != ScrollBar->getRelativePosition().getWidth() )
{
core::recti r(RelativeRect.getWidth() - size, 0, RelativeRect.getWidth(), RelativeRect.getHeight());
ScrollBar->setRelativePosition(r);
}
}
void CGUIListBox::setAutoScrollEnabled(bool scroll) void CGUIListBox::setAutoScrollEnabled(bool scroll)
{ {

View File

@ -157,6 +157,7 @@ namespace gui
void recalculateItemHeight(); void recalculateItemHeight();
void selectNew(s32 ypos, bool onlyHover=false); void selectNew(s32 ypos, bool onlyHover=false);
void recalculateScrollPos(); void recalculateScrollPos();
void updateScrollBarSize(s32 size);
// extracted that function to avoid copy&paste code // extracted that function to avoid copy&paste code
void recalculateItemWidth(s32 icon); void recalculateItemWidth(s32 icon);

View File

@ -466,10 +466,11 @@ void CGUIScrollBar::refreshControls()
if (Horizontal) if (Horizontal)
{ {
s32 h = RelativeRect.getHeight(); const s32 h = RelativeRect.getHeight();
const s32 w = (h < RelativeRect.getWidth() / 2) ? h : RelativeRect.getWidth() / 2;
if (!UpButton) if (!UpButton)
{ {
UpButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,0, h, h), NoClip); UpButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,0, w, h), NoClip);
UpButton->setSubElement(true); UpButton->setSubElement(true);
UpButton->setTabStop(false); UpButton->setTabStop(false);
} }
@ -479,11 +480,11 @@ void CGUIScrollBar::refreshControls()
UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor); UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor);
UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor); UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor);
} }
UpButton->setRelativePosition(core::rect<s32>(0,0, h, h)); UpButton->setRelativePosition(core::rect<s32>(0,0, w, h));
UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
if (!DownButton) if (!DownButton)
{ {
DownButton = new CGUIButton(Environment, this, -1, core::rect<s32>(RelativeRect.getWidth()-h, 0, RelativeRect.getWidth(), h), NoClip); DownButton = new CGUIButton(Environment, this, -1, core::rect<s32>(RelativeRect.getWidth()-w, 0, RelativeRect.getWidth(), h), NoClip);
DownButton->setSubElement(true); DownButton->setSubElement(true);
DownButton->setTabStop(false); DownButton->setTabStop(false);
} }
@ -493,15 +494,16 @@ void CGUIScrollBar::refreshControls()
DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor); DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor);
DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor); DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor);
} }
DownButton->setRelativePosition(core::rect<s32>(RelativeRect.getWidth()-h, 0, RelativeRect.getWidth(), h)); DownButton->setRelativePosition(core::rect<s32>(RelativeRect.getWidth()-w, 0, RelativeRect.getWidth(), h));
DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
} }
else else
{ {
s32 w = RelativeRect.getWidth(); const s32 w = RelativeRect.getWidth();
const s32 h = (w < RelativeRect.getHeight() / 2) ? w : RelativeRect.getHeight() / 2;
if (!UpButton) if (!UpButton)
{ {
UpButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,0, w, w), NoClip); UpButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,0, w, h), NoClip);
UpButton->setSubElement(true); UpButton->setSubElement(true);
UpButton->setTabStop(false); UpButton->setTabStop(false);
} }
@ -511,11 +513,11 @@ void CGUIScrollBar::refreshControls()
UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor); UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor);
UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor); UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor);
} }
UpButton->setRelativePosition(core::rect<s32>(0,0, w, w)); UpButton->setRelativePosition(core::rect<s32>(0,0, w, h));
UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
if (!DownButton) if (!DownButton)
{ {
DownButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,RelativeRect.getHeight()-w, w, RelativeRect.getHeight()), NoClip); DownButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,RelativeRect.getHeight()-h, w, RelativeRect.getHeight()), NoClip);
DownButton->setSubElement(true); DownButton->setSubElement(true);
DownButton->setTabStop(false); DownButton->setTabStop(false);
} }
@ -525,7 +527,7 @@ void CGUIScrollBar::refreshControls()
DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor); DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor);
DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor); DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor);
} }
DownButton->setRelativePosition(core::rect<s32>(0,RelativeRect.getHeight()-w, w, RelativeRect.getHeight())); DownButton->setRelativePosition(core::rect<s32>(0,RelativeRect.getHeight()-h, w, RelativeRect.getHeight()));
DownButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); DownButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
} }
} }

View File

@ -33,6 +33,7 @@ CGUITable::CGUITable(IGUIEnvironment* environment, IGUIElement* parent,
ItemHeight(0), TotalItemHeight(0), TotalItemWidth(0), Selected(-1), ItemHeight(0), TotalItemHeight(0), TotalItemWidth(0), Selected(-1),
CellHeightPadding(2), CellWidthPadding(5), ActiveTab(-1), CellHeightPadding(2), CellWidthPadding(5), ActiveTab(-1),
CurrentOrdering(EGOM_NONE), DrawFlags(EGTDF_ROWS | EGTDF_COLUMNS | EGTDF_ACTIVE_ROW ), CurrentOrdering(EGOM_NONE), DrawFlags(EGTDF_ROWS | EGTDF_COLUMNS | EGTDF_ACTIVE_ROW ),
ScrollBarSize(0),
OverrideFont(0) OverrideFont(0)
{ {
#ifdef _DEBUG #ifdef _DEBUG
@ -436,7 +437,8 @@ void CGUITable::checkScrollbars()
if ( !HorizontalScrollBar || !VerticalScrollBar || !skin) if ( !HorizontalScrollBar || !VerticalScrollBar || !skin)
return; return;
s32 scrollBarSize = skin->getSize(EGDS_SCROLLBAR_SIZE); ScrollBarSize = skin->getSize(EGDS_SCROLLBAR_SIZE);
bool wasHorizontalScrollBarVisible = HorizontalScrollBar->isVisible(); bool wasHorizontalScrollBarVisible = HorizontalScrollBar->isVisible();
bool wasVerticalScrollBarVisible = VerticalScrollBar->isVisible(); bool wasVerticalScrollBarVisible = VerticalScrollBar->isVisible();
HorizontalScrollBar->setVisible(false); HorizontalScrollBar->setVisible(false);
@ -456,7 +458,7 @@ void CGUITable::checkScrollbars()
// needs horizontal scroll be visible? // needs horizontal scroll be visible?
if( TotalItemWidth > clientClip.getWidth() ) if( TotalItemWidth > clientClip.getWidth() )
{ {
clientClip.LowerRightCorner.Y -= scrollBarSize; clientClip.LowerRightCorner.Y -= ScrollBarSize;
HorizontalScrollBar->setVisible(true); HorizontalScrollBar->setVisible(true);
HorizontalScrollBar->setMax(core::max_(0,TotalItemWidth - clientClip.getWidth())); HorizontalScrollBar->setMax(core::max_(0,TotalItemWidth - clientClip.getWidth()));
} }
@ -464,7 +466,7 @@ void CGUITable::checkScrollbars()
// needs vertical scroll be visible? // needs vertical scroll be visible?
if( TotalItemHeight > clientClip.getHeight() ) if( TotalItemHeight > clientClip.getHeight() )
{ {
clientClip.LowerRightCorner.X -= scrollBarSize; clientClip.LowerRightCorner.X -= ScrollBarSize;
VerticalScrollBar->setVisible(true); VerticalScrollBar->setVisible(true);
VerticalScrollBar->setMax(core::max_(0,TotalItemHeight - clientClip.getHeight())); VerticalScrollBar->setMax(core::max_(0,TotalItemHeight - clientClip.getHeight()));
@ -473,7 +475,7 @@ void CGUITable::checkScrollbars()
{ {
if( TotalItemWidth > clientClip.getWidth() ) if( TotalItemWidth > clientClip.getWidth() )
{ {
clientClip.LowerRightCorner.Y -= scrollBarSize; clientClip.LowerRightCorner.Y -= ScrollBarSize;
HorizontalScrollBar->setVisible(true); HorizontalScrollBar->setVisible(true);
HorizontalScrollBar->setMax(core::max_(0,TotalItemWidth - clientClip.getWidth())); HorizontalScrollBar->setMax(core::max_(0,TotalItemWidth - clientClip.getWidth()));
} }
@ -489,13 +491,13 @@ void CGUITable::checkScrollbars()
if ( HorizontalScrollBar->isVisible() ) if ( HorizontalScrollBar->isVisible() )
{ {
VerticalScrollBar->setRelativePosition( VerticalScrollBar->setRelativePosition(
core::rect<s32>(RelativeRect.getWidth() - scrollBarSize, 1, core::rect<s32>(RelativeRect.getWidth() - ScrollBarSize, 1,
RelativeRect.getWidth()-1, RelativeRect.getHeight()-(1+scrollBarSize) ) ); RelativeRect.getWidth()-1, RelativeRect.getHeight()-(1+ScrollBarSize) ) );
} }
else else
{ {
VerticalScrollBar->setRelativePosition( VerticalScrollBar->setRelativePosition(
core::rect<s32>(RelativeRect.getWidth() - scrollBarSize, 1, core::rect<s32>(RelativeRect.getWidth() - ScrollBarSize, 1,
RelativeRect.getWidth()-1, RelativeRect.getHeight()-1) ); RelativeRect.getWidth()-1, RelativeRect.getHeight()-1) );
} }
} }
@ -508,11 +510,11 @@ void CGUITable::checkScrollbars()
if ( VerticalScrollBar->isVisible() ) if ( VerticalScrollBar->isVisible() )
{ {
HorizontalScrollBar->setRelativePosition( core::rect<s32>(1, RelativeRect.getHeight() - scrollBarSize, RelativeRect.getWidth()-(1+scrollBarSize), RelativeRect.getHeight()-1) ); HorizontalScrollBar->setRelativePosition( core::rect<s32>(1, RelativeRect.getHeight() - ScrollBarSize, RelativeRect.getWidth()-(1+ScrollBarSize), RelativeRect.getHeight()-1) );
} }
else else
{ {
HorizontalScrollBar->setRelativePosition( core::rect<s32>(1, RelativeRect.getHeight() - scrollBarSize, RelativeRect.getWidth()-1, RelativeRect.getHeight()-1) ); HorizontalScrollBar->setRelativePosition( core::rect<s32>(1, RelativeRect.getHeight() - ScrollBarSize, RelativeRect.getWidth()-1, RelativeRect.getHeight()-1) );
} }
} }
} }
@ -864,15 +866,18 @@ void CGUITable::draw()
if (!font) if (!font)
return; return;
if ( ScrollBarSize != skin->getSize(EGDS_SCROLLBAR_SIZE) )
checkScrollbars();
// CAREFUL: near identical calculations for tableRect and clientClip are also done in checkScrollbars and selectColumnHeader // CAREFUL: near identical calculations for tableRect and clientClip are also done in checkScrollbars and selectColumnHeader
// Area of table used for drawing without scrollbars // Area of table used for drawing without scrollbars
core::rect<s32> tableRect(AbsoluteRect); core::rect<s32> tableRect(AbsoluteRect);
tableRect.UpperLeftCorner.X += 1; tableRect.UpperLeftCorner.X += 1;
tableRect.UpperLeftCorner.Y += 1; tableRect.UpperLeftCorner.Y += 1;
if ( VerticalScrollBar && VerticalScrollBar->isVisible() ) if ( VerticalScrollBar && VerticalScrollBar->isVisible() )
tableRect.LowerRightCorner.X -= skin->getSize(EGDS_SCROLLBAR_SIZE); tableRect.LowerRightCorner.X -= ScrollBarSize;
if ( HorizontalScrollBar && HorizontalScrollBar->isVisible() ) if ( HorizontalScrollBar && HorizontalScrollBar->isVisible() )
tableRect.LowerRightCorner.Y -= skin->getSize(EGDS_SCROLLBAR_SIZE); tableRect.LowerRightCorner.Y -= ScrollBarSize;
s32 headerBottom = tableRect.UpperLeftCorner.Y + ItemHeight; s32 headerBottom = tableRect.UpperLeftCorner.Y + ItemHeight;
@ -910,7 +915,7 @@ void CGUITable::draw()
if (rowRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y && if (rowRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y &&
rowRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y) rowRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y)
{ {
// draw row seperator // draw row separator
if ( DrawFlags & EGTDF_ROWS ) if ( DrawFlags & EGTDF_ROWS )
{ {
core::rect<s32> lineRect(rowRect); core::rect<s32> lineRect(rowRect);
@ -966,7 +971,7 @@ void CGUITable::draw()
// draw column background // draw column background
skin->draw3DButtonPaneStandard(this, columnrect, &tableClip); skin->draw3DButtonPaneStandard(this, columnrect, &tableClip);
// draw column seperator // draw column separator
if ( DrawFlags & EGTDF_COLUMNS ) if ( DrawFlags & EGTDF_COLUMNS )
{ {
columnSeparator.UpperLeftCorner.X = pos; columnSeparator.UpperLeftCorner.X = pos;

View File

@ -179,8 +179,8 @@ namespace gui
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) _IRR_OVERRIDE_; virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) _IRR_OVERRIDE_;
protected: protected:
virtual void refreshControls(); void refreshControls();
virtual void checkScrollbars(); void checkScrollbars();
private: private:
@ -240,6 +240,7 @@ namespace gui
s32 ActiveTab; s32 ActiveTab;
EGUI_ORDERING_MODE CurrentOrdering; EGUI_ORDERING_MODE CurrentOrdering;
s32 DrawFlags; s32 DrawFlags;
s32 ScrollBarSize;
gui::IGUIFont* OverrideFont; gui::IGUIFont* OverrideFont;
}; };

View File

@ -432,6 +432,7 @@ CGUITreeView::CGUITreeView(IGUIEnvironment* environment, IGUIElement* parent,
IndentWidth( 0 ), IndentWidth( 0 ),
TotalItemHeight( 0 ), TotalItemHeight( 0 ),
TotalItemWidth ( 0 ), TotalItemWidth ( 0 ),
ScrollBarSize( 0 ),
Font( 0 ), Font( 0 ),
OverrideFont( 0 ), OverrideFont( 0 ),
IconFont( 0 ), IconFont( 0 ),
@ -450,15 +451,15 @@ CGUITreeView::CGUITreeView(IGUIEnvironment* environment, IGUIElement* parent,
#endif #endif
IGUISkin* skin = Environment->getSkin(); IGUISkin* skin = Environment->getSkin();
s32 s = skin->getSize( EGDS_SCROLLBAR_SIZE ); ScrollBarSize = skin->getSize( EGDS_SCROLLBAR_SIZE );
if ( scrollBarVertical ) if ( scrollBarVertical )
{ {
ScrollBarV = new CGUIScrollBar( false, Environment, this, -1, ScrollBarV = new CGUIScrollBar( false, Environment, this, -1,
core::rect<s32>( RelativeRect.getWidth() - s, core::rect<s32>( RelativeRect.getWidth() - ScrollBarSize,
0, 0,
RelativeRect.getWidth(), RelativeRect.getWidth(),
RelativeRect.getHeight() - s RelativeRect.getHeight() - ScrollBarSize
), !clip ); ), !clip );
ScrollBarV->drop(); ScrollBarV->drop();
@ -471,8 +472,8 @@ CGUITreeView::CGUITreeView(IGUIEnvironment* environment, IGUIElement* parent,
{ {
ScrollBarH = new CGUIScrollBar( true, Environment, this, -1, ScrollBarH = new CGUIScrollBar( true, Environment, this, -1,
core::rect<s32>( 0, core::rect<s32>( 0,
RelativeRect.getHeight() - s, RelativeRect.getHeight() - ScrollBarSize,
RelativeRect.getWidth() - s, RelativeRect.getWidth() - ScrollBarSize,
RelativeRect.getHeight() RelativeRect.getHeight()
), !clip ); ), !clip );
ScrollBarH->drop(); ScrollBarH->drop();
@ -640,6 +641,28 @@ void CGUITreeView::recalculateItemHeight()
} }
void CGUITreeView::updateScrollBarSize(s32 size)
{
if ( size != ScrollBarSize )
{
ScrollBarSize = size;
if ( ScrollBarV )
{
core::recti r(RelativeRect.getWidth() - ScrollBarSize, 0,
RelativeRect.getWidth(), RelativeRect.getHeight() - ScrollBarSize);
ScrollBarV->setRelativePosition(r);
}
if ( ScrollBarH )
{
core::recti r(0, RelativeRect.getHeight() - ScrollBarSize,
RelativeRect.getWidth() - ScrollBarSize, RelativeRect.getHeight());
ScrollBarH->setRelativePosition(r);
}
}
}
//! called if an event happened. //! called if an event happened.
bool CGUITreeView::OnEvent( const SEvent &event ) bool CGUITreeView::OnEvent( const SEvent &event )
{ {
@ -829,9 +852,11 @@ void CGUITreeView::draw()
return; return;
} }
IGUISkin* skin = Environment->getSkin();
updateScrollBarSize(skin->getSize(EGDS_SCROLLBAR_SIZE));
recalculateItemHeight(); // if the font changed recalculateItemHeight(); // if the font changed
IGUISkin* skin = Environment->getSkin();
irr::video::IVideoDriver* driver = Environment->getVideoDriver(); irr::video::IVideoDriver* driver = Environment->getVideoDriver();
core::rect<s32>* clipRect = 0; core::rect<s32>* clipRect = 0;
@ -876,9 +901,9 @@ void CGUITreeView::draw()
clientClip.LowerRightCorner.Y -= 1; clientClip.LowerRightCorner.Y -= 1;
if ( ScrollBarV ) if ( ScrollBarV )
clientClip.LowerRightCorner.X -= skin->getSize( EGDS_SCROLLBAR_SIZE ); clientClip.LowerRightCorner.X -= ScrollBarSize;
if ( ScrollBarH ) if ( ScrollBarH )
clientClip.LowerRightCorner.Y -= skin->getSize( EGDS_SCROLLBAR_SIZE ); clientClip.LowerRightCorner.Y -= ScrollBarSize;
if( clipRect ) if( clipRect )
{ {
@ -886,7 +911,7 @@ void CGUITreeView::draw()
} }
frameRect = AbsoluteRect; frameRect = AbsoluteRect;
frameRect.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize( EGDS_SCROLLBAR_SIZE ); frameRect.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - ScrollBarSize;
frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight; frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight;
if ( ScrollBarV ) if ( ScrollBarV )

View File

@ -320,6 +320,9 @@ namespace gui
//! calculates the heigth of an node and of all visible nodes. //! calculates the heigth of an node and of all visible nodes.
void recalculateItemHeight(); void recalculateItemHeight();
//! Resize scrollbars when their size in the skin has changed
void updateScrollBarSize(s32 size);
//! executes an mouse action (like selectNew of CGUIListBox) //! executes an mouse action (like selectNew of CGUIListBox)
void mouseAction( s32 xpos, s32 ypos, bool onlyHover = false ); void mouseAction( s32 xpos, s32 ypos, bool onlyHover = false );
@ -329,6 +332,7 @@ namespace gui
s32 IndentWidth; s32 IndentWidth;
s32 TotalItemHeight; s32 TotalItemHeight;
s32 TotalItemWidth; s32 TotalItemWidth;
s32 ScrollBarSize;
IGUIFont* Font; IGUIFont* Font;
gui::IGUIFont* OverrideFont; gui::IGUIFont* OverrideFont;
IGUIFont* IconFont; IGUIFont* IconFont;

View File

@ -951,75 +951,63 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const
// not yet 32bit // not yet 32bit
IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted, bool calculateTangents) const IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted, bool calculateTangents) const
{ {
using namespace video;
if (!mesh) if (!mesh)
return 0; return 0;
// copy mesh and fill data into SMeshBufferTangents // copy mesh and fill data into SMeshBufferTangents
SMesh* clone = new SMesh(); SMesh* clone = new SMesh();
const u32 meshBufferCount = mesh->getMeshBufferCount(); const u32 meshBufferCount = mesh->getMeshBufferCount();
for (u32 b=0; b<meshBufferCount; ++b) for (u32 b=0; b<meshBufferCount; ++b)
{ {
const IMeshBuffer* const original = mesh->getMeshBuffer(b); const IMeshBuffer* const original = mesh->getMeshBuffer(b);
const u32 idxCnt = original->getIndexCount();
const u16* idx = original->getIndices();
SMeshBufferTangents* buffer = new SMeshBufferTangents(); SMeshBufferTangents* buffer = new SMeshBufferTangents();
// copy material
buffer->Material = original->getMaterial(); buffer->Material = original->getMaterial();
buffer->Vertices.reallocate(idxCnt);
buffer->Indices.reallocate(idxCnt);
core::map<video::S3DVertexTangents, int> vertMap; // copy indices
int vertLocation; const u32 idxCnt = original->getIndexCount();
const u16* indices = original->getIndices();
buffer->Indices.reallocate(idxCnt);
for (u32 i=0; i < idxCnt; ++i)
buffer->Indices.push_back(indices[i]);
// copy vertices // copy vertices
const u32 vtxCnt = original->getVertexCount();
buffer->Vertices.reallocate(vtxCnt);
const video::E_VERTEX_TYPE vType = original->getVertexType(); const E_VERTEX_TYPE vType = original->getVertexType();
video::S3DVertexTangents vNew; switch(vType)
for (u32 i=0; i<idxCnt; ++i)
{ {
switch(vType) case video::EVT_STANDARD:
{ {
case video::EVT_STANDARD: const S3DVertex* v = (const S3DVertex*)original->getVertices();
{
const video::S3DVertex* v =
(const video::S3DVertex*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
break;
case video::EVT_2TCOORDS:
{
const video::S3DVertex2TCoords* v =
(const video::S3DVertex2TCoords*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
break;
case video::EVT_TANGENTS:
{
const video::S3DVertexTangents* v =
(const video::S3DVertexTangents*)original->getVertices();
vNew = v[idx[i]];
}
break;
}
core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
if (n)
{
vertLocation = n->getValue();
}
else
{
vertLocation = buffer->Vertices.size();
buffer->Vertices.push_back(vNew);
vertMap.insert(vNew, vertLocation);
}
// create new indices for (u32 i=0; i < vtxCnt; ++i)
buffer->Indices.push_back(vertLocation); buffer->Vertices.push_back( S3DVertexTangents(
v[i].Pos, v[i].Normal, v[i].Color, v[i].TCoords) );
}
break;
case video::EVT_2TCOORDS:
{
const S3DVertex2TCoords* v =(const S3DVertex2TCoords*)original->getVertices();
for (u32 i=0; i < vtxCnt; ++i)
buffer->Vertices.push_back( S3DVertexTangents(
v[i].Pos, v[i].Normal, v[i].Color, v[i].TCoords) );
}
break;
case video::EVT_TANGENTS:
{
const S3DVertexTangents* v =(const S3DVertexTangents*)original->getVertices();
for (u32 i=0; i < vtxCnt; ++i)
buffer->Vertices.push_back(v[i]);
}
break;
} }
buffer->recalculateBoundingBox(); buffer->recalculateBoundingBox();
@ -1347,11 +1335,12 @@ donehere:
free(accel); free(accel);
} }
//! Creates a copy of the mesh, which will only consist of S3DVertex2TCoords vertices. //! Creates a copy of the mesh, which will only consist of S3DVertex2TCoords vertices.
// not yet 32bit // not yet 32bit
IMesh* CMeshManipulator::createMeshWith2TCoords(IMesh* mesh) const IMesh* CMeshManipulator::createMeshWith2TCoords(IMesh* mesh) const
{ {
using namespace video;
if (!mesh) if (!mesh)
return 0; return 0;
@ -1363,63 +1352,50 @@ IMesh* CMeshManipulator::createMeshWith2TCoords(IMesh* mesh) const
for (u32 b=0; b<meshBufferCount; ++b) for (u32 b=0; b<meshBufferCount; ++b)
{ {
const IMeshBuffer* const original = mesh->getMeshBuffer(b); const IMeshBuffer* const original = mesh->getMeshBuffer(b);
const u32 idxCnt = original->getIndexCount();
const u16* idx = original->getIndices();
SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); SMeshBufferLightMap* buffer = new SMeshBufferLightMap();
buffer->Material = original->getMaterial();
buffer->Vertices.reallocate(idxCnt);
buffer->Indices.reallocate(idxCnt);
core::map<video::S3DVertex2TCoords, int> vertMap; // copy material
int vertLocation; buffer->Material = original->getMaterial();
// copy indices
const u32 idxCnt = original->getIndexCount();
const u16* indices = original->getIndices();
buffer->Indices.reallocate(idxCnt);
for (u32 i=0; i < idxCnt; ++i)
buffer->Indices.push_back(indices[i]);
// copy vertices // copy vertices
const u32 vtxCnt = original->getVertexCount();
buffer->Vertices.reallocate(vtxCnt);
const video::E_VERTEX_TYPE vType = original->getVertexType(); const video::E_VERTEX_TYPE vType = original->getVertexType();
video::S3DVertex2TCoords vNew; switch(vType)
for (u32 i=0; i<idxCnt; ++i)
{ {
switch(vType) case video::EVT_STANDARD:
{ {
case video::EVT_STANDARD: const S3DVertex* v = (const S3DVertex*)original->getVertices();
{
const video::S3DVertex* v =
(const video::S3DVertex*)original->getVertices();
vNew = video::S3DVertex2TCoords(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords);
}
break;
case video::EVT_2TCOORDS:
{
const video::S3DVertex2TCoords* v =
(const video::S3DVertex2TCoords*)original->getVertices();
vNew = v[idx[i]];
}
break;
case video::EVT_TANGENTS:
{
const video::S3DVertexTangents* v =
(const video::S3DVertexTangents*)original->getVertices();
vNew = video::S3DVertex2TCoords(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords);
}
break;
}
core::map<video::S3DVertex2TCoords, int>::Node* n = vertMap.find(vNew);
if (n)
{
vertLocation = n->getValue();
}
else
{
vertLocation = buffer->Vertices.size();
buffer->Vertices.push_back(vNew);
vertMap.insert(vNew, vertLocation);
}
// create new indices for (u32 i=0; i < vtxCnt; ++i)
buffer->Indices.push_back(vertLocation); buffer->Vertices.push_back( video::S3DVertex2TCoords(
v[i].Pos, v[i].Normal, v[i].Color, v[i].TCoords, v[i].TCoords));
}
break;
case video::EVT_2TCOORDS:
{
const S3DVertex2TCoords* v =(const S3DVertex2TCoords*)original->getVertices();
for (u32 i=0; i < vtxCnt; ++i)
buffer->Vertices.push_back(v[i]);
}
break;
case video::EVT_TANGENTS:
{
const S3DVertexTangents* v =(const S3DVertexTangents*)original->getVertices();
for (u32 i=0; i < vtxCnt; ++i)
buffer->Vertices.push_back( S3DVertex2TCoords(
v[i].Pos, v[i].Normal, v[i].Color, v[i].TCoords, v[i].TCoords) );
}
break;
} }
buffer->recalculateBoundingBox(); buffer->recalculateBoundingBox();
@ -1437,6 +1413,8 @@ IMesh* CMeshManipulator::createMeshWith2TCoords(IMesh* mesh) const
// not yet 32bit // not yet 32bit
IMesh* CMeshManipulator::createMeshWith1TCoords(IMesh* mesh) const IMesh* CMeshManipulator::createMeshWith1TCoords(IMesh* mesh) const
{ {
using namespace video;
if (!mesh) if (!mesh)
return 0; return 0;
@ -1446,64 +1424,54 @@ IMesh* CMeshManipulator::createMeshWith1TCoords(IMesh* mesh) const
for (u32 b=0; b<meshBufferCount; ++b) for (u32 b=0; b<meshBufferCount; ++b)
{ {
IMeshBuffer* original = mesh->getMeshBuffer(b); const IMeshBuffer* const original = mesh->getMeshBuffer(b);
const u32 idxCnt = original->getIndexCount();
const u16* idx = original->getIndices();
SMeshBuffer* buffer = new SMeshBuffer(); SMeshBuffer* buffer = new SMeshBuffer();
buffer->Material = original->getMaterial();
buffer->Vertices.reallocate(idxCnt);
buffer->Indices.reallocate(idxCnt);
core::map<video::S3DVertex, int> vertMap; // copy material
int vertLocation; buffer->Material = original->getMaterial();
// copy indices
const u32 idxCnt = original->getIndexCount();
const u16* indices = original->getIndices();
buffer->Indices.reallocate(idxCnt);
for (u32 i=0; i < idxCnt; ++i)
buffer->Indices.push_back(indices[i]);
// copy vertices // copy vertices
const video::E_VERTEX_TYPE vType = original->getVertexType(); const u32 vtxCnt = original->getVertexCount();
video::S3DVertex vNew; buffer->Vertices.reallocate(vtxCnt);
for (u32 i=0; i<idxCnt; ++i)
{
switch(vType)
{
case video::EVT_STANDARD:
{
video::S3DVertex* v =
(video::S3DVertex*)original->getVertices();
vNew = v[idx[i]];
}
break;
case video::EVT_2TCOORDS:
{
video::S3DVertex2TCoords* v =
(video::S3DVertex2TCoords*)original->getVertices();
vNew = video::S3DVertex(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
break;
case video::EVT_TANGENTS:
{
video::S3DVertexTangents* v =
(video::S3DVertexTangents*)original->getVertices();
vNew = video::S3DVertex(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
break;
}
core::map<video::S3DVertex, int>::Node* n = vertMap.find(vNew);
if (n)
{
vertLocation = n->getValue();
}
else
{
vertLocation = buffer->Vertices.size();
buffer->Vertices.push_back(vNew);
vertMap.insert(vNew, vertLocation);
}
// create new indices const video::E_VERTEX_TYPE vType = original->getVertexType();
buffer->Indices.push_back(vertLocation); switch(vType)
{
case video::EVT_STANDARD:
{
const S3DVertex* v = (const S3DVertex*)original->getVertices();
for (u32 i=0; i < vtxCnt; ++i)
buffer->Vertices.push_back( v[i] );
}
break;
case video::EVT_2TCOORDS:
{
const S3DVertex2TCoords* v =(const S3DVertex2TCoords*)original->getVertices();
for (u32 i=0; i < vtxCnt; ++i)
buffer->Vertices.push_back( S3DVertex(
v[i].Pos, v[i].Normal, v[i].Color, v[i].TCoords) );
}
break;
case video::EVT_TANGENTS:
{
const S3DVertexTangents* v =(const S3DVertexTangents*)original->getVertices();
for (u32 i=0; i < vtxCnt; ++i)
buffer->Vertices.push_back( S3DVertex(
v[i].Pos, v[i].Normal, v[i].Color, v[i].TCoords) );
}
break;
} }
buffer->recalculateBoundingBox(); buffer->recalculateBoundingBox();
// add new buffer // add new buffer
clone->addMeshBuffer(buffer); clone->addMeshBuffer(buffer);

View File

@ -2087,6 +2087,15 @@ void CNullDriver::setMaterialRendererName(s32 idx, const char* name)
MaterialRenderers[idx].Name = name; MaterialRenderers[idx].Name = name;
} }
void CNullDriver::swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames)
{
if ( idx1 < MaterialRenderers.size() && idx2 < MaterialRenderers.size() )
{
irr::core::swap(MaterialRenderers[idx1].Renderer, MaterialRenderers[idx2].Renderer);
if ( swapNames )
irr::core::swap(MaterialRenderers[idx1].Name, MaterialRenderers[idx2].Name);
}
}
//! Creates material attributes list from a material, usable for serialization and more. //! Creates material attributes list from a material, usable for serialization and more.
io::IAttributes* CNullDriver::createAttributesFromMaterial(const video::SMaterial& material, io::IAttributes* CNullDriver::createAttributesFromMaterial(const video::SMaterial& material,

View File

@ -612,6 +612,9 @@ namespace video
//! Sets the name of a material renderer. //! Sets the name of a material renderer.
virtual void setMaterialRendererName(s32 idx, const char* name) _IRR_OVERRIDE_; virtual void setMaterialRendererName(s32 idx, const char* name) _IRR_OVERRIDE_;
//! Swap the material renderers used for certain id's
virtual void swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames) _IRR_OVERRIDE_;
//! Creates material attributes list from a material, usable for serialization and more. //! Creates material attributes list from a material, usable for serialization and more.
virtual io::IAttributes* createAttributesFromMaterial(const video::SMaterial& material, virtual io::IAttributes* createAttributesFromMaterial(const video::SMaterial& material,
io::SAttributeReadWriteOptions* options=0) _IRR_OVERRIDE_; io::SAttributeReadWriteOptions* options=0) _IRR_OVERRIDE_;

View File

@ -571,7 +571,7 @@ public:
//! Compare material to current cache and update it when there are differences //! Compare material to current cache and update it when there are differences
// Some material renderers do change the cache beyond the original material settings // Some material renderers do change the cache beyond the original material settings
// This correct the material to represent the current cache state again. // This corrects the material to represent the current cache state again.
void correctCacheMaterial(irr::video::SMaterial& material) void correctCacheMaterial(irr::video::SMaterial& material)
{ {
// Fix textures which got removed // Fix textures which got removed

View File

@ -324,9 +324,10 @@ bool CPLYMeshFileLoader::readVertex(const SPLYElement &Element, scene::CDynamicM
vert.Normal.Y = getFloat(t); vert.Normal.Y = getFloat(t);
result=true; result=true;
} }
else if (Element.Properties[i].Name == "u") // there isn't a single convention for the UV, some software like Blender or Assimp uses "st" instead of "uv"
else if (Element.Properties[i].Name == "u" || Element.Properties[i].Name == "s")
vert.TCoords.X = getFloat(t); vert.TCoords.X = getFloat(t);
else if (Element.Properties[i].Name == "v") else if (Element.Properties[i].Name == "v" || Element.Properties[i].Name == "t")
vert.TCoords.Y = getFloat(t); vert.TCoords.Y = getFloat(t);
else if (Element.Properties[i].Name == "red") else if (Element.Properties[i].Name == "red")
{ {

View File

@ -39,11 +39,21 @@ bool CPLYMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
os::Printer::log("Writing mesh", file->getFileName()); os::Printer::log("Writing mesh", file->getFileName());
// write PLY header // write PLY header
core::stringc header = core::stringc header = "ply\n";
"ply\n"
"format ascii 1.0\n" if (flags & scene::EMWF_WRITE_BINARY)
"comment Irrlicht Engine "; {
#ifdef __BIG_ENDIAN__
header += "format binary_big_endian 1.0\n";
#else
header += "format binary_little_endian 1.0\n";
#endif
}
else
header += "format ascii 1.0\n";
header += "comment Irrlicht Engine ";
header += IRRLICHT_SDK_VERSION; header += IRRLICHT_SDK_VERSION;
// get vertex and triangle counts // get vertex and triangle counts
@ -66,16 +76,12 @@ bool CPLYMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
"property float z\n" "property float z\n"
"property float nx\n" "property float nx\n"
"property float ny\n" "property float ny\n"
"property float nz\n"; "property float nz\n"
// todo: writer flags for extended (r,g,b,u,v) and non-standard (alpha,u1,uv,tx,ty,tz) properties "property float s\n"
// "property uchar red\n" "property float t\n"
// "property uchar green\n" "property uchar red\n"
// "property uchar blue\n" "property uchar green\n"
// "property uchar alpha\n" "property uchar blue\n";
// "property float u\n"
// "property float v\n";
// "property float u1\n
// "property float v1\n"
// "property float tx\n" // "property float tx\n"
// "property float ty\n" // "property float ty\n"
// "property float tz\n" // "property float tz\n"
@ -97,38 +103,61 @@ bool CPLYMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
for (u32 i=0; i < mesh->getMeshBufferCount(); ++i) for (u32 i=0; i < mesh->getMeshBufferCount(); ++i)
{ {
scene::IMeshBuffer* mb = mesh->getMeshBuffer(i); const scene::IMeshBuffer* mb = mesh->getMeshBuffer(i);
u32 vertexSize = 0;
switch(mb->getVertexType())
{
case video::EVT_STANDARD:
vertexSize = sizeof(video::S3DVertex);
break;
case video::EVT_2TCOORDS:
vertexSize = sizeof(video::S3DVertex2TCoords);
break;
case video::EVT_TANGENTS:
vertexSize = sizeof(video::S3DVertexTangents);
break;
}
u8 *vertices = (u8*)mb->getVertices() ;
for (u32 j=0; j < mb->getVertexCount(); ++j) for (u32 j=0; j < mb->getVertexCount(); ++j)
{ {
const core::vector3df& pos = mb->getPosition(j); u8 *buf = vertices + j * vertexSize;
const core::vector3df& n = mb->getNormal(j); const video::S3DVertex* vertex = ( (video::S3DVertex*)buf );
// const core::vector2df& tc = mb->getTCoords(j); const core::vector3df& pos = vertex->Pos;
const core::vector3df& n = vertex->Normal;
const core::vector2df& uv = vertex->TCoords;
const video::SColor& color = vertex->Color;
u8 *buf = (u8*)mb->getVertices(); if (flags & scene::EMWF_WRITE_BINARY)
switch(mb->getVertexType())
{ {
case video::EVT_STANDARD: // Y and Z are flipped
buf += sizeof(video::S3DVertex)*j; file->write(&pos.X, 4);
break; file->write(&pos.Z, 4);
case video::EVT_2TCOORDS: file->write(&pos.Y, 4);
buf += sizeof(video::S3DVertex2TCoords)*j;
break; file->write(&n.X, 4);
case video::EVT_TANGENTS: file->write(&n.Z, 4);
buf += sizeof(video::S3DVertexTangents)*j; file->write(&n.Y, 4);
break;
file->write(&uv, 8);
const u32 r = color.getRed(), g = color.getGreen(), b = color.getBlue();
file->write(&r, 1);
file->write(&g, 1);
file->write(&b, 1);
} }
// video::SColor &col = ( (video::S3DVertex*)buf )->Color; else
{
// x y z nx ny nz u v red green blue [u1 v1 | tx ty tz]\n
snprintf_irr(outLine, 1024,
"%f %f %f %f %f %f %f %f %d %d %d\n",// %u %u %u %u %f %f\n",
pos.X, pos.Z, pos.Y, // Y and Z are flipped
n.X, n.Z, n.Y,
uv.X, uv.Y,
color.getRed(), color.getGreen(), color.getBlue());
// x y z nx ny nz red green blue alpha u v [u1 v1 | tx ty tz]\n file->write(outLine, strlen(outLine));
snprintf_irr(outLine, 1024, }
"%f %f %f %f %f %f\n",// %u %u %u %u %f %f\n",
pos.X, pos.Z, pos.Y, // Y and Z are flipped
n.X, n.Z, n.Y);
/*col.getRed(), col.getGreen(), col.getBlue(), col.getAlpha(),
tc.X, tc.Y);*/
// write the line
file->write(outLine, strlen(outLine));
} }
} }
@ -136,6 +165,7 @@ bool CPLYMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
u32 StartOffset = 0; u32 StartOffset = 0;
// write triangles // write triangles
const unsigned char nbIndicesParFace = 3;
for (u32 i=0; i < mesh->getMeshBufferCount(); ++i) for (u32 i=0; i < mesh->getMeshBufferCount(); ++i)
{ {
scene::IMeshBuffer* mb = mesh->getMeshBuffer(i); scene::IMeshBuffer* mb = mesh->getMeshBuffer(i);
@ -155,15 +185,24 @@ bool CPLYMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
break; break;
case video::EIT_32BIT: case video::EIT_32BIT:
a += ((u32*)mb->getIndices()) [j+0]; a += ((u32*)mb->getIndices()) [j+0];
c += ((u32*)mb->getIndices()) [j+0]; c += ((u32*)mb->getIndices()) [j+1];
b += ((u32*)mb->getIndices()) [j+0]; b += ((u32*)mb->getIndices()) [j+2];
break; break;
} }
// count a b c\n if (flags & scene::EMWF_WRITE_BINARY)
snprintf_irr(outLine, 1024, "3 %u %u %u\n", a, b, c); {
// write the line file->write(&nbIndicesParFace, 1);
file->write(outLine, strlen(outLine)); file->write(&a, 4);
file->write(&b, 4);
file->write(&c, 4);
}
else
{
// count a b c\n
snprintf_irr(outLine, 1024, "3 %u %u %u\n", a, b, c);
file->write(outLine, strlen(outLine));
}
} }
// increment offset // increment offset

View File

@ -54,7 +54,7 @@ bool CSTLMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
os::Printer::log("Writing mesh", file->getFileName()); os::Printer::log("Writing mesh", file->getFileName());
if (flags & scene::EMWF_WRITE_COMPRESSED) if (flags & (scene::EMWF_WRITE_BINARY|scene::EMWF_WRITE_COMPRESSED) )
return writeMeshBinary(file, mesh, flags); return writeMeshBinary(file, mesh, flags);
else else
return writeMeshASCII(file, mesh, flags); return writeMeshASCII(file, mesh, flags);

View File

@ -38,6 +38,7 @@ namespace scene
TerrainData(patchSize, maxLOD, position, rotation, scale), RenderBuffer(0), TerrainData(patchSize, maxLOD, position, rotation, scale), RenderBuffer(0),
VerticesToRender(0), IndicesToRender(0), DynamicSelectorUpdate(false), VerticesToRender(0), IndicesToRender(0), DynamicSelectorUpdate(false),
OverrideDistanceThreshold(false), UseDefaultRotationPivot(true), ForceRecalculation(true), OverrideDistanceThreshold(false), UseDefaultRotationPivot(true), ForceRecalculation(true),
FixedBorderLOD(-1),
CameraMovementDelta(10.0f), CameraRotationDelta(1.0f),CameraFOVDelta(0.1f), CameraMovementDelta(10.0f), CameraRotationDelta(1.0f),CameraFOVDelta(0.1f),
TCoordScale1(1.0f), TCoordScale2(1.0f), SmoothFactor(0), FileSystem(fs) TCoordScale1(1.0f), TCoordScale2(1.0f), SmoothFactor(0), FileSystem(fs)
{ {
@ -640,7 +641,18 @@ namespace scene
{ {
const f32 distance = cameraPosition.getDistanceFromSQ(TerrainData.Patches[j].Center); const f32 distance = cameraPosition.getDistanceFromSQ(TerrainData.Patches[j].Center);
if ( FixedBorderLOD >= 0 )
{
TerrainData.Patches[j].CurrentLOD = FixedBorderLOD;
if (j < TerrainData.PatchCount
|| j >= (count - TerrainData.PatchCount)
|| (j % TerrainData.PatchCount) == 0
|| (j % TerrainData.PatchCount) == TerrainData.PatchCount-1)
continue;
}
TerrainData.Patches[j].CurrentLOD = 0; TerrainData.Patches[j].CurrentLOD = 0;
for (s32 i = TerrainData.MaxLOD - 1; i>0; --i) for (s32 i = TerrainData.MaxLOD - 1; i>0; --i)
{ {
if (distance >= TerrainData.LODDistanceThreshold[i]) if (distance >= TerrainData.LODDistanceThreshold[i])

View File

@ -202,6 +202,12 @@ namespace scene
//! Scales the two textures //! Scales the two textures
virtual void scaleTexture(f32 scale = 1.0f, f32 scale2 = 0.0f) _IRR_OVERRIDE_; virtual void scaleTexture(f32 scale = 1.0f, f32 scale2 = 0.0f) _IRR_OVERRIDE_;
//! Force node to use a fixed LOD level at the borders of the terrain.
virtual void setFixedBorderLOD(irr::s32 borderLOD) _IRR_OVERRIDE_
{
FixedBorderLOD = borderLOD;
}
//! Returns type of the scene node //! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const _IRR_OVERRIDE_ {return ESNT_TERRAIN;} virtual ESCENE_NODE_TYPE getType() const _IRR_OVERRIDE_ {return ESNT_TERRAIN;}
@ -303,6 +309,7 @@ namespace scene
bool OverrideDistanceThreshold; bool OverrideDistanceThreshold;
bool UseDefaultRotationPivot; bool UseDefaultRotationPivot;
bool ForceRecalculation; bool ForceRecalculation;
s32 FixedBorderLOD;
core::vector3df OldCameraPosition; core::vector3df OldCameraPosition;
core::vector3df OldCameraRotation; core::vector3df OldCameraRotation;

File diff suppressed because it is too large Load Diff