Merge from trunk, revisions 3831-3909. All fixes and additions from the last three month.
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@3910 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
7687813257
commit
5caf2b4045
45
changes.txt
45
changes.txt
|
@ -1,5 +1,27 @@
|
|||
Changes in 1.8 (??.??.2011)
|
||||
|
||||
- Add IGUIComboBox::setMaxSelectionRows and IGUIComboBox::getMaxSelectionRows
|
||||
|
||||
- Scenemanager switches from type ESNT_UNKNOWN to type ESNT_SCENE_MANAGER.
|
||||
|
||||
- Add getActiveFont to all elements which have setOverrideFont for cleaner code
|
||||
|
||||
- Add getOverrideFont to all elements which have setOverrideFont to have a consistent interface
|
||||
|
||||
- IGUIEditBox: added missing serialization for Border
|
||||
|
||||
- IGUIEditBox: remove bug that added spaces to the end of each line
|
||||
|
||||
- IGUIEditBox: fix crash that happened when wordwrapping was enabled, spaces were entered beyond the border and then cursor-key was pressed.
|
||||
|
||||
- IGUIEditBox::setDrawBackground added.
|
||||
|
||||
- CGUISkin::draw3DSunkenPane no longer ignores fillBackGround in non-flat mode. Also borderlines are no longer drawn overlapping to avoid ugly corners.
|
||||
|
||||
- CDummyTransformationSceneNode::clone() added.
|
||||
|
||||
- IParticleSystemSceneNode::doParticleSystem now public to allow rendering outside scenegraph.
|
||||
|
||||
- Renamed IOSOperator::getOperationSystemVersion to getOperatingSystemVersion. Changed return type from wchar_t to core::stringc, as that's the internal representation the name is built on.
|
||||
|
||||
- Added IGUITabControl::insertTab, IGUITabControl::removeTab, IGUITabControl::clear and IGUITabControl::getTabAt
|
||||
|
@ -12,7 +34,7 @@ Changes in 1.8 (??.??.2011)
|
|||
|
||||
- Added ISceneManager::createSceneNodeAnimator to create animators by name
|
||||
|
||||
- The Makefile now creates a symlink from the soname to the binary name during install. Binary compatibility is only confirmed between minor releases, so the only useful symlink is from libIrrlicht.so.1.8 to libIrrlicht.so.1.8.0; others should rightly fail.
|
||||
- The Makefile now creates a symlink from the soname to the binary name during install. Binary compatibility is only confirmed between same minor releases.
|
||||
|
||||
- Added SMF mesh loader, loads meshes from 3D World Studio. Originally written by Joseph Ellis
|
||||
|
||||
|
@ -266,6 +288,27 @@ The following names can be queried for the given types:
|
|||
|
||||
-----------------------------
|
||||
Changes in 1.7.3 (??.??.2011)
|
||||
|
||||
- editbox no longer moves text into next line when it fails wrapping creating senseless empty lines which mess up scrolling.
|
||||
|
||||
- Fix crash in editbox when scrolling up with empty first lines caused by textwrapping.
|
||||
|
||||
- triangle3d::isPointInside can now work with larger integers, old version failed already with values in the 3-digit range. It got also faster. (thx @ Eigen for report + testcase and REDDemon for patch proposal).
|
||||
|
||||
- Fix focus problem when removing an unfocused modal dialog reported by Reiko here: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=44358
|
||||
|
||||
- Add integer template specialization for vector3d::getSphericalCoordinateAngles which rounds angles to nearest integer now.
|
||||
|
||||
- Recalculate FrameRect and ScrollPos in CGUIEditBox when AbsoluteRect gets changed (thx @ serengeor for report + testcase)
|
||||
|
||||
- Fix 'k' in bigfont.png (thx @ Scrappi for reporting)
|
||||
|
||||
- fix serialization for CBillboardSceneNode, it had missed 2 color (thx for finding + patch from pc0de)
|
||||
|
||||
- EMIE_MOUSE_WHEEL messages now handled correctly in several gui-element when wheel isn't just 1.0 or -1.0 (thx @ Reiko for reporting)
|
||||
|
||||
- Fix problems in Textwrapping in CGUIStaticText. Did use wrong size and did ignore last word of the text (thx @ Reiko for bugreport)
|
||||
|
||||
- Fix crash in collada (.dae) loading
|
||||
|
||||
- Fix memory-leaks in example 22 MaterialViewer
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-W" />
|
||||
<Add option="-g" />
|
||||
<Add option="-W" />
|
||||
<Add option="-D_IRR_STATIC_LIB_" />
|
||||
<Add directory="../../lib/Linux" />
|
||||
</Compiler>
|
||||
|
@ -33,7 +33,7 @@
|
|||
<Add library="Xxf86vm" />
|
||||
<Add library="Xcursor" />
|
||||
<Add library="GL" />
|
||||
<Add directory="../../lib/gcc" />
|
||||
<Add directory="../../lib/Linux" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Linker>
|
||||
<Add library="Irrlicht" />
|
||||
<Add library="Xxf86vm" />
|
||||
<Add library="Xcursor" />
|
||||
<Add library="GL" />
|
||||
<Add directory="../../lib/Linux" />
|
||||
</Linker>
|
||||
</Target>
|
||||
|
@ -27,7 +29,7 @@
|
|||
<Add directory="../../include" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="../../lib/Win32-gcc/libIrrlicht.a" />
|
||||
<Add library="Irrlicht" />
|
||||
</Linker>
|
||||
<Unit filename="main.cpp" />
|
||||
<Extensions>
|
||||
|
|
|
@ -18,6 +18,9 @@ namespace scene
|
|||
name clashes with external scene nodes.*/
|
||||
enum ESCENE_NODE_TYPE
|
||||
{
|
||||
//! of type CSceneManager (note that ISceneManager is not(!) an ISceneNode)
|
||||
ESNT_SCENE_MANAGER = MAKE_IRR_ID('s','m','n','g'),
|
||||
|
||||
//! simple cube scene node
|
||||
ESNT_CUBE = MAKE_IRR_ID('c','u','b','e'),
|
||||
|
||||
|
|
|
@ -76,6 +76,9 @@ namespace scene
|
|||
/** If the camera's target and rotation are bound ( @see
|
||||
bindTargetAndRotation() ) then calling this will also change
|
||||
the camera's scene node rotation to match the target.
|
||||
Note that setTarget uses the current absolute position
|
||||
internally, so if you changed setPosition since last rendering you must
|
||||
call updateAbsolutePosition before using this function.
|
||||
\param pos Look at target of the camera, in world co-ordinates. */
|
||||
virtual void setTarget(const core::vector3df& pos) =0;
|
||||
|
||||
|
|
|
@ -284,7 +284,7 @@ struct SEvent
|
|||
//! Y position of mouse cursor
|
||||
s32 Y;
|
||||
|
||||
//! mouse wheel delta, usually 1.0 or -1.0.
|
||||
//! mouse wheel delta, often 1.0 or -1.0, but can have other values < 0.f or > 0.f;
|
||||
/** Only valid if event was EMIE_MOUSE_WHEEL */
|
||||
f32 Wheel;
|
||||
|
||||
|
|
|
@ -65,6 +65,15 @@ namespace gui
|
|||
\param font: New font to set. */
|
||||
virtual void setOverrideFont(IGUIFont* font=0) = 0;
|
||||
|
||||
//! Gets the override font (if any)
|
||||
/** \return The override font (may be 0) */
|
||||
virtual IGUIFont* getOverrideFont(void) const = 0;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
/** Currently this is the override font when one is set and the
|
||||
font of the active skin otherwise */
|
||||
virtual IGUIFont* getActiveFont() const = 0;
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in normal state.
|
||||
/** \param image: Image to be displayed */
|
||||
virtual void setImage(video::ITexture* image=0) = 0;
|
||||
|
|
|
@ -55,6 +55,12 @@ namespace gui
|
|||
\param vertical: EGUIA_UPPERLEFT to align with top edge,
|
||||
EGUIA_LOWEERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */
|
||||
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0;
|
||||
|
||||
//! Set the maximal number of rows for the selection listbox
|
||||
virtual void setMaxSelectionRows(u32 max) = 0;
|
||||
|
||||
//! Get the maximimal number of rows for the selection listbox
|
||||
virtual u32 getMaxSelectionRows() const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,15 @@ namespace gui
|
|||
\param font: New font to set. */
|
||||
virtual void setOverrideFont(IGUIFont* font=0) = 0;
|
||||
|
||||
//! Gets the override font (if any)
|
||||
/** \return The override font (may be 0) */
|
||||
virtual IGUIFont* getOverrideFont() const = 0;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
/** Currently this is the override font when one is set and the
|
||||
font of the active skin otherwise */
|
||||
virtual IGUIFont* getActiveFont() const = 0;
|
||||
|
||||
//! Sets another color for the text.
|
||||
/** If set, the edit box does not use the EGDC_BUTTON_TEXT color defined
|
||||
in the skin, but the set color instead. You don't need to call
|
||||
|
@ -51,6 +60,9 @@ namespace gui
|
|||
/** \return true if the override color is enabled, false otherwise */
|
||||
virtual bool isOverrideColorEnabled(void) const = 0;
|
||||
|
||||
//! Sets whether to draw the background
|
||||
virtual void setDrawBackground(bool draw) = 0;
|
||||
|
||||
//! Turns the border on or off
|
||||
/** \param border: true if you want the border to be drawn, false if not */
|
||||
virtual void setDrawBorder(bool border) = 0;
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace gui
|
|||
virtual void setStepSize(f32 step=1.f) = 0;
|
||||
|
||||
//! Sets the number of decimal places to display.
|
||||
//! Note that this also rounds the range to the same number of decimal places.
|
||||
/** \param places: The number of decimal places to display, use -1 to reset */
|
||||
virtual void setDecimalPlaces(s32 places) = 0;
|
||||
|
||||
|
|
|
@ -32,6 +32,11 @@ namespace gui
|
|||
/** \return The override font (may be 0) */
|
||||
virtual IGUIFont* getOverrideFont(void) const = 0;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
/** Currently this is the override font when one is set and the
|
||||
font of the active skin otherwise */
|
||||
virtual IGUIFont* getActiveFont() const = 0;
|
||||
|
||||
//! Sets another color for the text.
|
||||
/** If set, the static text does not use the EGDC_BUTTON_TEXT color defined
|
||||
in the skin, but the set color instead. You don't need to call
|
||||
|
@ -91,10 +96,10 @@ namespace gui
|
|||
/** If the text is broken, this returns the width of the widest line
|
||||
\return The width of the text, or the widest broken line. */
|
||||
virtual s32 getTextWidth(void) const = 0;
|
||||
|
||||
|
||||
//! Set whether the text in this label should be clipped if it goes outside bounds
|
||||
virtual void setTextRestrainedInside(bool restrainedInside) = 0;
|
||||
|
||||
|
||||
//! Checks if the text in this label should be clipped if it goes outside bounds
|
||||
virtual bool isTextRestrainedInside() const = 0;
|
||||
|
||||
|
|
|
@ -67,6 +67,11 @@ public:
|
|||
//! Remove all currently visible particles
|
||||
virtual void clearParticles() = 0;
|
||||
|
||||
//! Do manually update the particles.
|
||||
//! This should only be called when you want to render the node outside the scenegraph,
|
||||
//! as the node will care about this otherwise automatically.
|
||||
virtual void doParticleSystem(u32 time) = 0;
|
||||
|
||||
//! Gets the particle emitter, which creates the particles.
|
||||
/** \return The particle emitter. Can be 0 if none is set. */
|
||||
virtual IParticleEmitter* getEmitter() =0;
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace scene
|
|||
//! Transparent effect scene nodes, drawn after Transparent nodes. They are sorted from back to front and drawn in that order.
|
||||
ESNRP_TRANSPARENT_EFFECT =32,
|
||||
|
||||
//! Drawn after the transparent nodes, the time for drawing shadow volumes
|
||||
//! Drawn after the solid nodes, before the transparent nodes, the time for drawing shadow volumes
|
||||
ESNRP_SHADOW =64
|
||||
};
|
||||
|
||||
|
|
|
@ -14,10 +14,6 @@ namespace irr
|
|||
class ITimer : public virtual IReferenceCounted
|
||||
{
|
||||
public:
|
||||
|
||||
//! destructor
|
||||
virtual ~ITimer() {}
|
||||
|
||||
//! Returns current real time in milliseconds of the system.
|
||||
/** This value does not start with 0 when the application starts.
|
||||
For example in one implementation the value returned could be the
|
||||
|
@ -105,4 +101,3 @@ public:
|
|||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace irr
|
|||
{
|
||||
class ILogger;
|
||||
class IEventReceiver;
|
||||
class IRandomizer;
|
||||
|
||||
namespace io {
|
||||
class IFileSystem;
|
||||
|
@ -131,6 +132,22 @@ namespace irr
|
|||
\return Pointer to the ITimer object. */
|
||||
virtual ITimer* getTimer() = 0;
|
||||
|
||||
//! Provides access to the engine's currently set randomizer.
|
||||
/** \return Pointer to the IRandomizer object. */
|
||||
virtual IRandomizer* getRandomizer() const =0;
|
||||
|
||||
//! Sets a new randomizer.
|
||||
/** \param r Pointer to the new IRandomizer object. This object is
|
||||
grab()'ed by the engine and will be released upon the next setRandomizer
|
||||
call or upon device destruction. */
|
||||
virtual void setRandomizer(IRandomizer* r) =0;
|
||||
|
||||
//! Creates a new default randomizer.
|
||||
/** The default randomizer provides the random sequence known from previous
|
||||
Irrlicht versions and is the initial randomizer set on device creation.
|
||||
\return Pointer to the default IRandomizer object. */
|
||||
virtual IRandomizer* createDefaultRandomizer() const =0;
|
||||
|
||||
//! Sets the caption of the window.
|
||||
/** \param text: New text of the window caption. */
|
||||
virtual void setWindowCaption(const wchar_t* text) = 0;
|
||||
|
|
189
include/irrMap.h
189
include/irrMap.h
|
@ -58,6 +58,12 @@ class map
|
|||
return Value;
|
||||
}
|
||||
|
||||
ValueTypeRB& getValue()
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Value;
|
||||
}
|
||||
|
||||
KeyTypeRB getKey() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
|
@ -157,7 +163,7 @@ class map
|
|||
return Cur==0;
|
||||
}
|
||||
|
||||
Node* getNode()
|
||||
Node* getNode() const
|
||||
{
|
||||
return Cur;
|
||||
}
|
||||
|
@ -179,13 +185,12 @@ class map
|
|||
dec();
|
||||
}
|
||||
|
||||
|
||||
Node* operator -> ()
|
||||
Node* operator->()
|
||||
{
|
||||
return getNode();
|
||||
}
|
||||
|
||||
Node& operator* ()
|
||||
Node& operator*()
|
||||
{
|
||||
_IRR_DEBUG_BREAK_IF(atEnd()) // access violation
|
||||
|
||||
|
@ -194,14 +199,14 @@ class map
|
|||
|
||||
private:
|
||||
|
||||
Node* getMin(Node* n)
|
||||
Node* getMin(Node* n) const
|
||||
{
|
||||
while(n && n->getLeftChild())
|
||||
n = n->getLeftChild();
|
||||
return n;
|
||||
}
|
||||
|
||||
Node* getMax(Node* n)
|
||||
Node* getMax(Node* n) const
|
||||
{
|
||||
while(n && n->getRightChild())
|
||||
n = n->getRightChild();
|
||||
|
@ -275,6 +280,153 @@ class map
|
|||
Node* Cur;
|
||||
}; // Iterator
|
||||
|
||||
//! Const Iterator
|
||||
class ConstIterator
|
||||
{
|
||||
public:
|
||||
|
||||
ConstIterator() : Root(0), Cur(0) {}
|
||||
|
||||
// Constructor(Node*)
|
||||
ConstIterator(const Node* root) : Root(root)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
ConstIterator(const ConstIterator& src) : Root(src.Root), Cur(src.Cur) {}
|
||||
ConstIterator(const Iterator& src) : Root(src.Root), Cur(src.Cur) {}
|
||||
|
||||
void reset(bool atLowest=true)
|
||||
{
|
||||
if (atLowest)
|
||||
Cur = getMin(Root);
|
||||
else
|
||||
Cur = getMax(Root);
|
||||
}
|
||||
|
||||
bool atEnd() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Cur==0;
|
||||
}
|
||||
|
||||
const Node* getNode() const
|
||||
{
|
||||
return Cur;
|
||||
}
|
||||
|
||||
ConstIterator& operator=(const ConstIterator& src)
|
||||
{
|
||||
Root = src.Root;
|
||||
Cur = src.Cur;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
void operator++(int)
|
||||
{
|
||||
inc();
|
||||
}
|
||||
|
||||
void operator--(int)
|
||||
{
|
||||
dec();
|
||||
}
|
||||
|
||||
const Node* operator->()
|
||||
{
|
||||
return getNode();
|
||||
}
|
||||
|
||||
const Node& operator*()
|
||||
{
|
||||
_IRR_DEBUG_BREAK_IF(atEnd()) // access violation
|
||||
|
||||
return *Cur;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const Node* getMin(const Node* n) const
|
||||
{
|
||||
while(n && n->getLeftChild())
|
||||
n = n->getLeftChild();
|
||||
return n;
|
||||
}
|
||||
|
||||
const Node* getMax(const Node* n) const
|
||||
{
|
||||
while(n && n->getRightChild())
|
||||
n = n->getRightChild();
|
||||
return n;
|
||||
}
|
||||
|
||||
void inc()
|
||||
{
|
||||
// Already at end?
|
||||
if (Cur==0)
|
||||
return;
|
||||
|
||||
if (Cur->getRightChild())
|
||||
{
|
||||
// If current node has a right child, the next higher node is the
|
||||
// node with lowest key beneath the right child.
|
||||
Cur = getMin(Cur->getRightChild());
|
||||
}
|
||||
else if (Cur->isLeftChild())
|
||||
{
|
||||
// No right child? Well if current node is a left child then
|
||||
// the next higher node is the parent
|
||||
Cur = Cur->getParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current node neither is left child nor has a right child.
|
||||
// Ie it is either right child or root
|
||||
// The next higher node is the parent of the first non-right
|
||||
// child (ie either a left child or the root) up in the
|
||||
// hierarchy. Root's parent is 0.
|
||||
while(Cur->isRightChild())
|
||||
Cur = Cur->getParent();
|
||||
Cur = Cur->getParent();
|
||||
}
|
||||
}
|
||||
|
||||
void dec()
|
||||
{
|
||||
// Already at end?
|
||||
if (Cur==0)
|
||||
return;
|
||||
|
||||
if (Cur->getLeftChild())
|
||||
{
|
||||
// If current node has a left child, the next lower node is the
|
||||
// node with highest key beneath the left child.
|
||||
Cur = getMax(Cur->getLeftChild());
|
||||
}
|
||||
else if (Cur->isRightChild())
|
||||
{
|
||||
// No left child? Well if current node is a right child then
|
||||
// the next lower node is the parent
|
||||
Cur = Cur->getParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current node neither is right child nor has a left child.
|
||||
// Ie it is either left child or root
|
||||
// The next higher node is the parent of the first non-left
|
||||
// child (ie either a right child or the root) up in the
|
||||
// hierarchy. Root's parent is 0.
|
||||
|
||||
while(Cur->isLeftChild())
|
||||
Cur = Cur->getParent();
|
||||
Cur = Cur->getParent();
|
||||
}
|
||||
}
|
||||
|
||||
const Node* Root;
|
||||
const Node* Cur;
|
||||
}; // ConstIterator
|
||||
|
||||
|
||||
//! Parent First Iterator.
|
||||
|
@ -286,11 +438,7 @@ class map
|
|||
{
|
||||
public:
|
||||
|
||||
|
||||
ParentFirstIterator() : Root(0), Cur(0)
|
||||
{
|
||||
}
|
||||
|
||||
ParentFirstIterator() : Root(0), Cur(0) {}
|
||||
|
||||
explicit ParentFirstIterator(Node* root) : Root(root), Cur(0)
|
||||
{
|
||||
|
@ -302,7 +450,6 @@ class map
|
|||
Cur = Root;
|
||||
}
|
||||
|
||||
|
||||
bool atEnd() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
|
@ -314,7 +461,6 @@ class map
|
|||
return Cur;
|
||||
}
|
||||
|
||||
|
||||
ParentFirstIterator& operator=(const ParentFirstIterator& src)
|
||||
{
|
||||
Root = src.Root;
|
||||
|
@ -322,13 +468,11 @@ class map
|
|||
return (*this);
|
||||
}
|
||||
|
||||
|
||||
void operator++(int)
|
||||
{
|
||||
inc();
|
||||
}
|
||||
|
||||
|
||||
Node* operator -> ()
|
||||
{
|
||||
return getNode();
|
||||
|
@ -795,27 +939,36 @@ class map
|
|||
//------------------------------
|
||||
|
||||
//! Returns an iterator
|
||||
Iterator getIterator()
|
||||
Iterator getIterator() const
|
||||
{
|
||||
Iterator it(getRoot());
|
||||
return it;
|
||||
}
|
||||
|
||||
//! Returns a Constiterator
|
||||
ConstIterator getConstIterator() const
|
||||
{
|
||||
Iterator it(getRoot());
|
||||
return it;
|
||||
}
|
||||
|
||||
//! Returns a ParentFirstIterator.
|
||||
//! Traverses the tree from top to bottom. Typical usage is
|
||||
//! when storing the tree structure, because when reading it
|
||||
//! later (and inserting elements) the tree structure will
|
||||
//! be the same.
|
||||
ParentFirstIterator getParentFirstIterator()
|
||||
ParentFirstIterator getParentFirstIterator() const
|
||||
{
|
||||
ParentFirstIterator it(getRoot());
|
||||
return it;
|
||||
}
|
||||
|
||||
//! Returns a ParentLastIterator to traverse the tree from
|
||||
//! bottom to top.
|
||||
//! Typical usage is when deleting all elements in the tree
|
||||
//! because you must delete the children before you delete
|
||||
//! their parent.
|
||||
ParentLastIterator getParentLastIterator()
|
||||
ParentLastIterator getParentLastIterator() const
|
||||
{
|
||||
ParentLastIterator it(getRoot());
|
||||
return it;
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
#include "IMeshManipulator.h"
|
||||
#include "IMeshSceneNode.h"
|
||||
#include "IMeshWriter.h"
|
||||
#include "IColladaMeshWriter.h"
|
||||
#include "IMetaTriangleSelector.h"
|
||||
#include "IOSOperator.h"
|
||||
#include "IParticleSystemSceneNode.h" // also includes all emitters and attractors
|
||||
|
|
|
@ -648,24 +648,20 @@ inline core::quaternion& quaternion::rotationFromTo(const vector3df& from, const
|
|||
else if (d <= -1.0f) // exactly opposite
|
||||
{
|
||||
core::vector3df axis(1.0f, 0.f, 0.f);
|
||||
axis = axis.crossProduct(core::vector3df(X,Y,Z));
|
||||
axis = axis.crossProduct(v0);
|
||||
if (axis.getLength()==0)
|
||||
{
|
||||
axis.set(0.f,1.f,0.f);
|
||||
axis.crossProduct(core::vector3df(X,Y,Z));
|
||||
axis.crossProduct(v0);
|
||||
}
|
||||
return this->fromAngleAxis(core::PI, axis);
|
||||
// same as fromAngleAxis(core::PI, axis).normalize();
|
||||
return set(axis.X, axis.Y, axis.Z, 0).normalize();
|
||||
}
|
||||
|
||||
const f32 s = sqrtf( (1+d)*2 ); // optimize inv_sqrt
|
||||
const f32 invs = 1.f / s;
|
||||
const vector3df c = v0.crossProduct(v1)*invs;
|
||||
X = c.X;
|
||||
Y = c.Y;
|
||||
Z = c.Z;
|
||||
W = s * 0.5f;
|
||||
|
||||
return *this;
|
||||
return set(c.X, c.Y, c.Z, s * 0.5f).normalize();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -81,21 +81,39 @@ namespace core
|
|||
return d2 < d3 ? rbc : rca;
|
||||
}
|
||||
|
||||
//! Check if a point is inside the triangle
|
||||
//! Check if a point is inside the triangle (border-points count also as inside)
|
||||
/** \param p Point to test. Assumes that this point is already
|
||||
on the plane of the triangle.
|
||||
\return True if the point is inside the triangle, otherwise false. */
|
||||
bool isPointInside(const vector3d<T>& p) const
|
||||
{
|
||||
return (isOnSameSide(p, pointA, pointB, pointC) &&
|
||||
isOnSameSide(p, pointB, pointA, pointC) &&
|
||||
isOnSameSide(p, pointC, pointA, pointB));
|
||||
const vector3d<T> a = pointC - pointA;
|
||||
const vector3d<T> b = pointB - pointA;
|
||||
const vector3d<T> c = p - pointA;
|
||||
|
||||
const f64 dotAA = a.dotProduct( a);
|
||||
const f64 dotAB = a.dotProduct( b);
|
||||
const f64 dotAC = a.dotProduct( c);
|
||||
const f64 dotBB = b.dotProduct( b);
|
||||
const f64 dotBC = b.dotProduct( c);
|
||||
|
||||
// get coordinates in barycentric coordinate system
|
||||
const f64 invDenom = 1/(dotAA * dotBB - dotAB * dotAB);
|
||||
const f64 u = (dotBB * dotAC - dotAB * dotBC) * invDenom;
|
||||
const f64 v = (dotAA * dotBC - dotAB * dotAC ) * invDenom;
|
||||
|
||||
// We count border-points as inside to keep downward compatibility.
|
||||
// That's why we use >= and <= instead of > and < as more commonly seen on the web.
|
||||
return (u >= 0) && (v >= 0) && (u + v <= 1);
|
||||
}
|
||||
|
||||
//! Check if a point is inside the triangle.
|
||||
/** This method is an implementation of the example used in a
|
||||
paper by Kasper Fauerby original written by Keidy from
|
||||
Mr-Gamemaker.
|
||||
This was once faster than an old isPointInside implementation, but the
|
||||
current isPointInside is usualy as fast, sometimes even faster.
|
||||
Border-points in isPointInsideFast are not defined, some are inside and some outside.
|
||||
\param p Point to test. Assumes that this point is already
|
||||
on the plane of the triangle.
|
||||
\return True if point is inside the triangle, otherwise false. */
|
||||
|
|
|
@ -246,7 +246,7 @@ public:
|
|||
if (tmp < 0.0)
|
||||
tmp = -tmp;
|
||||
if ( tmp > 1.0 ) // avoid floating-point trouble
|
||||
tmp = 1.0;
|
||||
tmp = 1.0;
|
||||
|
||||
return atan(sqrt(1 - tmp*tmp) / tmp) * RADTODEG64;
|
||||
}
|
||||
|
|
|
@ -421,6 +421,26 @@ namespace core
|
|||
template <>
|
||||
inline vector3d<s32>& vector3d<s32>::operator /=(s32 val) {X/=val;Y/=val;Z/=val; return *this;}
|
||||
|
||||
template <>
|
||||
inline vector3d<s32> vector3d<s32>::getSphericalCoordinateAngles()
|
||||
{
|
||||
vector3d<s32> angle;
|
||||
const f64 length = X*X + Y*Y + Z*Z;
|
||||
|
||||
if (length)
|
||||
{
|
||||
if (X!=0)
|
||||
{
|
||||
angle.Y = round32((f32)(atan2((f64)Z,(f64)X) * RADTODEG64));
|
||||
}
|
||||
else if (Z<0)
|
||||
angle.Y=180;
|
||||
|
||||
angle.X = round32((f32)(acos(Y * core::reciprocal_squareroot(length)) * RADTODEG64));
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
//! Typedef for a f32 3d vector.
|
||||
typedef vector3d<f32> vector3df;
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
@ -15,8 +15,7 @@ namespace scene
|
|||
{
|
||||
|
||||
const s32 MD2_FRAME_SHIFT = 2;
|
||||
const f32 MD2_FRAME_SHIFT_RECIPROCAL = 1.f / ( 1 << MD2_FRAME_SHIFT );
|
||||
|
||||
const f32 MD2_FRAME_SHIFT_RECIPROCAL = 1.f / (1 << MD2_FRAME_SHIFT);
|
||||
|
||||
const s32 Q2_VERTEX_NORMAL_TABLE_SIZE = 162;
|
||||
|
||||
|
@ -194,27 +193,27 @@ struct SMD2AnimationType
|
|||
|
||||
static const SMD2AnimationType MD2AnimationTypeList[21] =
|
||||
{
|
||||
{ 0, 39, 9 }, // STAND
|
||||
{ 40, 45, 10 }, // RUN
|
||||
{ 46, 53, 10 }, // ATTACK
|
||||
{ 54, 57, 7 }, // PAIN_A
|
||||
{ 58, 61, 7 }, // PAIN_B
|
||||
{ 62, 65, 7 }, // PAIN_C
|
||||
{ 66, 71, 7 }, // JUMP
|
||||
{ 72, 83, 7 }, // FLIP
|
||||
{ 84, 94, 7 }, // SALUTE
|
||||
{ 95, 111, 10 }, // FALLBACK
|
||||
{ 112, 122, 7 }, // WAVE
|
||||
{ 123, 134, 6 }, // POINT
|
||||
{ 135, 153, 10 }, // CROUCH_STAND
|
||||
{ 154, 159, 7 }, // CROUCH_WALK
|
||||
{ 160, 168, 10 }, // CROUCH_ATTACK
|
||||
{ 169, 172, 7 }, // CROUCH_PAIN
|
||||
{ 173, 177, 5 }, // CROUCH_DEATH
|
||||
{ 178, 183, 7 }, // DEATH_FALLBACK
|
||||
{ 184, 189, 7 }, // DEATH_FALLFORWARD
|
||||
{ 190, 197, 7 }, // DEATH_FALLBACKSLOW
|
||||
{ 198, 198, 5 }, // BOOM
|
||||
{ 0, 39, 9}, // STAND
|
||||
{ 40, 45, 10}, // RUN
|
||||
{ 46, 53, 10}, // ATTACK
|
||||
{ 54, 57, 7}, // PAIN_A
|
||||
{ 58, 61, 7}, // PAIN_B
|
||||
{ 62, 65, 7}, // PAIN_C
|
||||
{ 66, 71, 7}, // JUMP
|
||||
{ 72, 83, 7}, // FLIP
|
||||
{ 84, 94, 7}, // SALUTE
|
||||
{ 95, 111, 10}, // FALLBACK
|
||||
{112, 122, 7}, // WAVE
|
||||
{123, 134, 6}, // POINT
|
||||
{135, 153, 10}, // CROUCH_STAND
|
||||
{154, 159, 7}, // CROUCH_WALK
|
||||
{160, 168, 10}, // CROUCH_ATTACK
|
||||
{169, 172, 7}, // CROUCH_PAIN
|
||||
{173, 177, 5}, // CROUCH_DEATH
|
||||
{178, 183, 7}, // DEATH_FALLBACK
|
||||
{184, 189, 7}, // DEATH_FALLFORWARD
|
||||
{190, 197, 7}, // DEATH_FALLBACKSLOW
|
||||
{198, 198, 5}, // BOOM
|
||||
};
|
||||
|
||||
|
||||
|
@ -238,6 +237,7 @@ CAnimatedMeshMD2::~CAnimatedMeshMD2()
|
|||
InterpolationBuffer->drop();
|
||||
}
|
||||
|
||||
|
||||
//! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh.
|
||||
u32 CAnimatedMeshMD2::getFrameCount() const
|
||||
{
|
||||
|
@ -294,7 +294,6 @@ void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop,
|
|||
{
|
||||
u32 firstFrame, secondFrame;
|
||||
f32 div;
|
||||
core::vector3df* NormalTable = (core::vector3df*)&Q2_VERTEX_NORMAL_TABLE;
|
||||
|
||||
// TA: resolve missing ipol in loop between end-start
|
||||
|
||||
|
@ -311,10 +310,10 @@ void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop,
|
|||
u32 e = endFrameLoop >> MD2_FRAME_SHIFT;
|
||||
|
||||
firstFrame = frame >> MD2_FRAME_SHIFT;
|
||||
secondFrame = core::if_c_a_else_b ( firstFrame + 1 > e, s, firstFrame + 1 );
|
||||
secondFrame = core::if_c_a_else_b(firstFrame + 1 > e, s, firstFrame + 1);
|
||||
|
||||
firstFrame = core::s32_min ( FrameCount - 1, firstFrame );
|
||||
secondFrame = core::s32_min ( FrameCount - 1, secondFrame );
|
||||
firstFrame = core::s32_min(FrameCount - 1, firstFrame);
|
||||
secondFrame = core::s32_min(FrameCount - 1, secondFrame);
|
||||
|
||||
//div = (frame % (1<<MD2_FRAME_SHIFT)) / (f32)(1<<MD2_FRAME_SHIFT);
|
||||
frame &= (1<<MD2_FRAME_SHIFT) - 1;
|
||||
|
@ -322,24 +321,29 @@ void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop,
|
|||
}
|
||||
|
||||
video::S3DVertex* target = static_cast<video::S3DVertex*>(InterpolationBuffer->getVertices());
|
||||
SMD2Vert* first = FrameList[firstFrame].pointer();
|
||||
SMD2Vert* second = FrameList[secondFrame].pointer();
|
||||
SMD2Vert* first = FrameList[firstFrame].pointer();
|
||||
SMD2Vert* second = FrameList[secondFrame].pointer();
|
||||
|
||||
// interpolate both frames
|
||||
const u32 count = FrameList[firstFrame].size();
|
||||
for (u32 i=0; i<count; ++i)
|
||||
{
|
||||
core::vector3df one, two;
|
||||
one.X = f32(first->Pos.X) * FrameTransforms[firstFrame].scale.X + FrameTransforms[firstFrame].translate.X;
|
||||
one.Y = f32(first->Pos.Y) * FrameTransforms[firstFrame].scale.Y + FrameTransforms[firstFrame].translate.Y;
|
||||
one.Z = f32(first->Pos.Z) * FrameTransforms[firstFrame].scale.Z + FrameTransforms[firstFrame].translate.Z;
|
||||
two.X = f32(second->Pos.X) * FrameTransforms[secondFrame].scale.X + FrameTransforms[secondFrame].translate.X;
|
||||
two.Y = f32(second->Pos.Y) * FrameTransforms[secondFrame].scale.Y + FrameTransforms[secondFrame].translate.Y;
|
||||
two.Z = f32(second->Pos.Z) * FrameTransforms[secondFrame].scale.Z + FrameTransforms[secondFrame].translate.Z;
|
||||
target->Pos = (two - one) * div + one;
|
||||
|
||||
target->Normal = (NormalTable[second->NormalIdx] - NormalTable[first->NormalIdx]) * div
|
||||
+ NormalTable[first->NormalIdx];
|
||||
const core::vector3df one = core::vector3df(f32(first->Pos.X) * FrameTransforms[firstFrame].scale.X + FrameTransforms[firstFrame].translate.X,
|
||||
f32(first->Pos.Y) * FrameTransforms[firstFrame].scale.Y + FrameTransforms[firstFrame].translate.Y,
|
||||
f32(first->Pos.Z) * FrameTransforms[firstFrame].scale.Z + FrameTransforms[firstFrame].translate.Z);
|
||||
const core::vector3df two = core::vector3df(f32(second->Pos.X) * FrameTransforms[secondFrame].scale.X + FrameTransforms[secondFrame].translate.X,
|
||||
f32(second->Pos.Y) * FrameTransforms[secondFrame].scale.Y + FrameTransforms[secondFrame].translate.Y,
|
||||
f32(second->Pos.Z) * FrameTransforms[secondFrame].scale.Z + FrameTransforms[secondFrame].translate.Z);
|
||||
target->Pos = two.getInterpolated(one, div);
|
||||
const core::vector3df n1(
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][0],
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][2],
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][1]);
|
||||
const core::vector3df n2(
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][0],
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][2],
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][1]);
|
||||
target->Normal = n2.getInterpolated(n1, div);
|
||||
++target;
|
||||
++first;
|
||||
++second;
|
||||
|
@ -381,7 +385,7 @@ const core::aabbox3d<f32>& CAnimatedMeshMD2::getBoundingBox() const
|
|||
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
void CAnimatedMeshMD2::setBoundingBox( const core::aabbox3df& box)
|
||||
void CAnimatedMeshMD2::setBoundingBox(const core::aabbox3df& box)
|
||||
{
|
||||
InterpolationBuffer->BoundingBox = box;
|
||||
}
|
||||
|
@ -396,7 +400,7 @@ E_ANIMATED_MESH_TYPE CAnimatedMeshMD2::getMeshType() const
|
|||
|
||||
//! Returns frame loop data for a special MD2 animation type.
|
||||
void CAnimatedMeshMD2::getFrameLoop(EMD2_ANIMATION_TYPE l,
|
||||
s32& outBegin, s32& outEnd, s32& outFPS) const
|
||||
s32& outBegin, s32& outEnd, s32& outFPS) const
|
||||
{
|
||||
if (l < 0 || l >= EMAT_COUNT)
|
||||
return;
|
||||
|
@ -405,7 +409,7 @@ void CAnimatedMeshMD2::getFrameLoop(EMD2_ANIMATION_TYPE l,
|
|||
outEnd = MD2AnimationTypeList[l].end << MD2_FRAME_SHIFT;
|
||||
|
||||
// correct to anim between last->first frame
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : ( 1 << MD2_FRAME_SHIFT ) - 1;
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
|
||||
outFPS = MD2AnimationTypeList[l].fps << MD2_FRAME_SHIFT;
|
||||
}
|
||||
|
||||
|
@ -420,7 +424,7 @@ bool CAnimatedMeshMD2::getFrameLoop(const c8* name,
|
|||
{
|
||||
outBegin = AnimationData[i].begin << MD2_FRAME_SHIFT;
|
||||
outEnd = AnimationData[i].end << MD2_FRAME_SHIFT;
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : ( 1 << MD2_FRAME_SHIFT ) - 1;
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
|
||||
outFPS = AnimationData[i].fps << MD2_FRAME_SHIFT;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -196,7 +196,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
|||
{
|
||||
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
|
||||
return 0;
|
||||
#endif
|
||||
#else
|
||||
|
||||
// As multiple scene nodes may be sharing the same skinned mesh, we have to
|
||||
// re-animate it every frame to ensure that this node gets the mesh that it needs.
|
||||
|
@ -230,6 +230,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
|||
}
|
||||
|
||||
return skinnedMesh;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -579,7 +580,7 @@ IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(const c8* jointName)
|
|||
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
|
||||
os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING);
|
||||
return 0;
|
||||
#endif
|
||||
#else
|
||||
|
||||
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
|
||||
{
|
||||
|
@ -606,6 +607,7 @@ IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(const c8* jointName)
|
|||
}
|
||||
|
||||
return JointChildSceneNodes[number];
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -617,7 +619,7 @@ IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(u32 jointID)
|
|||
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
|
||||
os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING);
|
||||
return 0;
|
||||
#endif
|
||||
#else
|
||||
|
||||
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
|
||||
{
|
||||
|
@ -634,6 +636,7 @@ IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(u32 jointID)
|
|||
}
|
||||
|
||||
return JointChildSceneNodes[jointID];
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Gets joint count.
|
||||
|
@ -641,7 +644,7 @@ u32 CAnimatedMeshSceneNode::getJointCount() const
|
|||
{
|
||||
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
|
||||
return 0;
|
||||
#endif
|
||||
#else
|
||||
|
||||
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
|
||||
return 0;
|
||||
|
@ -649,6 +652,7 @@ u32 CAnimatedMeshSceneNode::getJointCount() const
|
|||
ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh;
|
||||
|
||||
return skinnedMesh->getJointCount();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -949,7 +953,7 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
|
|||
{
|
||||
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
|
||||
return;
|
||||
#endif
|
||||
#else
|
||||
if (Mesh && Mesh->getMeshType() == EAMT_SKINNED )
|
||||
{
|
||||
checkJoints();
|
||||
|
@ -1021,6 +1025,7 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1029,7 +1034,7 @@ void CAnimatedMeshSceneNode::checkJoints()
|
|||
{
|
||||
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
|
||||
return;
|
||||
#endif
|
||||
#else
|
||||
|
||||
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
|
||||
return;
|
||||
|
@ -1047,6 +1052,7 @@ void CAnimatedMeshSceneNode::checkJoints()
|
|||
JointsUsed=true;
|
||||
JointMode=EJUOR_READ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -181,6 +181,8 @@ void CBillboardSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttrib
|
|||
Size.Height = in->getAttributeAsFloat("Height");
|
||||
vertices[1].Color = in->getAttributeAsColor ( "Shade_Top" );
|
||||
vertices[0].Color = in->getAttributeAsColor ( "Shade_Down" );
|
||||
vertices[2].Color = vertices[1].Color;
|
||||
vertices[3].Color = vertices[0].Color;
|
||||
|
||||
setSize(Size);
|
||||
}
|
||||
|
|
|
@ -1272,7 +1272,7 @@ void CColladaFileLoader::readTexture(io::IXMLReaderUTF8* reader)
|
|||
if (input)
|
||||
{
|
||||
const core::stringc imageName = input->Source;
|
||||
texture.Texture = getTextureFromImage(imageName);
|
||||
texture.Texture = getTextureFromImage(imageName, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1370,6 +1370,7 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect *
|
|||
{
|
||||
Effects.push_back(SColladaEffect());
|
||||
effect = &Effects.getLast();
|
||||
effect->Parameters = new io::CAttributes();
|
||||
effect->Id = readId(reader);
|
||||
effect->Transparency = 1.f;
|
||||
effect->Mat.Lighting=true;
|
||||
|
@ -1388,7 +1389,7 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect *
|
|||
readEffect(reader,effect);
|
||||
else
|
||||
if (newParamName == reader->getNodeName())
|
||||
readParameter(reader);
|
||||
readParameter(reader, effect->Parameters);
|
||||
else
|
||||
// these are the actual materials inside technique
|
||||
if (constantNode == reader->getNodeName() ||
|
||||
|
@ -1538,10 +1539,10 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect *
|
|||
effect->Mat.MaterialType = irr::video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||
effect->Mat.ZWriteEnable = false;
|
||||
}
|
||||
effect->Mat.setFlag(video::EMF_TEXTURE_WRAP, !Parameters.getAttributeAsBool("wrap_s"));
|
||||
effect->Mat.setFlag(video::EMF_BILINEAR_FILTER, Parameters.getAttributeAsBool("bilinear"));
|
||||
effect->Mat.setFlag(video::EMF_TRILINEAR_FILTER, Parameters.getAttributeAsBool("trilinear"));
|
||||
effect->Mat.setFlag(video::EMF_ANISOTROPIC_FILTER, Parameters.getAttributeAsBool("anisotropic"));
|
||||
effect->Mat.setFlag(video::EMF_TEXTURE_WRAP, !effect->Parameters->getAttributeAsBool("wrap_s"));
|
||||
effect->Mat.setFlag(video::EMF_BILINEAR_FILTER, effect->Parameters->getAttributeAsBool("bilinear"));
|
||||
effect->Mat.setFlag(video::EMF_TRILINEAR_FILTER, effect->Parameters->getAttributeAsBool("trilinear"));
|
||||
effect->Mat.setFlag(video::EMF_ANISOTROPIC_FILTER, effect->Parameters->getAttributeAsBool("anisotropic"));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1569,7 +1570,7 @@ const SColladaMaterial* CColladaFileLoader::findMaterial(const core::stringc& ma
|
|||
// found the effect, instantiate by copying into the material
|
||||
Materials[mat].Mat = Effects[effect].Mat;
|
||||
if (Effects[effect].Textures.size())
|
||||
Materials[mat].Mat.setTexture(0, getTextureFromImage(Effects[effect].Textures[0]));
|
||||
Materials[mat].Mat.setTexture(0, getTextureFromImage(Effects[effect].Textures[0], &(Effects[effect])));
|
||||
Materials[mat].Transparency = Effects[effect].Transparency;
|
||||
// and indicate the material is instantiated by removing the effect ref
|
||||
Materials[mat].InstanceEffectId = "";
|
||||
|
@ -2494,7 +2495,7 @@ void CColladaFileLoader::readColladaInputs(io::IXMLReaderUTF8* reader, const cor
|
|||
} // end while reader->read();
|
||||
}
|
||||
|
||||
//! parses all collada parameters inside an element and stores them in Parameters
|
||||
//! parses all collada parameters inside an element and stores them in ColladaParameters
|
||||
void CColladaFileLoader::readColladaParameters(io::IXMLReaderUTF8* reader,
|
||||
const core::stringc& parentName)
|
||||
{
|
||||
|
@ -2719,6 +2720,8 @@ void CColladaFileLoader::clearData()
|
|||
Inputs.clear();
|
||||
|
||||
// clear all effects
|
||||
for ( u32 i=0; i<Effects.size(); ++i )
|
||||
Effects[i].Parameters->drop();
|
||||
Effects.clear();
|
||||
|
||||
// clear all the materials to bind
|
||||
|
@ -2751,7 +2754,7 @@ core::stringc CColladaFileLoader::readId(io::IXMLReaderUTF8* reader)
|
|||
|
||||
|
||||
//! create an Irrlicht texture from the reference
|
||||
video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri)
|
||||
video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri, SColladaEffect * effect)
|
||||
{
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("COLLADA searching texture", uri);
|
||||
|
@ -2792,9 +2795,9 @@ video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (Parameters.getAttributeType(uri.c_str())==io::EAT_STRING)
|
||||
if (effect && effect->Parameters->getAttributeType(uri.c_str())==io::EAT_STRING)
|
||||
{
|
||||
uri = Parameters.getAttributeAsString(uri.c_str());
|
||||
uri = effect->Parameters->getAttributeAsString(uri.c_str());
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("COLLADA now searching texture", uri.c_str());
|
||||
#endif
|
||||
|
@ -2807,12 +2810,15 @@ video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri)
|
|||
|
||||
|
||||
//! read a parameter and value
|
||||
void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
|
||||
void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters)
|
||||
{
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("COLLADA reading parameter");
|
||||
#endif
|
||||
|
||||
if ( !parameters )
|
||||
return;
|
||||
|
||||
const core::stringc name = reader->getAttributeValue("sid");
|
||||
if (!reader->isEmptyElement())
|
||||
{
|
||||
|
@ -2823,7 +2829,7 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
|
|||
if (floatNodeName == reader->getNodeName())
|
||||
{
|
||||
const f32 f = readFloatNode(reader);
|
||||
Parameters.addFloat(name.c_str(), f);
|
||||
parameters->addFloat(name.c_str(), f);
|
||||
}
|
||||
else
|
||||
if (float2NodeName == reader->getNodeName())
|
||||
|
@ -2837,14 +2843,14 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
|
|||
{
|
||||
f32 f[3];
|
||||
readFloatsInsideElement(reader, f, 3);
|
||||
Parameters.addVector3d(name.c_str(), core::vector3df(f[0],f[1],f[2]));
|
||||
parameters->addVector3d(name.c_str(), core::vector3df(f[0],f[1],f[2]));
|
||||
}
|
||||
else
|
||||
if ((initFromName == reader->getNodeName()) ||
|
||||
(sourceSectionName == reader->getNodeName()))
|
||||
{
|
||||
reader->read();
|
||||
Parameters.addString(name.c_str(), reader->getNodeData());
|
||||
parameters->addString(name.c_str(), reader->getNodeData());
|
||||
}
|
||||
else
|
||||
if (wrapsName == reader->getNodeName())
|
||||
|
@ -2852,7 +2858,7 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
|
|||
reader->read();
|
||||
const core::stringc val = reader->getNodeData();
|
||||
if (val == "WRAP")
|
||||
Parameters.addBool("wrap_s", true);
|
||||
parameters->addBool("wrap_s", true);
|
||||
}
|
||||
else
|
||||
if (wraptName == reader->getNodeName())
|
||||
|
@ -2860,7 +2866,7 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
|
|||
reader->read();
|
||||
const core::stringc val = reader->getNodeData();
|
||||
if (val == "WRAP")
|
||||
Parameters.addBool("wrap_t", true);
|
||||
parameters->addBool("wrap_t", true);
|
||||
}
|
||||
else
|
||||
if (minfilterName == reader->getNodeName())
|
||||
|
@ -2868,10 +2874,10 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
|
|||
reader->read();
|
||||
const core::stringc val = reader->getNodeData();
|
||||
if (val == "LINEAR_MIPMAP_LINEAR")
|
||||
Parameters.addBool("trilinear", true);
|
||||
parameters->addBool("trilinear", true);
|
||||
else
|
||||
if (val == "LINEAR_MIPMAP_NEAREST")
|
||||
Parameters.addBool("bilinear", true);
|
||||
parameters->addBool("bilinear", true);
|
||||
}
|
||||
else
|
||||
if (magfilterName == reader->getNodeName())
|
||||
|
@ -2880,14 +2886,14 @@ void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
|
|||
const core::stringc val = reader->getNodeData();
|
||||
if (val != "LINEAR")
|
||||
{
|
||||
Parameters.addBool("bilinear", false);
|
||||
Parameters.addBool("trilinear", false);
|
||||
parameters->addBool("bilinear", false);
|
||||
parameters->addBool("trilinear", false);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (mipfilterName == reader->getNodeName())
|
||||
{
|
||||
Parameters.addBool("anisotropic", true);
|
||||
parameters->addBool("anisotropic", true);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -135,6 +135,8 @@ struct SColladaEffect
|
|||
f32 Transparency;
|
||||
core::array<core::stringc> Textures;
|
||||
video::SMaterial Mat;
|
||||
// TODO: Parameters looks somewhat lazy workaround, I think we should really read all parameters correct.
|
||||
io::IAttributes * Parameters;
|
||||
|
||||
inline bool operator< (const SColladaEffect & other) const
|
||||
{
|
||||
|
@ -298,7 +300,7 @@ private:
|
|||
//! clears all loaded data
|
||||
void clearData();
|
||||
|
||||
//! parses all collada parameters inside an element and stores them in Parameters
|
||||
//! parses all collada parameters inside an element and stores them in ColladaParameters
|
||||
void readColladaParameters(io::IXMLReaderUTF8* reader, const core::stringc& parentName);
|
||||
|
||||
//! returns a collada parameter or none if not found
|
||||
|
@ -332,10 +334,10 @@ private:
|
|||
void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id);
|
||||
|
||||
//! create an Irrlicht texture from the SColladaImage
|
||||
video::ITexture* getTextureFromImage(core::stringc uri);
|
||||
video::ITexture* getTextureFromImage(core::stringc uri, SColladaEffect * effect);
|
||||
|
||||
//! read a parameter and value
|
||||
void readParameter(io::IXMLReaderUTF8* reader);
|
||||
void readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters);
|
||||
|
||||
scene::ISceneManager* SceneManager;
|
||||
io::IFileSystem* FileSystem;
|
||||
|
@ -360,7 +362,6 @@ private:
|
|||
core::map<core::stringc,u32> MaterialsToBind;
|
||||
//! Array of buffers for each material binding
|
||||
core::array< core::array<irr::scene::IMeshBuffer*> > MeshesToBind;
|
||||
io::CAttributes Parameters;
|
||||
|
||||
bool CreateInstances;
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,8 +5,9 @@
|
|||
#ifndef __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
|
||||
#define __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
|
||||
|
||||
#include "IMeshWriter.h"
|
||||
#include "IColladaMeshWriter.h"
|
||||
#include "S3DVertex.h"
|
||||
#include "irrMap.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
namespace irr
|
||||
|
@ -19,19 +20,59 @@ namespace io
|
|||
namespace scene
|
||||
{
|
||||
|
||||
//! Callback interface for properties which can be used to influence collada writing
|
||||
// (Implementer note: keep namespace labels here to make it easier for users copying this one)
|
||||
class CColladaMeshWriterProperties : public virtual IColladaMeshWriterProperties
|
||||
{
|
||||
public:
|
||||
//! Which lighting model should be used in the technique (FX) section when exporting effects (materials)
|
||||
virtual irr::scene::E_COLLADA_TECHNIQUE_FX getTechniqueFx(const irr::video::SMaterial& material) const;
|
||||
|
||||
//! Which texture index should be used when writing the texture of the given sampler color.
|
||||
virtual irr::s32 getTextureIdx(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
|
||||
|
||||
//! Return which color from Irrlicht should be used for the color requested by collada
|
||||
virtual irr::scene::E_COLLADA_IRR_COLOR getColorMapping(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
|
||||
|
||||
//! Return custom colors for certain color types requested by collada.
|
||||
virtual irr::video::SColor getCustomColor(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
|
||||
|
||||
//! Return the settings for transparence
|
||||
virtual irr::scene::E_COLLADA_TRANSPARENT_FX getTransparentFx(const irr::video::SMaterial& material) const;
|
||||
|
||||
//! Transparency value for that material.
|
||||
virtual irr::f32 getTransparency(const irr::video::SMaterial& material) const;
|
||||
|
||||
//! Reflectivity value for that material
|
||||
virtual irr::f32 getReflectivity(const irr::video::SMaterial& material) const;
|
||||
|
||||
//! Return index of refraction for that material
|
||||
virtual irr::f32 getIndexOfRefraction(const irr::video::SMaterial& material) const;
|
||||
|
||||
//! Should node be used in scene export? By default all visible nodes are exported.
|
||||
virtual bool isExportable(const irr::scene::ISceneNode * node) const;
|
||||
|
||||
//! Return the mesh for the given nod. If it has no mesh or shouldn't export it's mesh return 0.
|
||||
virtual irr::scene::IMesh* getMesh(irr::scene::ISceneNode * node);
|
||||
};
|
||||
|
||||
|
||||
//! class to write meshes, implementing a COLLADA (.dae, .xml) writer
|
||||
/** This writer implementation has been originally developed for irrEdit and then
|
||||
merged out to the Irrlicht Engine */
|
||||
class CColladaMeshWriter : public IMeshWriter
|
||||
class CColladaMeshWriter : public IColladaMeshWriter
|
||||
{
|
||||
public:
|
||||
|
||||
CColladaMeshWriter(video::IVideoDriver* driver, io::IFileSystem* fs);
|
||||
CColladaMeshWriter(ISceneManager * smgr, video::IVideoDriver* driver, io::IFileSystem* fs);
|
||||
virtual ~CColladaMeshWriter();
|
||||
|
||||
//! Returns the type of the mesh writer
|
||||
virtual EMESH_WRITER_TYPE getType() const;
|
||||
|
||||
//! writes a scene starting with the given node
|
||||
virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root);
|
||||
|
||||
//! writes a mesh
|
||||
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE);
|
||||
|
||||
|
@ -40,9 +81,48 @@ protected:
|
|||
|
||||
bool hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const;
|
||||
inline irr::core::stringw toString(const irr::core::vector3df& vec) const;
|
||||
inline irr::core::stringw uvToString(const irr::core::vector2df& vec) const;
|
||||
inline irr::core::stringw toString(const irr::core::vector2df& vec) const;
|
||||
inline irr::core::stringw toString(const irr::video::SColorf& colorf) const;
|
||||
inline void writeColorAttribute(wchar_t * parentTag, io::IAttributes* attributes, s32 attridx);
|
||||
inline irr::core::stringw toString(const irr::video::SColorf& colorf, bool writeAlpha=true) const;
|
||||
inline irr::core::stringw toString(const irr::video::ECOLOR_FORMAT format) const;
|
||||
inline irr::core::stringw toString(const irr::video::E_TEXTURE_CLAMP clamp) const;
|
||||
inline irr::core::stringw toString(const irr::scene::E_COLLADA_TRANSPARENT_FX opaque) const;
|
||||
inline irr::core::stringw toRef(const irr::core::stringw& source) const;
|
||||
irr::core::stringw uniqueNameForMesh(const scene::IMesh* mesh) const;
|
||||
irr::core::stringw uniqueNameForLight(const scene::ISceneNode* lightNode) const;
|
||||
irr::core::stringw uniqueNameForNode(const scene::ISceneNode* node) const;
|
||||
irr::core::stringw minTexfilterToString(bool bilinear, bool trilinear) const;
|
||||
irr::core::stringw magTexfilterToString(bool bilinear, bool trilinear) const;
|
||||
irr::core::stringw pathToNCName(const irr::io::path& path) const;
|
||||
irr::core::stringw pathToURI(const irr::io::path& path) const;
|
||||
inline bool isXmlNameStartChar(wchar_t c) const;
|
||||
inline bool isXmlNameChar(wchar_t c) const;
|
||||
s32 getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs);
|
||||
video::SColor getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType);
|
||||
void writeAsset();
|
||||
void makeMeshNames(irr::scene::ISceneNode * node);
|
||||
void writeNodeMaterials(irr::scene::ISceneNode * node);
|
||||
void writeNodeEffects(irr::scene::ISceneNode * node);
|
||||
void writeNodeLights(irr::scene::ISceneNode * node);
|
||||
void writeNodeGeometries(irr::scene::ISceneNode * node);
|
||||
void writeSceneNode(irr::scene::ISceneNode * node);
|
||||
void writeMeshMaterials(const irr::core::stringw& meshname, scene::IMesh* mesh);
|
||||
void writeMeshEffects(const irr::core::stringw& meshname, scene::IMesh* mesh);
|
||||
void writeMaterialEffect(const irr::core::stringw& meshname, const irr::core::stringw& materialname, const video::SMaterial & material);
|
||||
void writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh);
|
||||
void writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh);
|
||||
void writeLightInstance(const irr::core::stringw& lightName);
|
||||
void writeLibraryImages();
|
||||
void writeColorFx(const irr::core::stringw& meshname, const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name=0, const wchar_t* attr1Value=0);
|
||||
void writeAmbientLightElement(const video::SColorf & col);
|
||||
void writeColorElement(const video::SColor & col, bool writeAlpha=true);
|
||||
void writeColorElement(const video::SColorf & col, bool writeAlpha=true);
|
||||
void writeTextureSampler(const irr::core::stringw& meshname, s32 textureIdx);
|
||||
void writeFxElement(const irr::core::stringw& meshname, const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx);
|
||||
void writeFloatElement(irr::f32 value);
|
||||
void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle);
|
||||
void writeScaleElement(const irr::core::vector3df& scale);
|
||||
void writeTranslateElement(const irr::core::vector3df& translate);
|
||||
|
||||
struct SComponentGlobalStartPos
|
||||
{
|
||||
|
@ -68,6 +148,30 @@ protected:
|
|||
io::IFileSystem* FileSystem;
|
||||
video::IVideoDriver* VideoDriver;
|
||||
io::IXMLWriter* Writer;
|
||||
core::array<video::ITexture*> LibraryImages;
|
||||
io::path Directory;
|
||||
|
||||
struct ColladaMesh
|
||||
{
|
||||
ColladaMesh() : MaterialWritten(false), EffectWritten(false), GeometryWritten(false)
|
||||
{
|
||||
}
|
||||
|
||||
irr::core::stringw Name;
|
||||
bool MaterialWritten;
|
||||
bool EffectWritten;
|
||||
bool GeometryWritten;
|
||||
};
|
||||
typedef core::map<IMesh*, ColladaMesh>::Node MeshNode;
|
||||
core::map<IMesh*, ColladaMesh> Meshes;
|
||||
|
||||
struct ColladaLight
|
||||
{
|
||||
ColladaLight() {}
|
||||
irr::core::stringw Name;
|
||||
};
|
||||
typedef core::map<ISceneNode*, ColladaLight>::Node LightNode;
|
||||
core::map<ISceneNode*, ColladaLight> LightNodes;
|
||||
};
|
||||
|
||||
|
||||
|
@ -76,3 +180,4 @@ protected:
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -1053,7 +1053,7 @@ bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer)
|
|||
}
|
||||
|
||||
DWORD flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY
|
||||
if(hwBuffer->Mapped_Vertex != scene::EHM_STATIC)
|
||||
if (hwBuffer->Mapped_Vertex != scene::EHM_STATIC)
|
||||
flags |= D3DUSAGE_DYNAMIC;
|
||||
|
||||
if (FAILED(pID3DDevice->CreateVertexBuffer(bufSize, flags, FVF, D3DPOOL_DEFAULT, &hwBuffer->vertexBuffer, NULL)))
|
||||
|
@ -1061,7 +1061,7 @@ bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer)
|
|||
hwBuffer->vertexBufferSize = bufSize;
|
||||
|
||||
flags = 0; // SIO2: Reset flags before Lock
|
||||
if(hwBuffer->Mapped_Vertex != scene::EHM_STATIC)
|
||||
if (hwBuffer->Mapped_Vertex != scene::EHM_STATIC)
|
||||
flags = D3DLOCK_DISCARD;
|
||||
|
||||
void* lockedBuffer = 0;
|
||||
|
@ -1187,7 +1187,9 @@ bool CD3D9Driver::updateHardwareBuffer(SHWBufferLink *hwBuffer)
|
|||
//! Create hardware buffer from meshbuffer
|
||||
CD3D9Driver::SHWBufferLink *CD3D9Driver::createHardwareBuffer(const scene::IMeshBuffer* mb)
|
||||
{
|
||||
if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER))
|
||||
// Looks like d3d does not support only partial buffering, so refuse
|
||||
// in any case of NEVER
|
||||
if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER || mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER))
|
||||
return 0;
|
||||
|
||||
SHWBufferLink_d3d9 *hwBuffer=new SHWBufferLink_d3d9(mb);
|
||||
|
@ -1252,12 +1254,20 @@ void CD3D9Driver::drawHardwareBuffer(SHWBufferLink *_HWBuffer)
|
|||
const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;
|
||||
const E_VERTEX_TYPE vType = mb->getVertexType();
|
||||
const u32 stride = getVertexPitchFromType(vType);
|
||||
const void* vPtr = mb->getVertices();
|
||||
const void* iPtr = mb->getIndices();
|
||||
if (HWBuffer->vertexBuffer)
|
||||
{
|
||||
pID3DDevice->SetStreamSource(0, HWBuffer->vertexBuffer, 0, stride);
|
||||
vPtr=0;
|
||||
}
|
||||
if (HWBuffer->indexBuffer)
|
||||
{
|
||||
pID3DDevice->SetIndices(HWBuffer->indexBuffer);
|
||||
iPtr=0;
|
||||
}
|
||||
|
||||
drawVertexPrimitiveList(0, mb->getVertexCount(), 0, mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType());
|
||||
drawVertexPrimitiveList(vPtr, mb->getVertexCount(), iPtr, mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType());
|
||||
|
||||
if (HWBuffer->vertexBuffer)
|
||||
pID3DDevice->SetStreamSource(0, 0, 0, 0);
|
||||
|
@ -2563,9 +2573,15 @@ void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan
|
|||
|
||||
pID3DDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
}
|
||||
pID3DDevice->SetTransform(D3DTS_WORLD, &UnitMatrixD3D9);
|
||||
|
||||
core::matrix4 m;
|
||||
// this fixes some problems with pixel exact rendering, but also breaks nice texturing
|
||||
// moreover, it would have to be tested in each call, as the texture flag can change each time
|
||||
// if (!texture)
|
||||
// m.setTranslation(core::vector3df(0.5f,0.5f,0));
|
||||
pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)m.pointer()));
|
||||
|
||||
// adjust the view such that pixel center aligns with texels
|
||||
// Otherwise, subpixel artifacts will occur
|
||||
m.setTranslation(core::vector3df(-0.5f,-0.5f,0));
|
||||
pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)m.pointer()));
|
||||
|
||||
|
@ -2574,6 +2590,7 @@ void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan
|
|||
m.setTranslation(core::vector3df(-1,1,0));
|
||||
pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)m.pointer()));
|
||||
|
||||
// 2d elements are clipped in software
|
||||
pID3DDevice->SetRenderState(D3DRS_CLIPPING, FALSE);
|
||||
|
||||
Transformation3DChanged = false;
|
||||
|
|
|
@ -44,6 +44,25 @@ core::matrix4 CDummyTransformationSceneNode::getRelativeTransformation() const
|
|||
return RelativeTransformationMatrix;
|
||||
}
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CDummyTransformationSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CDummyTransformationSceneNode* nb = new CDummyTransformationSceneNode(newParent,
|
||||
newManager, ID);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->RelativeTransformationMatrix = RelativeTransformationMatrix;
|
||||
nb->Box = Box;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
|
|
@ -36,6 +36,10 @@ namespace scene
|
|||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_DUMMY_TRANSFORMATION; }
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
core::matrix4 RelativeTransformationMatrix;
|
||||
|
|
|
@ -700,36 +700,66 @@ io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root
|
|||
//! Get the relative filename, relative to the given directory
|
||||
path CFileSystem::getRelativeFilename(const path& filename, const path& directory) const
|
||||
{
|
||||
io::path path1, file, ext;
|
||||
core::splitFilename(getAbsolutePath(filename), &path1, &file, &ext);
|
||||
io::path path2(getAbsolutePath(directory));
|
||||
core::list<io::path> list1, list2;
|
||||
path1.split(list1, _IRR_TEXT("/\\"), 2);
|
||||
path2.split(list2, _IRR_TEXT("/\\"), 2);
|
||||
u32 i=0;
|
||||
core::list<io::path>::ConstIterator it1,it2;
|
||||
it1=list1.begin();
|
||||
it2=list2.begin();
|
||||
for (; i<list1.size() && i<list2.size() && (*it1==*it2); ++i)
|
||||
{
|
||||
++it1;
|
||||
++it2;
|
||||
}
|
||||
path1=_IRR_TEXT("");
|
||||
for (; i<list2.size(); ++i)
|
||||
path1 += _IRR_TEXT("../");
|
||||
while (it1 != list1.end())
|
||||
{
|
||||
path1 += *it1++;
|
||||
path1 += _IRR_TEXT('/');
|
||||
}
|
||||
path1 += file;
|
||||
if (ext.size())
|
||||
{
|
||||
path1 += _IRR_TEXT('.');
|
||||
path1 += ext;
|
||||
}
|
||||
return path1;
|
||||
if ( filename.empty() || directory.empty() )
|
||||
return filename;
|
||||
|
||||
io::path path1, file, ext;
|
||||
core::splitFilename(getAbsolutePath(filename), &path1, &file, &ext);
|
||||
io::path path2(getAbsolutePath(directory));
|
||||
core::list<io::path> list1, list2;
|
||||
path1.split(list1, _IRR_TEXT("/\\"), 2);
|
||||
path2.split(list2, _IRR_TEXT("/\\"), 2);
|
||||
u32 i=0;
|
||||
core::list<io::path>::ConstIterator it1,it2;
|
||||
it1=list1.begin();
|
||||
it2=list2.begin();
|
||||
|
||||
#if defined (_IRR_WINDOWS_API_)
|
||||
fschar_t partition1 = 0, partition2 = 0;
|
||||
io::path prefix1, prefix2;
|
||||
if ( it1 != list1.end() )
|
||||
prefix1 = *it1;
|
||||
if ( it2 != list2.end() )
|
||||
prefix2 = *it2;
|
||||
if ( prefix1.size() > 1 && prefix1[1] == _IRR_TEXT(':') )
|
||||
partition1 = core::locale_lower(prefix1[0]);
|
||||
if ( prefix2.size() > 1 && prefix2[1] == _IRR_TEXT(':') )
|
||||
partition2 = core::locale_lower(prefix2[0]);
|
||||
|
||||
// must have the same prefix or we can't resolve it to a relative filename
|
||||
if ( partition1 != partition2 )
|
||||
{
|
||||
return filename;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
for (; i<list1.size() && i<list2.size()
|
||||
#if defined (_IRR_WINDOWS_API_)
|
||||
&& (io::path(*it1).make_lower()==io::path(*it2).make_lower())
|
||||
#else
|
||||
&& (*it1==*it2)
|
||||
#endif
|
||||
; ++i)
|
||||
{
|
||||
++it1;
|
||||
++it2;
|
||||
}
|
||||
path1=_IRR_TEXT("");
|
||||
for (; i<list2.size(); ++i)
|
||||
path1 += _IRR_TEXT("../");
|
||||
while (it1 != list1.end())
|
||||
{
|
||||
path1 += *it1++;
|
||||
path1 += _IRR_TEXT('/');
|
||||
}
|
||||
path1 += file;
|
||||
if (ext.size())
|
||||
{
|
||||
path1 += _IRR_TEXT('.');
|
||||
path1 += ext;
|
||||
}
|
||||
return path1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -287,9 +287,7 @@ void CGUIButton::draw()
|
|||
|
||||
if (Text.size())
|
||||
{
|
||||
IGUIFont* font = OverrideFont;
|
||||
if (!OverrideFont)
|
||||
font = skin->getFont(EGDF_BUTTON);
|
||||
IGUIFont* font = getActiveFont();
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
if (Pressed)
|
||||
|
@ -320,6 +318,22 @@ void CGUIButton::setOverrideFont(IGUIFont* font)
|
|||
OverrideFont->grab();
|
||||
}
|
||||
|
||||
//! Gets the override font (if any)
|
||||
IGUIFont * CGUIButton::getOverrideFont() const
|
||||
{
|
||||
return OverrideFont;
|
||||
}
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
IGUIFont* CGUIButton::getActiveFont() const
|
||||
{
|
||||
if ( OverrideFont )
|
||||
return OverrideFont;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
return skin->getFont();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in normal state.
|
||||
void CGUIButton::setImage(video::ITexture* image)
|
||||
|
|
|
@ -37,6 +37,12 @@ namespace gui
|
|||
//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
|
||||
virtual void setOverrideFont(IGUIFont* font=0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in normal state.
|
||||
virtual void setImage(video::ITexture* image=0);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
|
|||
s32 id, core::rect<s32> rectangle)
|
||||
: IGUIComboBox(environment, parent, id, rectangle),
|
||||
ListButton(0), SelectedText(0), ListBox(0), LastFocus(0),
|
||||
Selected(-1), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), HasFocus(false)
|
||||
Selected(-1), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), MaxSelectionRows(5), HasFocus(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIComboBox");
|
||||
|
@ -81,6 +81,26 @@ void CGUIComboBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT ve
|
|||
}
|
||||
|
||||
|
||||
//! Set the maximal number of rows for the selection listbox
|
||||
void CGUIComboBox::setMaxSelectionRows(u32 max)
|
||||
{
|
||||
MaxSelectionRows = max;
|
||||
|
||||
// force recalculation of open listbox
|
||||
if (ListBox)
|
||||
{
|
||||
openCloseMenu();
|
||||
openCloseMenu();
|
||||
}
|
||||
}
|
||||
|
||||
//! Get the maximimal number of rows for the selection listbox
|
||||
u32 CGUIComboBox::getMaxSelectionRows() const
|
||||
{
|
||||
return MaxSelectionRows;
|
||||
}
|
||||
|
||||
|
||||
//! Returns amount of items in box
|
||||
u32 CGUIComboBox::getItemCount() const
|
||||
{
|
||||
|
@ -408,10 +428,10 @@ void CGUIComboBox::openCloseMenu()
|
|||
Parent->bringToFront(this);
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
s32 h = Items.size();
|
||||
u32 h = Items.size();
|
||||
|
||||
if (h > 5)
|
||||
h = 5;
|
||||
if (h > getMaxSelectionRows())
|
||||
h = getMaxSelectionRows();
|
||||
if (h == 0)
|
||||
h = 1;
|
||||
|
||||
|
@ -450,6 +470,7 @@ void CGUIComboBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadW
|
|||
|
||||
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
|
||||
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
|
||||
out->addInt("MaxSelectionRows", (s32)MaxSelectionRows );
|
||||
|
||||
out->addInt ("Selected", Selected );
|
||||
out->addInt ("ItemCount", Items.size());
|
||||
|
@ -470,6 +491,7 @@ void CGUIComboBox::deserializeAttributes(io::IAttributes* in, io::SAttributeRead
|
|||
|
||||
setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
|
||||
(EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
|
||||
setMaxSelectionRows( (u32)(in->getAttributeAsInt("MaxSelectionRows")) );
|
||||
|
||||
// clear the list
|
||||
clear();
|
||||
|
|
|
@ -62,6 +62,12 @@ namespace gui
|
|||
//! sets the text alignment of the text part
|
||||
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical);
|
||||
|
||||
//! Set the maximal number of rows for the selection listbox
|
||||
virtual void setMaxSelectionRows(u32 max);
|
||||
|
||||
//! Get the maximimal number of rows for the selection listbox
|
||||
virtual u32 getMaxSelectionRows() const;
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
|
@ -97,6 +103,7 @@ namespace gui
|
|||
|
||||
s32 Selected;
|
||||
EGUI_ALIGNMENT HAlign, VAlign;
|
||||
u32 MaxSelectionRows;
|
||||
bool HasFocus;
|
||||
};
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border,
|
|||
IGUIEnvironment* environment, IGUIElement* parent, s32 id,
|
||||
const core::rect<s32>& rectangle)
|
||||
: IGUIEditBox(environment, parent, id, rectangle), MouseMarking(false),
|
||||
Border(border), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0),
|
||||
Border(border), Background(true), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0),
|
||||
OverrideColor(video::SColor(101,255,255,255)), OverrideFont(0), LastBreakFont(0),
|
||||
Operator(0), BlinkStartTime(0), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0),
|
||||
WordWrap(false), MultiLine(false), AutoScroll(true), PasswordBox(false),
|
||||
|
@ -55,17 +55,7 @@ CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border,
|
|||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
|
||||
IGUISkin *skin = 0;
|
||||
if (Environment)
|
||||
skin = Environment->getSkin();
|
||||
if (Border && skin)
|
||||
{
|
||||
FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
|
||||
FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
|
||||
FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
|
||||
FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
|
||||
}
|
||||
|
||||
calculateFrameRect();
|
||||
breakText();
|
||||
|
||||
calculateScrollPos();
|
||||
|
@ -100,6 +90,22 @@ void CGUIEditBox::setOverrideFont(IGUIFont* font)
|
|||
breakText();
|
||||
}
|
||||
|
||||
//! Gets the override font (if any)
|
||||
IGUIFont * CGUIEditBox::getOverrideFont() const
|
||||
{
|
||||
return OverrideFont;
|
||||
}
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
IGUIFont* CGUIEditBox::getActiveFont() const
|
||||
{
|
||||
if ( OverrideFont )
|
||||
return OverrideFont;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
return skin->getFont();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets another color for the text.
|
||||
void CGUIEditBox::setOverrideColor(video::SColor color)
|
||||
|
@ -121,6 +127,11 @@ void CGUIEditBox::setDrawBorder(bool border)
|
|||
Border = border;
|
||||
}
|
||||
|
||||
//! Sets whether to draw the background
|
||||
void CGUIEditBox::setDrawBackground(bool draw)
|
||||
{
|
||||
Background = draw;
|
||||
}
|
||||
|
||||
//! Sets if the text should use the overide color or the color in the gui skin.
|
||||
void CGUIEditBox::enableOverrideColor(bool enable)
|
||||
|
@ -148,7 +159,9 @@ void CGUIEditBox::updateAbsolutePosition()
|
|||
IGUIElement::updateAbsolutePosition();
|
||||
if ( oldAbsoluteRect != AbsoluteRect )
|
||||
{
|
||||
calculateFrameRect();
|
||||
breakText();
|
||||
calculateScrollPos();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,7 +520,7 @@ bool CGUIEditBox::processKey(const SEvent& event)
|
|||
{
|
||||
s32 cp = CursorPos - BrokenTextPositions[lineNo];
|
||||
if ((s32)BrokenText[lineNo-1].size() < cp)
|
||||
CursorPos = BrokenTextPositions[lineNo-1] + (s32)BrokenText[lineNo-1].size()-1;
|
||||
CursorPos = BrokenTextPositions[lineNo-1] + core::max_((u32)1, BrokenText[lineNo-1].size())-1;
|
||||
else
|
||||
CursorPos = BrokenTextPositions[lineNo-1] + cp;
|
||||
}
|
||||
|
@ -538,7 +551,7 @@ bool CGUIEditBox::processKey(const SEvent& event)
|
|||
{
|
||||
s32 cp = CursorPos - BrokenTextPositions[lineNo];
|
||||
if ((s32)BrokenText[lineNo+1].size() < cp)
|
||||
CursorPos = BrokenTextPositions[lineNo+1] + BrokenText[lineNo+1].size()-1;
|
||||
CursorPos = BrokenTextPositions[lineNo+1] + core::max_((u32)1, BrokenText[lineNo+1].size())-1;
|
||||
else
|
||||
CursorPos = BrokenTextPositions[lineNo+1] + cp;
|
||||
}
|
||||
|
@ -702,31 +715,29 @@ void CGUIEditBox::draw()
|
|||
if (!skin)
|
||||
return;
|
||||
|
||||
FrameRect = AbsoluteRect;
|
||||
EGUI_DEFAULT_COLOR bgCol = EGDC_GRAY_EDITABLE;
|
||||
if ( isEnabled() )
|
||||
bgCol = focus ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE;
|
||||
|
||||
// draw the border
|
||||
if (!Border && Background)
|
||||
{
|
||||
skin->draw2DRectangle(this, skin->getColor(bgCol), AbsoluteRect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
if (Border)
|
||||
{
|
||||
EGUI_DEFAULT_COLOR col = EGDC_GRAY_EDITABLE;
|
||||
if ( isEnabled() )
|
||||
col = focus ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE;
|
||||
skin->draw3DSunkenPane(this, skin->getColor(col),
|
||||
false, true, FrameRect, &AbsoluteClippingRect);
|
||||
// draw the border
|
||||
skin->draw3DSunkenPane(this, skin->getColor(bgCol), false, Background, AbsoluteRect, &AbsoluteClippingRect);
|
||||
|
||||
FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
|
||||
FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
|
||||
FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
|
||||
FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
|
||||
calculateFrameRect();
|
||||
}
|
||||
|
||||
core::rect<s32> localClipRect = FrameRect;
|
||||
localClipRect.clipAgainst(AbsoluteClippingRect);
|
||||
|
||||
// draw the text
|
||||
|
||||
IGUIFont* font = OverrideFont;
|
||||
if (!OverrideFont)
|
||||
font = skin->getFont();
|
||||
IGUIFont* font = getActiveFont();
|
||||
|
||||
s32 cursorLine = 0;
|
||||
s32 charcursorpos = 0;
|
||||
|
@ -1024,10 +1035,7 @@ bool CGUIEditBox::processMouse(const SEvent& event)
|
|||
|
||||
s32 CGUIEditBox::getCursorPos(s32 x, s32 y)
|
||||
{
|
||||
IGUIFont* font = OverrideFont;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (!OverrideFont)
|
||||
font = skin->getFont();
|
||||
IGUIFont* font = getActiveFont();
|
||||
|
||||
const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
|
||||
|
||||
|
@ -1056,7 +1064,10 @@ s32 CGUIEditBox::getCursorPos(s32 x, s32 y)
|
|||
if (x < CurrentTextRect.UpperLeftCorner.X)
|
||||
x = CurrentTextRect.UpperLeftCorner.X;
|
||||
|
||||
s32 idx = txtLine ? font->getCharacterFromPos(txtLine->c_str(), x - CurrentTextRect.UpperLeftCorner.X) : -1;
|
||||
if ( !txtLine )
|
||||
return 0;
|
||||
|
||||
s32 idx = font->getCharacterFromPos(txtLine->c_str(), x - CurrentTextRect.UpperLeftCorner.X);
|
||||
|
||||
// click was on or left of the line
|
||||
if (idx != -1)
|
||||
|
@ -1070,18 +1081,13 @@ s32 CGUIEditBox::getCursorPos(s32 x, s32 y)
|
|||
//! Breaks the single text line.
|
||||
void CGUIEditBox::breakText()
|
||||
{
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
if ((!WordWrap && !MultiLine) || !skin)
|
||||
if ((!WordWrap && !MultiLine))
|
||||
return;
|
||||
|
||||
BrokenText.clear(); // need to reallocate :/
|
||||
BrokenTextPositions.set_used(0);
|
||||
|
||||
IGUIFont* font = OverrideFont;
|
||||
if (!OverrideFont)
|
||||
font = skin->getFont();
|
||||
|
||||
IGUIFont* font = getActiveFont();
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
|
@ -1104,7 +1110,7 @@ void CGUIEditBox::breakText()
|
|||
if (c == L'\r') // Mac or Windows breaks
|
||||
{
|
||||
lineBreak = true;
|
||||
c = ' ';
|
||||
c = 0;
|
||||
if (Text[i+1] == L'\n') // Windows breaks
|
||||
{
|
||||
Text.erase(i+1);
|
||||
|
@ -1114,7 +1120,7 @@ void CGUIEditBox::breakText()
|
|||
else if (c == L'\n') // Unix breaks
|
||||
{
|
||||
lineBreak = true;
|
||||
c = ' ';
|
||||
c = 0;
|
||||
}
|
||||
|
||||
// don't break if we're not a multi-line edit box
|
||||
|
@ -1123,35 +1129,35 @@ void CGUIEditBox::breakText()
|
|||
|
||||
if (c == L' ' || c == 0 || i == (size-1))
|
||||
{
|
||||
if (word.size())
|
||||
// here comes the next whitespace, look if
|
||||
// we can break the last word to the next line
|
||||
// We also break whitespace, otherwise cursor would vanish beside the right border.
|
||||
s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
|
||||
s32 worldlgth = font->getDimension(word.c_str()).Width;
|
||||
|
||||
if (WordWrap && length + worldlgth + whitelgth > elWidth && line.size() > 0)
|
||||
{
|
||||
// here comes the next whitespace, look if
|
||||
// we can break the last word to the next line.
|
||||
s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
|
||||
s32 worldlgth = font->getDimension(word.c_str()).Width;
|
||||
|
||||
if (WordWrap && length + worldlgth + whitelgth > elWidth)
|
||||
{
|
||||
// break to next line
|
||||
length = worldlgth;
|
||||
BrokenText.push_back(line);
|
||||
BrokenTextPositions.push_back(lastLineStart);
|
||||
lastLineStart = i - (s32)word.size();
|
||||
line = word;
|
||||
}
|
||||
else
|
||||
{
|
||||
// add word to line
|
||||
line += whitespace;
|
||||
line += word;
|
||||
length += whitelgth + worldlgth;
|
||||
}
|
||||
|
||||
word = L"";
|
||||
whitespace = L"";
|
||||
// break to next line
|
||||
length = worldlgth;
|
||||
BrokenText.push_back(line);
|
||||
BrokenTextPositions.push_back(lastLineStart);
|
||||
lastLineStart = i - (s32)word.size();
|
||||
line = word;
|
||||
}
|
||||
else
|
||||
{
|
||||
// add word to line
|
||||
line += whitespace;
|
||||
line += word;
|
||||
length += whitelgth + worldlgth;
|
||||
}
|
||||
|
||||
whitespace += c;
|
||||
word = L"";
|
||||
whitespace = L"";
|
||||
|
||||
|
||||
if ( c )
|
||||
whitespace += c;
|
||||
|
||||
// compute line break
|
||||
if (lineBreak)
|
||||
|
@ -1183,17 +1189,15 @@ void CGUIEditBox::breakText()
|
|||
|
||||
void CGUIEditBox::setTextRect(s32 line)
|
||||
{
|
||||
core::dimension2du d;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
if ( line < 0 )
|
||||
return;
|
||||
|
||||
IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
|
||||
|
||||
IGUIFont* font = getActiveFont();
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
core::dimension2du d;
|
||||
|
||||
// get text dimension
|
||||
const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
|
||||
if (WordWrap || MultiLine)
|
||||
|
@ -1321,16 +1325,15 @@ void CGUIEditBox::calculateScrollPos()
|
|||
|
||||
// calculate horizontal scroll position
|
||||
s32 cursLine = getLineFromPos(CursorPos);
|
||||
if ( cursLine < 0 )
|
||||
return;
|
||||
setTextRect(cursLine);
|
||||
|
||||
// don't do horizontal scrolling when wordwrap is enabled.
|
||||
if (!WordWrap)
|
||||
{
|
||||
// get cursor position
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
|
||||
IGUIFont* font = getActiveFont();
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
|
@ -1364,6 +1367,21 @@ void CGUIEditBox::calculateScrollPos()
|
|||
// todo: adjust scrollbar
|
||||
}
|
||||
|
||||
void CGUIEditBox::calculateFrameRect()
|
||||
{
|
||||
FrameRect = AbsoluteRect;
|
||||
IGUISkin *skin = 0;
|
||||
if (Environment)
|
||||
skin = Environment->getSkin();
|
||||
if (Border && skin)
|
||||
{
|
||||
FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
|
||||
FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
|
||||
FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
|
||||
FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
|
||||
}
|
||||
}
|
||||
|
||||
//! set text markers
|
||||
void CGUIEditBox::setTextMarkers(s32 begin, s32 end)
|
||||
{
|
||||
|
@ -1395,6 +1413,8 @@ void CGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWr
|
|||
{
|
||||
// IGUIEditBox::serializeAttributes(out,options);
|
||||
|
||||
out->addBool ("Border", Border);
|
||||
out->addBool ("Background", Background);
|
||||
out->addBool ("OverrideColorEnabled",OverrideColorEnabled );
|
||||
out->addColor ("OverrideColor", OverrideColor);
|
||||
// out->addFont("OverrideFont",OverrideFont);
|
||||
|
@ -1418,6 +1438,8 @@ void CGUIEditBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadW
|
|||
{
|
||||
IGUIEditBox::deserializeAttributes(in,options);
|
||||
|
||||
setDrawBorder( in->getAttributeAsBool("Border") );
|
||||
setDrawBackground( in->getAttributeAsBool("Background") );
|
||||
setOverrideColor(in->getAttributeAsColor("OverrideColor"));
|
||||
enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled"));
|
||||
setMax(in->getAttributeAsInt("MaxChars"));
|
||||
|
|
|
@ -30,6 +30,15 @@ namespace gui
|
|||
//! Sets another skin independent font.
|
||||
virtual void setOverrideFont(IGUIFont* font=0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
/** \return The override font (may be 0) */
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
/** Currently this is the override font when one is set and the
|
||||
font of the active skin otherwise */
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets another color for the text.
|
||||
virtual void setOverrideColor(video::SColor color);
|
||||
|
||||
|
@ -44,6 +53,9 @@ namespace gui
|
|||
/** \return true if the override color is enabled, false otherwise */
|
||||
virtual bool isOverrideColorEnabled(void) const;
|
||||
|
||||
//! Sets whether to draw the background
|
||||
virtual void setDrawBackground(bool draw);
|
||||
|
||||
//! Turns the border on or off
|
||||
virtual void setDrawBorder(bool border);
|
||||
|
||||
|
@ -124,6 +136,8 @@ namespace gui
|
|||
void inputChar(wchar_t c);
|
||||
//! calculates the current scroll position
|
||||
void calculateScrollPos();
|
||||
//! calculated the FrameRect
|
||||
void calculateFrameRect();
|
||||
//! send some gui event to parent
|
||||
void sendGuiEvent(EGUI_EVENT_TYPE type);
|
||||
//! set text markers
|
||||
|
@ -135,6 +149,7 @@ namespace gui
|
|||
|
||||
bool MouseMarking;
|
||||
bool Border;
|
||||
bool Background;
|
||||
bool OverrideColorEnabled;
|
||||
s32 MarkBegin;
|
||||
s32 MarkEnd;
|
||||
|
|
|
@ -405,7 +405,7 @@ bool CGUIListBox::OnEvent(const SEvent& event)
|
|||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
ScrollBar->setPos(ScrollBar->getPos() + (s32)event.MouseInput.Wheel*-ItemHeight/2);
|
||||
ScrollBar->setPos(ScrollBar->getPos() + (event.MouseInput.Wheel < 0 ? -1 : 1)*-ItemHeight/2);
|
||||
return true;
|
||||
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
|
|
|
@ -33,7 +33,7 @@ bool CGUIModalScreen::canTakeFocus(IGUIElement* target) const
|
|||
{
|
||||
return (target && ((const IGUIElement*)target == this // this element can take it
|
||||
|| isMyChild(target) // own children also
|
||||
|| (target->getType() == EGUIET_MODAL_SCREEN )// other modals also fine
|
||||
|| (target->getType() == EGUIET_MODAL_SCREEN ) // other modals also fine (is now on top or explicitely requested)
|
||||
|| (target->getParent() && target->getParent()->getType() == EGUIET_MODAL_SCREEN ))) // children of other modals will do
|
||||
;
|
||||
}
|
||||
|
@ -86,6 +86,13 @@ bool CGUIModalScreen::OnEvent(const SEvent& event)
|
|||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUSED:
|
||||
if ( event.GUIEvent.Caller == this && isMyChild(event.GUIEvent.Element) )
|
||||
{
|
||||
Environment->removeFocus(0); // can't setFocus otherwise at it still has focus here
|
||||
Environment->setFocus(event.GUIEvent.Element);
|
||||
MouseDownTime = os::Timer::getTime();
|
||||
return true;
|
||||
}
|
||||
if ( !canTakeFocus(event.GUIEvent.Caller))
|
||||
{
|
||||
if ( !Children.empty() )
|
||||
|
|
|
@ -146,7 +146,7 @@ bool CGUIScrollBar::OnEvent(const SEvent& event)
|
|||
// thanks to tommi by tommi for another bugfix
|
||||
// everybody needs a little thanking. hallo niko!;-)
|
||||
setPos( getPos() +
|
||||
( (s32)event.MouseInput.Wheel * SmallStep * (Horizontal ? 1 : -1 ) )
|
||||
( (event.MouseInput.Wheel < 0 ? -1 : 1) * SmallStep * (Horizontal ? 1 : -1 ) )
|
||||
);
|
||||
|
||||
SEvent newEvent;
|
||||
|
|
|
@ -47,9 +47,9 @@ CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver)
|
|||
Colors[EGDC_ICON] = video::SColor(200,255,255,255);
|
||||
Colors[EGDC_ICON_HIGH_LIGHT] = video::SColor(200,8,36,107);
|
||||
Colors[EGDC_GRAY_WINDOW_SYMBOL] = video::SColor(240,100,100,100);
|
||||
Colors[EGDC_EDITABLE] = video::SColor(101,255,255,255);
|
||||
Colors[EGDC_GRAY_EDITABLE] = video::SColor(101,200,200,200);
|
||||
Colors[EGDC_FOCUSED_EDITABLE] = video::SColor(101,230,230,255);
|
||||
Colors[EGDC_EDITABLE] = video::SColor(255,255,255,255);
|
||||
Colors[EGDC_GRAY_EDITABLE] = video::SColor(255,120,120,120);
|
||||
Colors[EGDC_FOCUSED_EDITABLE] = video::SColor(255,240,240,255);
|
||||
|
||||
|
||||
Sizes[EGDS_SCROLLBAR_SIZE] = 14;
|
||||
|
@ -414,49 +414,74 @@ void CGUISkin::draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor,
|
|||
|
||||
core::rect<s32> rect = r;
|
||||
|
||||
if (fillBackGround)
|
||||
Driver->draw2DRectangle(bgcolor, rect, clip);
|
||||
|
||||
if (flat)
|
||||
{
|
||||
// draw flat sunken pane
|
||||
if (fillBackGround)
|
||||
Driver->draw2DRectangle(bgcolor, rect, clip);
|
||||
|
||||
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip);
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // top
|
||||
|
||||
++rect.UpperLeftCorner.Y;
|
||||
rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
|
||||
rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip);
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // left
|
||||
|
||||
rect = r;
|
||||
++rect.UpperLeftCorner.Y;
|
||||
rect.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip);
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // right
|
||||
|
||||
rect = r;
|
||||
++rect.UpperLeftCorner.X;
|
||||
rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
|
||||
rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip);
|
||||
--rect.LowerRightCorner.X;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // bottom
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw deep sunken pane
|
||||
if (fillBackGround)
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip);
|
||||
|
||||
rect.LowerRightCorner.X -= 1;
|
||||
rect.LowerRightCorner.Y -= 1;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip);
|
||||
|
||||
rect.UpperLeftCorner.X += 1;
|
||||
rect.UpperLeftCorner.Y += 1;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_LIGHT), rect, clip);
|
||||
|
||||
rect.LowerRightCorner.X -= 1;
|
||||
rect.LowerRightCorner.Y -= 1;
|
||||
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // top
|
||||
++rect.UpperLeftCorner.X;
|
||||
++rect.UpperLeftCorner.Y;
|
||||
--rect.LowerRightCorner.X;
|
||||
++rect.LowerRightCorner.Y;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip);
|
||||
|
||||
rect.UpperLeftCorner.X += 1;
|
||||
rect.UpperLeftCorner.Y += 1;
|
||||
Driver->draw2DRectangle(bgcolor, rect, clip);
|
||||
rect.UpperLeftCorner.X = r.UpperLeftCorner.X;
|
||||
rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y+1;
|
||||
rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
|
||||
rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // left
|
||||
++rect.UpperLeftCorner.X;
|
||||
++rect.UpperLeftCorner.Y;
|
||||
++rect.LowerRightCorner.X;
|
||||
--rect.LowerRightCorner.Y;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip);
|
||||
|
||||
rect = r;
|
||||
rect.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
|
||||
++rect.UpperLeftCorner.Y;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // right
|
||||
--rect.UpperLeftCorner.X;
|
||||
++rect.UpperLeftCorner.Y;
|
||||
--rect.LowerRightCorner.X;
|
||||
--rect.LowerRightCorner.Y;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_LIGHT), rect, clip);
|
||||
|
||||
rect = r;
|
||||
++rect.UpperLeftCorner.X;
|
||||
rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
|
||||
--rect.LowerRightCorner.X;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // bottom
|
||||
++rect.UpperLeftCorner.X;
|
||||
--rect.UpperLeftCorner.Y;
|
||||
--rect.LowerRightCorner.X;
|
||||
--rect.LowerRightCorner.Y;
|
||||
Driver->draw2DRectangle(getColor(EGDC_3D_LIGHT), rect, clip);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,14 @@ void CGUISpinBox::setRange(f32 min, f32 max)
|
|||
core::swap(min, max);
|
||||
RangeMin = min;
|
||||
RangeMax = max;
|
||||
|
||||
// we have to round the range - otherwise we can get into an infinte setValue/verifyValueRange cycle.
|
||||
wchar_t str[100];
|
||||
swprintf(str, 99, FormatString.c_str(), RangeMin);
|
||||
RangeMin = core::fast_atof(core::stringc(str).c_str());
|
||||
swprintf(str, 99, FormatString.c_str(), RangeMax);
|
||||
RangeMax = core::fast_atof(core::stringc(str).c_str());
|
||||
|
||||
verifyValueRange();
|
||||
}
|
||||
|
||||
|
@ -173,6 +181,7 @@ void CGUISpinBox::setDecimalPlaces(s32 places)
|
|||
FormatString += places;
|
||||
FormatString += "f";
|
||||
}
|
||||
setRange( RangeMin, RangeMax );
|
||||
setValue(getValue());
|
||||
}
|
||||
|
||||
|
@ -189,7 +198,7 @@ bool CGUISpinBox::OnEvent(const SEvent& event)
|
|||
{
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
{
|
||||
f32 val = getValue() + (StepSize * event.MouseInput.Wheel);
|
||||
f32 val = getValue() + (StepSize * (event.MouseInput.Wheel < 0 ? -1.f : 1.f));
|
||||
setValue(val);
|
||||
changeEvent = true;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ namespace gui
|
|||
virtual const wchar_t* getText() const;
|
||||
|
||||
//! Sets the number of decimal places to display.
|
||||
//! Note that this also rounds the range to the same number of decimal places.
|
||||
/** \param places: The number of decimal places to display, use -1 to reset */
|
||||
virtual void setDecimalPlaces(s32 places);
|
||||
|
||||
|
|
|
@ -82,9 +82,7 @@ void CGUIStaticText::draw()
|
|||
// draw the text
|
||||
if (Text.size())
|
||||
{
|
||||
IGUIFont* font = OverrideFont;
|
||||
if (!OverrideFont)
|
||||
font = skin->getFont();
|
||||
IGUIFont* font = getActiveFont();
|
||||
|
||||
if (font)
|
||||
{
|
||||
|
@ -162,12 +160,22 @@ void CGUIStaticText::setOverrideFont(IGUIFont* font)
|
|||
breakText();
|
||||
}
|
||||
|
||||
|
||||
//! Gets the override font (if any)
|
||||
IGUIFont * CGUIStaticText::getOverrideFont() const
|
||||
{
|
||||
return OverrideFont;
|
||||
}
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
IGUIFont* CGUIStaticText::getActiveFont() const
|
||||
{
|
||||
if ( OverrideFont )
|
||||
return OverrideFont;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
return skin->getFont();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets another color for the text.
|
||||
void CGUIStaticText::setOverrideColor(video::SColor color)
|
||||
|
@ -204,7 +212,7 @@ void CGUIStaticText::setTextRestrainedInside(bool restrainTextInside)
|
|||
{
|
||||
RestrainTextInside = restrainTextInside;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CGUIStaticText::isTextRestrainedInside() const
|
||||
{
|
||||
|
@ -275,36 +283,34 @@ bool CGUIStaticText::isRightToLeft() const
|
|||
//! Breaks the single text line.
|
||||
void CGUIStaticText::breakText()
|
||||
{
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
if (!WordWrap || !skin)
|
||||
if (!WordWrap)
|
||||
return;
|
||||
|
||||
BrokenText.clear();
|
||||
|
||||
IGUIFont* font = OverrideFont;
|
||||
if (!OverrideFont)
|
||||
font = skin->getFont();
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
IGUIFont* font = getActiveFont();
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
LastBreakFont = font;
|
||||
|
||||
core::stringw line;
|
||||
core::stringw word;
|
||||
core::stringw whitespace;
|
||||
s32 size = Text.size();
|
||||
s32 length = 0;
|
||||
s32 elWidth = RelativeRect.getWidth();
|
||||
if (Border)
|
||||
elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X);
|
||||
wchar_t c;
|
||||
|
||||
// We have to deal with right-to-left and left-to-right differently
|
||||
// However, most parts of the following code is the same, it's just
|
||||
// some order and boundaries which change.
|
||||
if (!RightToLeft)
|
||||
{
|
||||
// regular (left-to-right)
|
||||
core::stringw line;
|
||||
core::stringw word;
|
||||
core::stringw whitespace;
|
||||
s32 size = Text.size();
|
||||
s32 length = 0;
|
||||
s32 elWidth = RelativeRect.getWidth() - 6;
|
||||
wchar_t c;
|
||||
|
||||
for (s32 i=0; i<size; ++i)
|
||||
{
|
||||
c = Text[i];
|
||||
|
@ -326,7 +332,14 @@ void CGUIStaticText::breakText()
|
|||
c = '\0';
|
||||
}
|
||||
|
||||
if (c==L' ' || c==0 || i==(size-1))
|
||||
bool isWhitespace = (c == L' ' || c == 0);
|
||||
if ( !isWhitespace )
|
||||
{
|
||||
// part of a word
|
||||
word += c;
|
||||
}
|
||||
|
||||
if ( isWhitespace || i == (size-1))
|
||||
{
|
||||
if (word.size())
|
||||
{
|
||||
|
@ -334,7 +347,7 @@ void CGUIStaticText::breakText()
|
|||
// we must break the last word to the next line.
|
||||
const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
|
||||
const s32 wordlgth = font->getDimension(word.c_str()).Width;
|
||||
|
||||
|
||||
if (wordlgth > elWidth)
|
||||
{
|
||||
// This word is too long to fit in the available space, look for
|
||||
|
@ -347,7 +360,7 @@ void CGUIStaticText::breakText()
|
|||
core::stringw second = word.subString(where, word.size() - where);
|
||||
BrokenText.push_back(line + first + L"-");
|
||||
const s32 secondLength = font->getDimension(second.c_str()).Width;
|
||||
|
||||
|
||||
length = secondLength;
|
||||
line = second;
|
||||
}
|
||||
|
@ -380,7 +393,10 @@ void CGUIStaticText::breakText()
|
|||
whitespace = L"";
|
||||
}
|
||||
|
||||
whitespace += c;
|
||||
if ( isWhitespace )
|
||||
{
|
||||
whitespace += c;
|
||||
}
|
||||
|
||||
// compute line break
|
||||
if (lineBreak)
|
||||
|
@ -394,11 +410,6 @@ void CGUIStaticText::breakText()
|
|||
length = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// yippee this is a word..
|
||||
word += c;
|
||||
}
|
||||
}
|
||||
|
||||
line += whitespace;
|
||||
|
@ -408,14 +419,6 @@ void CGUIStaticText::breakText()
|
|||
else
|
||||
{
|
||||
// right-to-left
|
||||
core::stringw line;
|
||||
core::stringw word;
|
||||
core::stringw whitespace;
|
||||
s32 size = Text.size();
|
||||
s32 length = 0;
|
||||
s32 elWidth = RelativeRect.getWidth() - 6;
|
||||
wchar_t c;
|
||||
|
||||
for (s32 i=size; i>=0; --i)
|
||||
{
|
||||
c = Text[i];
|
||||
|
@ -512,15 +515,7 @@ void CGUIStaticText::updateAbsolutePosition()
|
|||
//! Returns the height of the text in pixels when it is drawn.
|
||||
s32 CGUIStaticText::getTextHeight() const
|
||||
{
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
if (!skin)
|
||||
return 0;
|
||||
|
||||
IGUIFont* font = OverrideFont;
|
||||
if (!OverrideFont)
|
||||
font = skin->getFont();
|
||||
|
||||
IGUIFont* font = getActiveFont();
|
||||
if (!font)
|
||||
return 0;
|
||||
|
||||
|
@ -535,15 +530,7 @@ s32 CGUIStaticText::getTextHeight() const
|
|||
|
||||
s32 CGUIStaticText::getTextWidth() const
|
||||
{
|
||||
IGUIFont * font = OverrideFont;
|
||||
|
||||
if(!OverrideFont)
|
||||
{
|
||||
IGUISkin * skin = Environment->getSkin();
|
||||
if(skin)
|
||||
font = skin->getFont();
|
||||
}
|
||||
|
||||
IGUIFont * font = getActiveFont();
|
||||
if(!font)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -34,7 +34,10 @@ namespace gui
|
|||
virtual void setOverrideFont(IGUIFont* font=0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
virtual IGUIFont * getOverrideFont() const;
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets another color for the text.
|
||||
virtual void setOverrideColor(video::SColor color);
|
||||
|
@ -63,7 +66,7 @@ namespace gui
|
|||
|
||||
//! Set whether the text in this label should be clipped if it goes outside bounds
|
||||
virtual void setTextRestrainedInside(bool restrainedInside);
|
||||
|
||||
|
||||
//! Checks if the text in this label should be clipped if it goes outside bounds
|
||||
virtual bool isTextRestrainedInside() const;
|
||||
|
||||
|
|
|
@ -583,7 +583,7 @@ bool CGUITable::OnEvent(const SEvent &event)
|
|||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
VerticalScrollBar->setPos(VerticalScrollBar->getPos() + (s32)event.MouseInput.Wheel*-10);
|
||||
VerticalScrollBar->setPos(VerticalScrollBar->getPos() + (event.MouseInput.Wheel < 0 ? -1 : 1)*-10);
|
||||
return true;
|
||||
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
|
|
|
@ -625,7 +625,7 @@ bool CGUITreeView::OnEvent( const SEvent &event )
|
|||
{
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
if ( ScrollBarV )
|
||||
ScrollBarV->setPos( ScrollBarV->getPos() + (s32)event.MouseInput.Wheel * -10 );
|
||||
ScrollBarV->setPos( ScrollBarV->getPos() + (event.MouseInput.Wheel < 0 ? -1 : 1) * -10 );
|
||||
return true;
|
||||
break;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "CTimer.h"
|
||||
#include "CLogger.h"
|
||||
#include "irrString.h"
|
||||
#include "IRandomizer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
@ -19,7 +20,7 @@ namespace irr
|
|||
CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters& params)
|
||||
: IrrlichtDevice(), VideoDriver(0), GUIEnvironment(0), SceneManager(0),
|
||||
Timer(0), CursorControl(0), UserReceiver(params.EventReceiver), Logger(0), Operator(0),
|
||||
FileSystem(0), InputReceivingSceneManager(0), CreationParams(params),
|
||||
Randomizer(0), FileSystem(0), InputReceivingSceneManager(0), CreationParams(params),
|
||||
Close(false)
|
||||
{
|
||||
Timer = new CTimer(params.UsePerformanceTimer);
|
||||
|
@ -34,9 +35,10 @@ CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters& params)
|
|||
Logger = new CLogger(UserReceiver);
|
||||
os::Printer::Logger = Logger;
|
||||
}
|
||||
Logger->setLogLevel( CreationParams.LoggingLevel );
|
||||
Logger->setLogLevel(CreationParams.LoggingLevel);
|
||||
|
||||
os::Printer::Logger = Logger;
|
||||
Randomizer = createDefaultRandomizer();
|
||||
|
||||
FileSystem = io::createFileSystem();
|
||||
core::stringc s = "Irrlicht Engine version ";
|
||||
|
@ -69,9 +71,13 @@ CIrrDeviceStub::~CIrrDeviceStub()
|
|||
if (Operator)
|
||||
Operator->drop();
|
||||
|
||||
if (Randomizer)
|
||||
Randomizer->drop();
|
||||
|
||||
CursorControl = 0;
|
||||
|
||||
Timer->drop();
|
||||
if (Timer)
|
||||
Timer->drop();
|
||||
|
||||
if (Logger->drop())
|
||||
os::Printer::Logger = 0;
|
||||
|
@ -256,6 +262,61 @@ IOSOperator* CIrrDeviceStub::getOSOperator()
|
|||
}
|
||||
|
||||
|
||||
//! Provides access to the engine's currently set randomizer.
|
||||
IRandomizer* CIrrDeviceStub::getRandomizer() const
|
||||
{
|
||||
return Randomizer;
|
||||
}
|
||||
|
||||
//! Sets a new randomizer.
|
||||
void CIrrDeviceStub::setRandomizer(IRandomizer* r)
|
||||
{
|
||||
if (r!=Randomizer)
|
||||
{
|
||||
if (Randomizer)
|
||||
Randomizer->drop();
|
||||
Randomizer=r;
|
||||
if (Randomizer)
|
||||
Randomizer->grab();
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct SDefaultRandomizer : public IRandomizer
|
||||
{
|
||||
virtual void reset(s32 value=0x0f0f0f0f)
|
||||
{
|
||||
os::Randomizer::reset(value);
|
||||
}
|
||||
|
||||
virtual s32 rand() const
|
||||
{
|
||||
return os::Randomizer::rand();
|
||||
}
|
||||
|
||||
virtual f32 frand() const
|
||||
{
|
||||
return os::Randomizer::frand();
|
||||
}
|
||||
|
||||
virtual s32 randMax() const
|
||||
{
|
||||
return os::Randomizer::randMax();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//! Creates a new default randomizer.
|
||||
IRandomizer* CIrrDeviceStub::createDefaultRandomizer() const
|
||||
{
|
||||
IRandomizer* r = new SDefaultRandomizer();
|
||||
if (r)
|
||||
r->reset();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the input receiving scene manager.
|
||||
void CIrrDeviceStub::setInputReceivingSceneManager(scene::ISceneManager* sceneManager)
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace irr
|
|||
// lots of prototypes:
|
||||
class ILogger;
|
||||
class CLogger;
|
||||
class IRandomizer;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
@ -97,6 +98,15 @@ namespace irr
|
|||
//! Returns a pointer to the logger.
|
||||
virtual ILogger* getLogger();
|
||||
|
||||
//! Provides access to the engine's currently set randomizer.
|
||||
virtual IRandomizer* getRandomizer() const;
|
||||
|
||||
//! Sets a new randomizer.
|
||||
virtual void setRandomizer(IRandomizer* r);
|
||||
|
||||
//! Creates a new default randomizer.
|
||||
virtual IRandomizer* createDefaultRandomizer() const;
|
||||
|
||||
//! Returns the operation system opertator object.
|
||||
virtual IOSOperator* getOSOperator();
|
||||
|
||||
|
@ -148,6 +158,7 @@ namespace irr
|
|||
IEventReceiver* UserReceiver;
|
||||
CLogger* Logger;
|
||||
IOSOperator* Operator;
|
||||
IRandomizer* Randomizer;
|
||||
io::IFileSystem* FileSystem;
|
||||
scene::ISceneManager* InputReceivingSceneManager;
|
||||
|
||||
|
|
|
@ -289,6 +289,8 @@ const core::aabbox3d<f32>& COctreeSceneNode::getBoundingBox() const
|
|||
|
||||
|
||||
//! creates the tree
|
||||
/* This method has a lot of duplication and overhead. Moreover, the tangents mesh conversion does not really work. I think we need a a proper mesh implementation for octrees, which handle all vertex types internally. Converting all structures to just one vertex type is always problematic.
|
||||
Thanks to Auria for fixing major parts of this method. */
|
||||
bool COctreeSceneNode::createTree(IMesh* mesh)
|
||||
{
|
||||
if (!mesh)
|
||||
|
@ -301,7 +303,7 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
|
|||
|
||||
Mesh = mesh;
|
||||
|
||||
u32 beginTime = os::Timer::getRealTime();
|
||||
const u32 beginTime = os::Timer::getRealTime();
|
||||
|
||||
u32 nodeCount = 0;
|
||||
u32 polyCount = 0;
|
||||
|
@ -311,12 +313,28 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
|
|||
|
||||
if (mesh->getMeshBufferCount())
|
||||
{
|
||||
VertexType = mesh->getMeshBuffer(0)->getVertexType();
|
||||
// check for "larger" buffer types
|
||||
VertexType = video::EVT_STANDARD;
|
||||
u32 meshReserve = 0;
|
||||
for (i=0; i<mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
const IMeshBuffer* b = mesh->getMeshBuffer(i);
|
||||
if (b->getVertexCount() && b->getIndexCount())
|
||||
{
|
||||
++meshReserve;
|
||||
if (b->getVertexType() == video::EVT_2TCOORDS)
|
||||
VertexType = video::EVT_2TCOORDS;
|
||||
else if (b->getVertexType() == video::EVT_TANGENTS)
|
||||
VertexType = video::EVT_TANGENTS;
|
||||
}
|
||||
}
|
||||
Materials.reallocate(Materials.size()+meshReserve);
|
||||
|
||||
switch(VertexType)
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
{
|
||||
StdMeshes.reallocate(StdMeshes.size() + meshReserve);
|
||||
for (i=0; i<mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
IMeshBuffer* b = mesh->getMeshBuffer(i);
|
||||
|
@ -331,8 +349,21 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
|
|||
|
||||
u32 v;
|
||||
nchunk.Vertices.reallocate(b->getVertexCount());
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]);
|
||||
switch (b->getVertexType())
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]);
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]);
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]);
|
||||
break;
|
||||
}
|
||||
|
||||
polyCount += b->getIndexCount();
|
||||
|
||||
|
@ -348,22 +379,11 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
|
|||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
{
|
||||
IMeshBuffer* b;
|
||||
u32 meshReserve = 0;
|
||||
for ( i=0; i < mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
b = mesh->getMeshBuffer(i);
|
||||
if (b->getVertexCount() && b->getIndexCount())
|
||||
{
|
||||
meshReserve += 1;
|
||||
}
|
||||
|
||||
}
|
||||
LightMapMeshes.reallocate ( LightMapMeshes.size() + meshReserve );
|
||||
LightMapMeshes.reallocate(LightMapMeshes.size() + meshReserve);
|
||||
|
||||
for ( i=0; i < mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
b = mesh->getMeshBuffer(i);
|
||||
IMeshBuffer* b = mesh->getMeshBuffer(i);
|
||||
|
||||
if (b->getVertexCount() && b->getIndexCount())
|
||||
{
|
||||
|
@ -382,8 +402,21 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
|
|||
|
||||
u32 v;
|
||||
nchunk.Vertices.reallocate(b->getVertexCount());
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]);
|
||||
switch (b->getVertexType())
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]);
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]);
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]);
|
||||
break;
|
||||
}
|
||||
|
||||
polyCount += b->getIndexCount();
|
||||
nchunk.Indices.reallocate(b->getIndexCount());
|
||||
|
@ -398,6 +431,8 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
|
|||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
{
|
||||
TangentsMeshes.reallocate(TangentsMeshes.size() + meshReserve);
|
||||
|
||||
for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
IMeshBuffer* b = mesh->getMeshBuffer(i);
|
||||
|
@ -411,8 +446,27 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
|
|||
|
||||
u32 v;
|
||||
nchunk.Vertices.reallocate(b->getVertexCount());
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]);
|
||||
switch (b->getVertexType())
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
{
|
||||
const video::S3DVertex& tmpV = ((video::S3DVertex*)b->getVertices())[v];
|
||||
nchunk.Vertices.push_back(video::S3DVertexTangents(tmpV.Pos, tmpV.Color, tmpV.TCoords));
|
||||
}
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
{
|
||||
const video::S3DVertex2TCoords& tmpV = ((video::S3DVertex2TCoords*)b->getVertices())[v];
|
||||
nchunk.Vertices.push_back(video::S3DVertexTangents(tmpV.Pos, tmpV.Color, tmpV.TCoords));
|
||||
}
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]);
|
||||
break;
|
||||
}
|
||||
|
||||
polyCount += b->getIndexCount();
|
||||
nchunk.Indices.reallocate(b->getIndexCount());
|
||||
|
@ -428,7 +482,7 @@ bool COctreeSceneNode::createTree(IMesh* mesh)
|
|||
}
|
||||
}
|
||||
|
||||
u32 endTime = os::Timer::getRealTime();
|
||||
const u32 endTime = os::Timer::getRealTime();
|
||||
c8 tmp[255];
|
||||
sprintf(tmp, "Needed %ums to create Octree SceneNode.(%u nodes, %u polys)",
|
||||
endTime - beginTime, nodeCount, polyCount/3);
|
||||
|
|
|
@ -193,6 +193,11 @@ public:
|
|||
//! Remove all currently visible particles
|
||||
virtual void clearParticles();
|
||||
|
||||
//! Do manually update the particles.
|
||||
//! This should only be called when you want to render the node outside the scenegraph,
|
||||
//! as the node will care about this otherwise automatically.
|
||||
virtual void doParticleSystem(u32 time);
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
|
@ -204,7 +209,6 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void doParticleSystem(u32 time);
|
||||
void reallocateBuffers();
|
||||
|
||||
core::list<IParticleAffector*> AffectorList;
|
||||
|
|
|
@ -358,6 +358,9 @@ bool CSceneCollisionManager::getCollisionPoint(const core::line3d<f32>& ray,
|
|||
}
|
||||
|
||||
s32 totalcnt = selector->getTriangleCount();
|
||||
if ( totalcnt <= 0 )
|
||||
return false;
|
||||
|
||||
Triangles.set_used(totalcnt);
|
||||
|
||||
s32 cnt = 0;
|
||||
|
@ -889,7 +892,7 @@ core::position2d<s32> CSceneCollisionManager::getScreenCoordinatesFrom3DPosition
|
|||
if (useViewPort)
|
||||
dim.set(Driver->getViewPort().getWidth(), Driver->getViewPort().getHeight());
|
||||
else
|
||||
dim=(Driver->getScreenSize());
|
||||
dim=(Driver->getCurrentRenderTargetSize());
|
||||
|
||||
dim.Width /= 2;
|
||||
dim.Height /= 2;
|
||||
|
|
|
@ -2475,7 +2475,7 @@ IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type)
|
|||
#endif
|
||||
case EMWT_COLLADA:
|
||||
#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_
|
||||
return new CColladaMeshWriter(Driver, FileSystem);
|
||||
return new CColladaMeshWriter(this, Driver, FileSystem);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
|
|
@ -433,7 +433,7 @@ namespace scene
|
|||
virtual ISceneManager* createNewSceneManager(bool cloneContent);
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_UNKNOWN; }
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_SCENE_MANAGER; }
|
||||
|
||||
//! Returns the default scene node factory which can create all built in scene nodes
|
||||
virtual ISceneNodeFactory* getDefaultSceneNodeFactory();
|
||||
|
|
|
@ -28,14 +28,7 @@ CWaterSurfaceSceneNode::CWaterSurfaceSceneNode(f32 waveHeight, f32 waveSpeed, f3
|
|||
setDebugName("CWaterSurfaceSceneNode");
|
||||
#endif
|
||||
|
||||
// create copy of the mesh
|
||||
if (mesh)
|
||||
{
|
||||
// Mesh is set in CMeshSceneNode constructor, now it is moved to OriginalMesh
|
||||
IMesh* clone = SceneManager->getMeshManipulator()->createMeshCopy(mesh);
|
||||
OriginalMesh = Mesh;
|
||||
Mesh = clone;
|
||||
}
|
||||
setMesh(mesh);
|
||||
}
|
||||
|
||||
|
||||
|
@ -71,6 +64,7 @@ void CWaterSurfaceSceneNode::OnAnimate(u32 timeMs)
|
|||
OriginalMesh->getMeshBuffer(b)->getPosition(i),
|
||||
time);
|
||||
}// end for all mesh buffers
|
||||
Mesh->setDirty(scene::EBT_VERTEX);
|
||||
|
||||
SceneManager->getMeshManipulator()->recalculateNormals(Mesh);
|
||||
}
|
||||
|
@ -88,6 +82,8 @@ void CWaterSurfaceSceneNode::setMesh(IMesh* mesh)
|
|||
IMesh* clone = SceneManager->getMeshManipulator()->createMeshCopy(mesh);
|
||||
OriginalMesh = mesh;
|
||||
Mesh = clone;
|
||||
Mesh->setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_INDEX);
|
||||
// Mesh->setHardwareMappingHint(scene::EHM_STREAM, scene::EBT_VERTEX);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ IFileArchive* CArchiveLoaderZIP::createArchive(io::IReadFile* file, bool ignoreC
|
|||
file->read(&sig, 2);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
os::Byteswap::byteswap(sig);
|
||||
sig = os::Byteswap::byteswap(sig);
|
||||
#endif
|
||||
|
||||
file->seek(0);
|
||||
|
@ -126,7 +126,7 @@ bool CArchiveLoaderZIP::isALoadableFileFormat(io::IReadFile* file) const
|
|||
|
||||
file->read( &header.Sig, 4 );
|
||||
#ifdef __BIG_ENDIAN__
|
||||
os::Byteswap::byteswap(header.Sig);
|
||||
header.Sig = os::Byteswap::byteswap(header.Sig);
|
||||
#endif
|
||||
|
||||
return header.Sig == 0x04034b50 || // ZIP
|
||||
|
@ -192,8 +192,8 @@ bool CZipReader::scanGZipHeader()
|
|||
{
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
os::Byteswap::byteswap(header.sig);
|
||||
os::Byteswap::byteswap(header.time);
|
||||
header.sig = os::Byteswap::byteswap(header.sig);
|
||||
header.time = os::Byteswap::byteswap(header.time);
|
||||
#endif
|
||||
|
||||
// check header value
|
||||
|
@ -209,7 +209,7 @@ bool CZipReader::scanGZipHeader()
|
|||
File->read(&dataLen, 2);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
os::Byteswap::byteswap(dataLen);
|
||||
dataLen = os::Byteswap::byteswap(dataLen);
|
||||
#endif
|
||||
|
||||
// skip it
|
||||
|
@ -274,8 +274,8 @@ bool CZipReader::scanGZipHeader()
|
|||
File->read(&entry.header.DataDescriptor.UncompressedSize, 4);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32);
|
||||
os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize);
|
||||
entry.header.DataDescriptor.CRC32 = os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32);
|
||||
entry.header.DataDescriptor.UncompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize);
|
||||
#endif
|
||||
|
||||
// now we've filled all the fields, this is just a standard deflate block
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<Build>
|
||||
<Target title="Win32 - Debug - dll">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../../lib/Win32-gcc/Irrlicht" prefix_auto="1" extension_auto="1" />
|
||||
<Option output="../../lib/Win32-gcc/libIrrlicht" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="../obj/win32-gcc-debug-dll" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
|
@ -52,7 +52,7 @@
|
|||
</Target>
|
||||
<Target title="Win32 - Release - accurate math - dll">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../../lib/Win32-gcc/Irrlicht" prefix_auto="1" extension_auto="1" />
|
||||
<Option output="../../lib/Win32-gcc/libIrrlicht" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="../obj/win32-gcc-release-dll" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
|
@ -94,7 +94,7 @@
|
|||
</Target>
|
||||
<Target title="Win32 - Release - fast math - dll">
|
||||
<Option platforms="Windows;" />
|
||||
<Option output="../../lib/Win32-gcc/Irrlicht" prefix_auto="1" extension_auto="1" />
|
||||
<Option output="../../lib/Win32-gcc/libIrrlicht" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="../obj/win32-gcc-release-fast-dll" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
|
@ -455,6 +455,7 @@
|
|||
<Unit filename="../../include/IBillboardTextSceneNode.h" />
|
||||
<Unit filename="../../include/IBoneSceneNode.h" />
|
||||
<Unit filename="../../include/ICameraSceneNode.h" />
|
||||
<Unit filename="../../include/IColladaMeshWriter.h" />
|
||||
<Unit filename="../../include/ICursorControl.h" />
|
||||
<Unit filename="../../include/IDummyTransformationSceneNode.h" />
|
||||
<Unit filename="../../include/IDynamicMeshBuffer.h" />
|
||||
|
|
|
@ -827,6 +827,7 @@
|
|||
<ClInclude Include="..\..\include\IEventReceiver.h" />
|
||||
<ClInclude Include="..\..\include\ILogger.h" />
|
||||
<ClInclude Include="..\..\include\IOSOperator.h" />
|
||||
<ClInclude Include="..\..\include\IRandomizer.h" />
|
||||
<ClInclude Include="..\..\include\IReferenceCounted.h" />
|
||||
<ClInclude Include="..\..\include\IrrCompileConfig.h" />
|
||||
<ClInclude Include="..\..\include\irrlicht.h" />
|
||||
|
|
|
@ -1339,6 +1339,9 @@
|
|||
<ClInclude Include="..\..\include\EDriverFeatures.h">
|
||||
<Filter>include\video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\IRandomizer.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\changes.txt">
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 8
|
||||
VERSION_RELEASE = 0-SVN
|
||||
VERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
|
||||
COMPATIBILITY_VERSION = $(VERSION_MAJOR).$(VERSION_MINOR)
|
||||
# Irrlicht Engine 1.7.0-SVN
|
||||
# Irrlicht Engine 1.8.0-SVN
|
||||
# Makefile for Linux
|
||||
#
|
||||
# To use, just run:
|
||||
|
@ -18,6 +16,10 @@ COMPATIBILITY_VERSION = $(VERSION_MAJOR).$(VERSION_MINOR)
|
|||
# make sharedlib
|
||||
# make install
|
||||
#
|
||||
# If you want to compile in release mode run:
|
||||
#
|
||||
# make NDEBUG=1
|
||||
#
|
||||
# For cross-compilation for Win32 under Linux, just use the win32 targets. You have to set
|
||||
# at least CXX, CC, and AR to the proper binaries.
|
||||
#
|
||||
|
@ -105,15 +107,19 @@ sharedlib_win32: LDFLAGS += -lgdi32 -lopengl32 -ld3dx9d -lwinmm
|
|||
sharedlib_win32 staticlib_win32: CPPFLAGS += -DIRR_COMPILE_WITH_DX9_DEV_PACK -D__GNUWIN32__ -D_WIN32 -DWIN32 -D_WINDOWS -D_MBCS -D_USRDLL
|
||||
staticlib_win32: CPPFLAGS += -D_IRR_STATIC_LIB_
|
||||
|
||||
VERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
|
||||
SHARED_FULLNAME = $(SHARED_LIB).$(VERSION)
|
||||
SONAME = $(SHARED_LIB).$(VERSION_MAJOR).$(VERSION_MINOR)
|
||||
|
||||
####################
|
||||
# All target, builds Irrlicht as static lib (libIrrlicht.a) and copies it into lib/Linux
|
||||
all linux: staticlib
|
||||
|
||||
# Builds Irrlicht as shared lib (libIrrlicht.so.versionNumber) and copies it into lib/Linux
|
||||
sharedlib: $(LINKOBJ)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -shared -Wl,-soname,$(SHARED_LIB).$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE) -o $(SHARED_LIB).$(VERSION) $^ $(LDFLAGS)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -shared -Wl,-soname,$(SONAME) -o $(SHARED_FULLNAME) $^ $(LDFLAGS)
|
||||
mkdir -p $(LIB_PATH)
|
||||
cp $(SHARED_LIB).$(VERSION) $(LIB_PATH)
|
||||
cp $(SHARED_FULLNAME) $(LIB_PATH)
|
||||
|
||||
# Builds Irrlicht as static lib (libIrrlicht.a)
|
||||
$(STATIC_LIB): $(LINKOBJ)
|
||||
|
@ -135,17 +141,17 @@ staticlib_win32: $(STATIC_LIB)
|
|||
|
||||
# Builds Irrlicht as shared lib (libIrrlicht.so.versionNumber) and copies it into /lib/MacOSX
|
||||
sharedlib_osx: $(LINKOBJ)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -dynamiclib -Wl,-install_name,$(SHARED_LIB).$(COMPATIBILITY_VERSION) -o $(SHARED_LIB).$(VERSION) $^ $(LDFLAGS)
|
||||
cp $(SHARED_LIB).$(VERSION) $(LIB_PATH)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -dynamiclib -Wl,-install_name,$(SONAME) -o $(SHARED_FULLNAME) $^ $(LDFLAGS)
|
||||
cp $(SHARED_FULLNAME) $(LIB_PATH)
|
||||
|
||||
# Installs Irrlicht if it was created as shared lib
|
||||
install install_osx:
|
||||
$(RM) -r $(INSTALL_DIR)/../include/irrlicht
|
||||
mkdir -p $(INSTALL_DIR)/../include/irrlicht
|
||||
cp ../../include/*.h $(INSTALL_DIR)/../include/irrlicht/
|
||||
cp $(LIB_PATH)/$(SHARED_LIB).$(VERSION) $(INSTALL_DIR)
|
||||
cd $(INSTALL_DIR) && ln -s -f $(SHARED_LIB).$(VERSION) $(COMPATIBILITY_VERSION)
|
||||
|
||||
cp $(LIB_PATH)/$(SHARED_FULLNAME) $(INSTALL_DIR)
|
||||
cd $(INSTALL_DIR) && ln -s -f $(SHARED_FULLNAME) $(SONAME)
|
||||
cd $(INSTALL_DIR) && ln -s -f $(SONAME) $(SHARED_LIB)
|
||||
# ldconfig -n $(INSTALL_DIR)
|
||||
|
||||
TAGS:
|
||||
|
@ -180,7 +186,7 @@ help:
|
|||
|
||||
# Cleans all temporary files and compilation results.
|
||||
clean:
|
||||
$(RM) $(LINKOBJ) $(SHARED_LIB).$(VERSION) $(STATIC_LIB) $(LINKOBJ:.o=.d)
|
||||
$(RM) $(LINKOBJ) $(SHARED_FULLNAME) $(STATIC_LIB) $(LINKOBJ:.o=.d)
|
||||
|
||||
.PHONY: all sharedlib staticlib sharedlib_win32 staticlib_win32 help install clean
|
||||
|
||||
|
|
|
@ -222,9 +222,9 @@ namespace os
|
|||
}
|
||||
|
||||
//! resets the randomizer
|
||||
void Randomizer::reset()
|
||||
void Randomizer::reset(s32 value)
|
||||
{
|
||||
seed = 0x0f0f0f0f;
|
||||
seed = value;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace os
|
|||
public:
|
||||
|
||||
//! resets the randomizer
|
||||
static void reset();
|
||||
static void reset(s32 value=0x0f0f0f0f);
|
||||
|
||||
//! generates a pseudo random number in the range 0..randMax()
|
||||
static s32 rand();
|
||||
|
|
|
@ -9,23 +9,23 @@ namespace
|
|||
// based on code and media from SuperTuxKart
|
||||
class ScalableFont : public gui::IGUIFontBitmap
|
||||
{
|
||||
float m_scale;
|
||||
struct TextureInfo
|
||||
{
|
||||
irr::core::stringc m_file_name;
|
||||
bool m_has_alpha;
|
||||
float m_scale;
|
||||
|
||||
TextureInfo()
|
||||
{
|
||||
m_has_alpha = false;
|
||||
m_scale = 1.0f;
|
||||
}
|
||||
};
|
||||
|
||||
std::map<int /* texture file ID */, TextureInfo> m_texture_files;
|
||||
|
||||
void lazyLoadTexture(int texID)
|
||||
float m_scale;
|
||||
struct TextureInfo
|
||||
{
|
||||
irr::core::stringc m_file_name;
|
||||
bool m_has_alpha;
|
||||
float m_scale;
|
||||
|
||||
TextureInfo()
|
||||
{
|
||||
m_has_alpha = false;
|
||||
m_scale = 1.0f;
|
||||
}
|
||||
};
|
||||
|
||||
std::map<int /* texture file ID */, TextureInfo> m_texture_files;
|
||||
|
||||
void lazyLoadTexture(int texID)
|
||||
{
|
||||
const bool mipmap = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
|
||||
|
@ -33,7 +33,7 @@ class ScalableFont : public gui::IGUIFontBitmap
|
|||
SpriteBank->setTexture(texID, Driver->getTexture( m_texture_files[texID].m_file_name ));
|
||||
// set previous mip-map+filter state
|
||||
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap);
|
||||
|
||||
|
||||
// couldn't load texture, abort.
|
||||
if (!SpriteBank->getTexture(texID))
|
||||
{
|
||||
|
@ -48,7 +48,7 @@ class ScalableFont : public gui::IGUIFontBitmap
|
|||
}
|
||||
}
|
||||
}
|
||||
void doReadXmlFile(io::IXMLReader* xml)
|
||||
void doReadXmlFile(io::IXMLReader* xml)
|
||||
{
|
||||
while (xml->read())
|
||||
{
|
||||
|
@ -70,29 +70,29 @@ class ScalableFont : public gui::IGUIFontBitmap
|
|||
core::stringc filename = xml->getAttributeValue(L"filename");
|
||||
core::stringc fn = filename;
|
||||
u32 i = (u32)xml->getAttributeValueAsInt(L"index");
|
||||
|
||||
|
||||
float scale=1.0f;
|
||||
if(xml->getAttributeValue(L"scale"))
|
||||
if (xml->getAttributeValue(L"scale"))
|
||||
scale = xml->getAttributeValueAsFloat(L"scale");
|
||||
//std::cout << "scale = " << scale << std::endl;
|
||||
|
||||
|
||||
core::stringw alpha = xml->getAttributeValue(L"hasAlpha");
|
||||
|
||||
|
||||
//std::cout << "---- Adding font texture " << fn.c_str() << "; alpha=" << alpha.c_str() << std::endl;
|
||||
|
||||
|
||||
|
||||
|
||||
// make sure the sprite bank has enough textures in it
|
||||
while (i+1 > SpriteBank->getTextureCount())
|
||||
{
|
||||
SpriteBank->addTexture(NULL);
|
||||
}
|
||||
|
||||
|
||||
TextureInfo info;
|
||||
info.m_file_name = fn;
|
||||
info.m_has_alpha = (alpha == core::stringw("true"));
|
||||
info.m_scale = scale;
|
||||
|
||||
m_texture_files[i] = info;
|
||||
info.m_scale = scale;
|
||||
|
||||
m_texture_files[i] = info;
|
||||
}
|
||||
else if (core::stringw(L"c") == xml->getNodeName())
|
||||
{
|
||||
|
@ -101,16 +101,16 @@ class ScalableFont : public gui::IGUIFontBitmap
|
|||
gui::SGUISpriteFrame f;
|
||||
gui::SGUISprite s;
|
||||
core::rect<s32> rectangle;
|
||||
|
||||
a.underhang = xml->getAttributeValueAsInt(L"u");
|
||||
a.overhang = xml->getAttributeValueAsInt(L"o");
|
||||
a.spriteno = SpriteBank->getSprites().size();
|
||||
s32 texno = xml->getAttributeValueAsInt(L"i");
|
||||
|
||||
|
||||
a.underhang = xml->getAttributeValueAsInt(L"u");
|
||||
a.overhang = xml->getAttributeValueAsInt(L"o");
|
||||
a.spriteno = SpriteBank->getSprites().size();
|
||||
s32 texno = xml->getAttributeValueAsInt(L"i");
|
||||
|
||||
// parse rectangle
|
||||
core::stringc rectstr = xml->getAttributeValue(L"r");
|
||||
wchar_t ch = xml->getAttributeValue(L"c")[0];
|
||||
|
||||
wchar_t ch = xml->getAttributeValue(L"c")[0];
|
||||
|
||||
const c8 *c = rectstr.c_str();
|
||||
s32 val;
|
||||
val = 0;
|
||||
|
@ -122,7 +122,7 @@ class ScalableFont : public gui::IGUIFontBitmap
|
|||
}
|
||||
rectangle.UpperLeftCorner.X = val;
|
||||
while (*c == L' ' || *c == L',') c++;
|
||||
|
||||
|
||||
val = 0;
|
||||
while (*c >= '0' && *c <= '9')
|
||||
{
|
||||
|
@ -132,7 +132,7 @@ class ScalableFont : public gui::IGUIFontBitmap
|
|||
}
|
||||
rectangle.UpperLeftCorner.Y = val;
|
||||
while (*c == L' ' || *c == L',') c++;
|
||||
|
||||
|
||||
val = 0;
|
||||
while (*c >= '0' && *c <= '9')
|
||||
{
|
||||
|
@ -142,7 +142,7 @@ class ScalableFont : public gui::IGUIFontBitmap
|
|||
}
|
||||
rectangle.LowerRightCorner.X = val;
|
||||
while (*c == L' ' || *c == L',') c++;
|
||||
|
||||
|
||||
val = 0;
|
||||
while (*c >= '0' && *c <= '9')
|
||||
{
|
||||
|
@ -151,24 +151,24 @@ class ScalableFont : public gui::IGUIFontBitmap
|
|||
c++;
|
||||
}
|
||||
rectangle.LowerRightCorner.Y = val;
|
||||
|
||||
|
||||
CharacterMap[ch] = Areas.size();
|
||||
|
||||
|
||||
// make frame
|
||||
f.rectNumber = SpriteBank->getPositions().size();
|
||||
f.textureNumber = texno;
|
||||
|
||||
|
||||
// add frame to sprite
|
||||
s.Frames.push_back(f);
|
||||
s.frameTime = 0;
|
||||
|
||||
|
||||
// add rectangle to sprite bank
|
||||
SpriteBank->getPositions().push_back(rectangle);
|
||||
a.width = rectangle.getWidth();
|
||||
|
||||
|
||||
// add sprite to sprite bank
|
||||
SpriteBank->getSprites().push_back(s);
|
||||
|
||||
|
||||
// add character to font
|
||||
Areas.push_back(a);
|
||||
}
|
||||
|
@ -178,13 +178,13 @@ class ScalableFont : public gui::IGUIFontBitmap
|
|||
|
||||
public:
|
||||
|
||||
bool m_black_border;
|
||||
|
||||
ScalableFont* m_fallback_font;
|
||||
float m_fallback_font_scale;
|
||||
int m_fallback_kerning_width;
|
||||
|
||||
//! constructor
|
||||
bool m_black_border;
|
||||
|
||||
ScalableFont* m_fallback_font;
|
||||
float m_fallback_font_scale;
|
||||
int m_fallback_kerning_width;
|
||||
|
||||
//! constructor
|
||||
ScalableFont(gui::IGUIEnvironment *env, const io::path& filename)
|
||||
: Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
|
||||
MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
|
||||
|
@ -192,12 +192,12 @@ public:
|
|||
#ifdef _DEBUG
|
||||
setDebugName("ScalableFont");
|
||||
#endif
|
||||
|
||||
m_fallback_font = NULL;
|
||||
|
||||
m_fallback_font = NULL;
|
||||
m_fallback_kerning_width = 0;
|
||||
m_fallback_font_scale = 1.0f;
|
||||
m_scale = 0.37f;
|
||||
m_black_border = false;
|
||||
m_fallback_font_scale = 1.0f;
|
||||
m_scale = 0.37f;
|
||||
m_black_border = false;
|
||||
|
||||
if (Environment)
|
||||
{
|
||||
|
@ -213,7 +213,7 @@ public:
|
|||
Driver->grab();
|
||||
|
||||
setInvisibleCharacters ( L" " );
|
||||
|
||||
|
||||
io::IXMLReader* reader = env->getFileSystem()->createXMLReader(filename.c_str());
|
||||
if (reader)
|
||||
{
|
||||
|
@ -223,21 +223,23 @@ public:
|
|||
assert(Areas.size() > 0);
|
||||
}
|
||||
|
||||
//! destructor
|
||||
virtual ~ScalableFont()
|
||||
//! destructor
|
||||
virtual ~ScalableFont()
|
||||
{
|
||||
if (Driver) Driver->drop();
|
||||
if (SpriteBank) SpriteBank->drop();
|
||||
if (Driver)
|
||||
Driver->drop();
|
||||
if (SpriteBank)
|
||||
SpriteBank->drop();
|
||||
}
|
||||
|
||||
//! loads a font from an XML file
|
||||
bool load(io::IXMLReader* xml)
|
||||
//! loads a font from an XML file
|
||||
bool load(io::IXMLReader* xml)
|
||||
{
|
||||
if (!SpriteBank)
|
||||
return false;
|
||||
|
||||
doReadXmlFile(xml);
|
||||
|
||||
|
||||
// set bad character
|
||||
WrongCharacter = getAreaIDFromCharacter(L' ', NULL);
|
||||
|
||||
|
@ -246,32 +248,33 @@ public:
|
|||
for(wchar_t c='0'; c<='9'; c++)
|
||||
{
|
||||
SFontArea a = getAreaFromCharacter(c, NULL);
|
||||
if(a.overhang > m_max_digit_area.overhang ) m_max_digit_area.overhang = a.overhang;
|
||||
if(a.underhang > m_max_digit_area.underhang) m_max_digit_area.underhang = a.underhang;
|
||||
if(a.width > m_max_digit_area.width ) m_max_digit_area.width = a.width;
|
||||
if (a.overhang > m_max_digit_area.overhang ) m_max_digit_area.overhang = a.overhang;
|
||||
if (a.underhang > m_max_digit_area.underhang) m_max_digit_area.underhang = a.underhang;
|
||||
if (a.width > m_max_digit_area.width) m_max_digit_area.width = a.width;
|
||||
}
|
||||
m_max_digit_area.overhang = 0;m_max_digit_area.underhang=0;
|
||||
m_max_digit_area.overhang = 0;
|
||||
m_max_digit_area.underhang=0;
|
||||
return true;
|
||||
}
|
||||
//! draws an text and clips it to the specified rectangle if wanted
|
||||
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
|
||||
video::SColor color, bool hcenter=false,
|
||||
bool vcenter=false, const core::rect<s32>* clip=0)
|
||||
//! draws an text and clips it to the specified rectangle if wanted
|
||||
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
|
||||
video::SColor color, bool hcenter=false,
|
||||
bool vcenter=false, const core::rect<s32>* clip=0)
|
||||
{
|
||||
if (!Driver) return;
|
||||
|
||||
|
||||
core::position2d<s32> offset = position.UpperLeftCorner;
|
||||
core::dimension2d<s32> text_dimension;
|
||||
|
||||
// When we use the "tab" hack, disable right-alignment, it messes up everything
|
||||
bool has_tab = (text.findFirst(L'\t') != -1);
|
||||
// bool has_tab = (text.findFirst(L'\t') != -1);
|
||||
// ---- collect character locations
|
||||
const unsigned int text_size = text.size();
|
||||
core::array<s32> indices(text_size);
|
||||
core::array<s32> indices(text_size);
|
||||
core::array<core::position2di> offsets(text_size);
|
||||
core::array<bool> fallback;
|
||||
core::array<bool> fallback;
|
||||
fallback.set_used(text_size);
|
||||
|
||||
|
||||
for (u32 i = 0; i<text_size; i++)
|
||||
{
|
||||
wchar_t c = text[i];
|
||||
|
@ -282,11 +285,12 @@ public:
|
|||
offset.X = position.UpperLeftCorner.X + position.getWidth()/2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == L'\r' || // Windows breaks
|
||||
c == L'\n' ) // Unix breaks
|
||||
|
||||
if (c == L'\r' || // Windows breaks
|
||||
c == L'\n') // Unix breaks
|
||||
{
|
||||
if(c==L'\r' && text[i+1]==L'\n') c = text[++i];
|
||||
if (c==L'\r' && text[i+1]==L'\n')
|
||||
c = text[++i];
|
||||
offset.Y += (int)(MaxHeight*m_scale);
|
||||
offset.X = position.UpperLeftCorner.X;
|
||||
if (hcenter)
|
||||
|
@ -296,23 +300,23 @@ public:
|
|||
|
||||
bool use_fallback_font = false;
|
||||
const SFontArea &area = getAreaFromCharacter(c, &use_fallback_font);
|
||||
fallback[i] = use_fallback_font;
|
||||
offset.X += area.underhang;
|
||||
fallback[i] = use_fallback_font;
|
||||
offset.X += area.underhang;
|
||||
offsets.push_back(offset);
|
||||
// Invisible character. add something to the array anyway so that
|
||||
// indices from the various arrays remain in sync
|
||||
indices.push_back( Invisible.findFirst(c) < 0 ? area.spriteno
|
||||
: -1 );
|
||||
indices.push_back((Invisible.findFirst(c) < 0) ? (int)area.spriteno
|
||||
: -1);
|
||||
offset.X += getCharWidth(area, fallback[i]);
|
||||
} // for i<text_size
|
||||
|
||||
// ---- do the actual rendering
|
||||
const int indiceAmount = indices.size();
|
||||
core::array< gui::SGUISprite >& sprites = SpriteBank->getSprites();
|
||||
core::array< core::rect<s32> >& positions = SpriteBank->getPositions();
|
||||
const int indiceAmount = indices.size();
|
||||
core::array< gui::SGUISprite >& sprites = SpriteBank->getSprites();
|
||||
core::array< core::rect<s32> >& positions = SpriteBank->getPositions();
|
||||
core::array< gui::SGUISprite >* fallback_sprites;
|
||||
core::array< core::rect<s32> >* fallback_positions;
|
||||
if(m_fallback_font!=NULL)
|
||||
if (m_fallback_font!=NULL)
|
||||
{
|
||||
fallback_sprites = &m_fallback_font->SpriteBank->getSprites();
|
||||
fallback_positions = &m_fallback_font->SpriteBank->getPositions();
|
||||
|
@ -324,50 +328,51 @@ public:
|
|||
}
|
||||
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
const int spriteAmount = sprites.size();
|
||||
const int spriteAmount = sprites.size();
|
||||
for (int n=0; n<indiceAmount; n++)
|
||||
{
|
||||
const int spriteID = indices[n];
|
||||
if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount)) continue;
|
||||
if (indices[n] == -1) continue;
|
||||
|
||||
if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount))
|
||||
continue;
|
||||
if (indices[n] == -1)
|
||||
continue;
|
||||
|
||||
//assert(sprites[spriteID].Frames.size() > 0);
|
||||
|
||||
|
||||
const int texID = (fallback[n] ?
|
||||
(*fallback_sprites)[spriteID].Frames[0].textureNumber :
|
||||
sprites[spriteID].Frames[0].textureNumber);
|
||||
|
||||
(*fallback_sprites)[spriteID].Frames[0].textureNumber :
|
||||
sprites[spriteID].Frames[0].textureNumber);
|
||||
|
||||
core::rect<s32> source = (fallback[n] ?
|
||||
(*fallback_positions)[(*fallback_sprites)[spriteID].Frames[0].rectNumber] :
|
||||
positions[sprites[spriteID].Frames[0].rectNumber]);
|
||||
|
||||
(*fallback_positions)[(*fallback_sprites)[spriteID].Frames[0].rectNumber] :
|
||||
positions[sprites[spriteID].Frames[0].rectNumber]);
|
||||
|
||||
const TextureInfo& info = (fallback[n] ?
|
||||
(*(m_fallback_font->m_texture_files.find(texID))).second :
|
||||
(*(m_texture_files.find(texID))).second
|
||||
);
|
||||
(*(m_fallback_font->m_texture_files.find(texID))).second :
|
||||
(*(m_texture_files.find(texID))).second);
|
||||
float char_scale = info.m_scale;
|
||||
|
||||
core::dimension2d<s32> size = source.getSize();
|
||||
|
||||
|
||||
float scale = (fallback[n] ? m_scale*m_fallback_font_scale : m_scale);
|
||||
size.Width = (int)(size.Width * scale * char_scale);
|
||||
size.Height = (int)(size.Height * scale * char_scale);
|
||||
|
||||
|
||||
// align vertically if character is smaller
|
||||
int y_shift = (size.Height < MaxHeight*m_scale ? (int)((MaxHeight*m_scale - size.Height)/2.0f) : 0);
|
||||
|
||||
|
||||
core::rect<s32> dest(offsets[n] + core::position2di(0, y_shift), size);
|
||||
|
||||
|
||||
video::SColor colors[] = {color, color, color, color};
|
||||
|
||||
|
||||
video::ITexture* texture = (fallback[n] ?
|
||||
m_fallback_font->SpriteBank->getTexture(texID) :
|
||||
SpriteBank->getTexture(texID) );
|
||||
|
||||
|
||||
if (texture == NULL)
|
||||
{
|
||||
// perform lazy loading
|
||||
|
||||
|
||||
if (fallback[n])
|
||||
{
|
||||
m_fallback_font->lazyLoadTexture(texID);
|
||||
|
@ -378,19 +383,19 @@ public:
|
|||
lazyLoadTexture(texID);
|
||||
texture = SpriteBank->getTexture(texID);
|
||||
}
|
||||
|
||||
|
||||
if (texture == NULL)
|
||||
{
|
||||
continue; // no such character
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_black_border)
|
||||
{
|
||||
// draw black border
|
||||
video::SColor black(color.getAlpha(),0,0,0);
|
||||
video::SColor black_colors[] = {black, black, black, black};
|
||||
|
||||
|
||||
for (int x_delta=-2; x_delta<=2; x_delta++)
|
||||
{
|
||||
for (int y_delta=-2; y_delta<=2; y_delta++)
|
||||
|
@ -401,10 +406,10 @@ public:
|
|||
source,
|
||||
clip,
|
||||
black_colors, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fallback[n])
|
||||
{
|
||||
// draw text over
|
||||
|
@ -424,23 +429,23 @@ public:
|
|||
source,
|
||||
clip,
|
||||
colors, true);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! returns the dimension of a text
|
||||
virtual core::dimension2d<u32> getDimension(const wchar_t* text) const
|
||||
//! returns the dimension of a text
|
||||
virtual core::dimension2d<u32> getDimension(const wchar_t* text) const
|
||||
{
|
||||
assert(Areas.size() > 0);
|
||||
|
||||
|
||||
core::dimension2d<u32> dim(0, 0);
|
||||
core::dimension2d<u32> thisLine(0, (int)(MaxHeight*m_scale));
|
||||
|
||||
for (const wchar_t* p = text; *p; ++p)
|
||||
{
|
||||
if (*p == L'\r' || // Windows breaks
|
||||
*p == L'\n' ) // Unix breaks
|
||||
if (*p == L'\r' || // Windows breaks
|
||||
*p == L'\n') // Unix breaks
|
||||
{
|
||||
if (*p==L'\r' && p[1] == L'\n') // Windows breaks
|
||||
++p;
|
||||
|
@ -453,26 +458,26 @@ public:
|
|||
|
||||
bool fallback = false;
|
||||
const SFontArea &area = getAreaFromCharacter(*p, &fallback);
|
||||
|
||||
|
||||
thisLine.Width += area.underhang;
|
||||
|
||||
|
||||
thisLine.Width += getCharWidth(area, fallback);
|
||||
}
|
||||
|
||||
dim.Height += thisLine.Height;
|
||||
if (dim.Width < thisLine.Width) dim.Width = thisLine.Width;
|
||||
|
||||
// std::cout << "ScalableFont::getDimension returns : " << dim.Width << ", " << dim.Height << " --> ";
|
||||
// std::cout << "ScalableFont::getDimension returns : " << dim.Width << ", " << dim.Height << " --> ";
|
||||
|
||||
dim.Width = (int)(dim.Width + 0.9f); // round up
|
||||
dim.Height = (int)(dim.Height + 0.9f);
|
||||
|
||||
//std::cout << dim.Width << ", " << dim.Height << std::endl;
|
||||
|
||||
|
||||
return dim;
|
||||
}
|
||||
//! Calculates the index of the character in the text which is on a specific position.
|
||||
virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
|
||||
//! Calculates the index of the character in the text which is on a specific position.
|
||||
virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
|
||||
{
|
||||
s32 x = 0;
|
||||
s32 idx = 0;
|
||||
|
@ -491,20 +496,20 @@ public:
|
|||
|
||||
return -1;
|
||||
}
|
||||
//! Returns the type of this font
|
||||
virtual gui::EGUI_FONT_TYPE getType() const { return gui::EGFT_BITMAP; }
|
||||
//! Returns the type of this font
|
||||
virtual gui::EGUI_FONT_TYPE getType() const { return gui::EGFT_BITMAP; }
|
||||
|
||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
||||
virtual void setKerningWidth (s32 kerning)
|
||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
||||
virtual void setKerningWidth (s32 kerning)
|
||||
{
|
||||
GlobalKerningWidth = kerning;
|
||||
}
|
||||
virtual void setKerningHeight (s32 kerning)
|
||||
virtual void setKerningHeight (s32 kerning)
|
||||
{
|
||||
GlobalKerningHeight = kerning;
|
||||
}
|
||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
||||
virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const
|
||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
||||
virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const
|
||||
{
|
||||
s32 ret = GlobalKerningWidth;
|
||||
|
||||
|
@ -520,67 +525,69 @@ public:
|
|||
|
||||
return ret;
|
||||
}
|
||||
virtual s32 getKerningHeight() const
|
||||
virtual s32 getKerningHeight() const
|
||||
{
|
||||
return GlobalKerningHeight;
|
||||
}
|
||||
|
||||
//! gets the sprite bank
|
||||
virtual gui::IGUISpriteBank* getSpriteBank() const
|
||||
//! gets the sprite bank
|
||||
virtual gui::IGUISpriteBank* getSpriteBank() const
|
||||
{
|
||||
return SpriteBank;
|
||||
}
|
||||
|
||||
//! returns the sprite number from a given character
|
||||
virtual u32 getSpriteNoFromChar(const wchar_t *c) const
|
||||
//! returns the sprite number from a given character
|
||||
virtual u32 getSpriteNoFromChar(const wchar_t *c) const
|
||||
{
|
||||
return Areas[getAreaIDFromCharacter(*c, NULL)].spriteno;
|
||||
}
|
||||
|
||||
virtual void setInvisibleCharacters( const wchar_t *s )
|
||||
virtual void setInvisibleCharacters( const wchar_t *s )
|
||||
{
|
||||
Invisible = s;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct SFontArea
|
||||
{
|
||||
SFontArea() : underhang(0), overhang(0), width(0), spriteno(0) {}
|
||||
s32 underhang;
|
||||
s32 overhang;
|
||||
s32 width;
|
||||
u32 spriteno;
|
||||
};
|
||||
|
||||
int getCharWidth(const SFontArea& area, const bool fallback) const
|
||||
struct SFontArea
|
||||
{
|
||||
core::array< gui::SGUISprite >& sprites = SpriteBank->getSprites();
|
||||
SFontArea() : underhang(0), overhang(0), width(0), spriteno(0) {}
|
||||
s32 underhang;
|
||||
s32 overhang;
|
||||
s32 width;
|
||||
u32 spriteno;
|
||||
};
|
||||
|
||||
int getCharWidth(const SFontArea& area, const bool fallback) const
|
||||
{
|
||||
core::array< gui::SGUISprite >& sprites = SpriteBank->getSprites();
|
||||
core::array< gui::SGUISprite >* fallback_sprites = (m_fallback_font != NULL ?
|
||||
&m_fallback_font->SpriteBank->getSprites() :
|
||||
NULL);
|
||||
|
||||
&m_fallback_font->SpriteBank->getSprites() :
|
||||
NULL);
|
||||
|
||||
const int texID = (fallback ?
|
||||
(*fallback_sprites)[area.spriteno].Frames[0].textureNumber :
|
||||
sprites[area.spriteno].Frames[0].textureNumber);
|
||||
|
||||
(*fallback_sprites)[area.spriteno].Frames[0].textureNumber :
|
||||
sprites[area.spriteno].Frames[0].textureNumber);
|
||||
|
||||
const TextureInfo& info = (fallback ?
|
||||
(*(m_fallback_font->m_texture_files.find(texID))).second :
|
||||
(*(m_texture_files.find(texID))).second
|
||||
);
|
||||
(*(m_fallback_font->m_texture_files.find(texID))).second :
|
||||
(*(m_texture_files.find(texID))).second);
|
||||
const float char_scale = info.m_scale;
|
||||
|
||||
|
||||
//std::cout << "area.spriteno=" << area.spriteno << ", char_scale=" << char_scale << std::endl;
|
||||
|
||||
if (fallback) return (int)(((area.width + area.overhang)*m_fallback_font_scale + m_fallback_kerning_width) * m_scale * char_scale);
|
||||
else return (int)((area.width + area.overhang + GlobalKerningWidth) * m_scale * char_scale);
|
||||
|
||||
if (fallback)
|
||||
return (int)(((area.width + area.overhang)*m_fallback_font_scale + m_fallback_kerning_width) * m_scale * char_scale);
|
||||
else
|
||||
return (int)((area.width + area.overhang + GlobalKerningWidth) * m_scale * char_scale);
|
||||
}
|
||||
s32 getAreaIDFromCharacter(const wchar_t c, bool* fallback_font) const
|
||||
{
|
||||
std::map<wchar_t, s32>::const_iterator n = CharacterMap.find(c);
|
||||
if (n != CharacterMap.end())
|
||||
{
|
||||
if (fallback_font != NULL) *fallback_font = false;
|
||||
if (fallback_font != NULL)
|
||||
*fallback_font = false;
|
||||
return (*n).second;
|
||||
}
|
||||
else if (m_fallback_font != NULL && fallback_font != NULL)
|
||||
|
@ -591,19 +598,20 @@ private:
|
|||
else
|
||||
{
|
||||
// std::cout << "The font does not have this character : <" << (int)c << ">" << std::endl;
|
||||
if (fallback_font != NULL) *fallback_font = false;
|
||||
if (fallback_font != NULL)
|
||||
*fallback_font = false;
|
||||
return WrongCharacter;
|
||||
}
|
||||
}
|
||||
const SFontArea &getAreaFromCharacter(const wchar_t c, bool* fallback_font) const
|
||||
const SFontArea &getAreaFromCharacter(const wchar_t c, bool* fallback_font) const
|
||||
{
|
||||
const int area_id = getAreaIDFromCharacter(c, fallback_font);
|
||||
const bool use_fallback_font = (fallback_font && *fallback_font);
|
||||
|
||||
const bool use_fallback_font = (fallback_font && *fallback_font);
|
||||
|
||||
// Note: fallback_font can be NULL
|
||||
return ( use_fallback_font ? m_fallback_font->Areas[area_id] : Areas[area_id]);
|
||||
} // getAreaFromCharacter
|
||||
void setMaxHeight()
|
||||
void setMaxHeight()
|
||||
{
|
||||
// FIXME: should consider per-texture scaling
|
||||
MaxHeight = 0;
|
||||
|
@ -618,18 +626,18 @@ private:
|
|||
MaxHeight = t;
|
||||
}
|
||||
}
|
||||
core::array<SFontArea> Areas;
|
||||
/** The maximum values of all digits, used in monospace_digits. */
|
||||
mutable SFontArea m_max_digit_area;
|
||||
std::map<wchar_t, s32> CharacterMap;
|
||||
video::IVideoDriver* Driver;
|
||||
gui::IGUISpriteBank* SpriteBank;
|
||||
gui::IGUIEnvironment* Environment;
|
||||
u32 WrongCharacter;
|
||||
s32 MaxHeight;
|
||||
s32 GlobalKerningWidth, GlobalKerningHeight;
|
||||
core::array<SFontArea> Areas;
|
||||
/** The maximum values of all digits, used in monospace_digits. */
|
||||
mutable SFontArea m_max_digit_area;
|
||||
std::map<wchar_t, s32> CharacterMap;
|
||||
video::IVideoDriver* Driver;
|
||||
gui::IGUISpriteBank* SpriteBank;
|
||||
gui::IGUIEnvironment* Environment;
|
||||
u32 WrongCharacter;
|
||||
s32 MaxHeight;
|
||||
s32 GlobalKerningWidth, GlobalKerningHeight;
|
||||
|
||||
core::stringw Invisible;
|
||||
core::stringw Invisible;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -655,12 +663,12 @@ static bool draw2DImage4c(video::E_DRIVER_TYPE type)
|
|||
|
||||
logTestString("Testing driver %ls\n", driver->getName());
|
||||
|
||||
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS,true);
|
||||
driver->setTextureCreationFlag(video::ETCF_OPTIMIZED_FOR_QUALITY,true);
|
||||
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS,true);
|
||||
driver->setTextureCreationFlag(video::ETCF_OPTIMIZED_FOR_QUALITY,true);
|
||||
|
||||
video::ITexture* images = driver->getTexture("../media/2ddemo.png");
|
||||
driver->makeColorKeyTexture(images, core::position2d<s32>(0,0));
|
||||
|
||||
|
||||
core::rect<s32> imp1(349,15,385,78);
|
||||
core::rect<s32> imp2(387,15,423,78);
|
||||
|
||||
|
@ -668,54 +676,54 @@ static bool draw2DImage4c(video::E_DRIVER_TYPE type)
|
|||
io::path cwd = device->getFileSystem()->getWorkingDirectory();
|
||||
device->getFileSystem()->changeWorkingDirectoryTo("media");
|
||||
|
||||
ScalableFont* font = new ScalableFont(device->getGUIEnvironment(), "title_font.xml");
|
||||
font->m_fallback_font_scale = 4.0f;
|
||||
font->m_fallback_kerning_width = 15;
|
||||
font->setKerningWidth(-18);
|
||||
font->m_black_border = true;
|
||||
ScalableFont* font = new ScalableFont(device->getGUIEnvironment(), "title_font.xml");
|
||||
font->m_fallback_font_scale = 4.0f;
|
||||
font->m_fallback_kerning_width = 15;
|
||||
font->setKerningWidth(-18);
|
||||
font->m_black_border = true;
|
||||
|
||||
/*
|
||||
Prepare a nicely filtering 2d render mode for special cases.
|
||||
*/
|
||||
driver->getMaterial2D().UseMipMaps = true;
|
||||
Prepare a nicely filtering 2d render mode for special cases.
|
||||
*/
|
||||
driver->getMaterial2D().UseMipMaps = true;
|
||||
driver->getMaterial2D().TextureLayer[0].BilinearFilter = true;
|
||||
|
||||
|
||||
{
|
||||
driver->beginScene(true, true, video::SColor(255,120,102,136));
|
||||
|
||||
driver->enableMaterial2D();
|
||||
|
||||
driver->enableMaterial2D();
|
||||
|
||||
// draw fire & dragons background world
|
||||
driver->draw2DImage(images, core::position2di(),
|
||||
core::rect<s32>(0,0,342,224), 0,
|
||||
video::SColor(255,255,255,255), true);
|
||||
|
||||
core::rect<s32>(0,0,342,224), 0,
|
||||
video::SColor(255,255,255,255), true);
|
||||
|
||||
// draw flying imp
|
||||
driver->draw2DImage(images, core::position2d<s32>(114,75),
|
||||
imp1, 0, video::SColor(255,255,255,255), true);
|
||||
|
||||
imp1, 0, video::SColor(255,255,255,255), true);
|
||||
|
||||
// draw second flying imp
|
||||
driver->draw2DImage(images, core::position2d<s32>(220,55),
|
||||
imp2, 0, video::SColor(255,255,255,255), true);
|
||||
|
||||
imp2, 0, video::SColor(255,255,255,255), true);
|
||||
|
||||
driver->draw2DImage(images, core::rect<s32>(10,10,108,48),
|
||||
core::rect<s32>(354,87,442,118));
|
||||
core::rect<s32>(354,87,442,118));
|
||||
|
||||
video::SColor colors[] = {0xff00ffff, 0xff00ffff, 0xffffff00, 0xffffff00};
|
||||
driver->draw2DImage(images, core::recti(10,50,108,88),
|
||||
core::recti(354,87,442,118), 0, colors, true);
|
||||
|
||||
font->draw( L"WXYZsSdDrRjJbB", core::rect<s32>(30,20,300,300),
|
||||
video::SColor(255,255,255,255) );
|
||||
|
||||
font->draw( L"WXYZsSdDrRjJbB", core::rect<s32>(30,20,300,300),
|
||||
video::SColor(255,255,255,255) );
|
||||
|
||||
driver->enableMaterial2D(false);
|
||||
|
||||
|
||||
driver->draw2DImage(images, core::recti(10,90,108,128),
|
||||
core::recti(354,87,442,118), 0, colors, true);
|
||||
|
||||
font->draw( L"WXYZsSdDrRjJbB", core::rect<s32>(30,60,300,400),
|
||||
video::SColor(255,255,255,255) );
|
||||
|
||||
font->draw( L"WXYZsSdDrRjJbB", core::rect<s32>(30,60,300,400),
|
||||
video::SColor(255,255,255,255) );
|
||||
|
||||
driver->endScene();
|
||||
}
|
||||
font->drop();
|
||||
|
@ -727,7 +735,7 @@ static bool draw2DImage4c(video::E_DRIVER_TYPE type)
|
|||
device->closeDevice();
|
||||
device->run();
|
||||
device->drop();
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// This test renders a 3d scene and a gui on top of it. The GUI is
|
||||
|
@ -821,7 +829,7 @@ static bool addBlend2d(video::E_DRIVER_TYPE type)
|
|||
device->closeDevice();
|
||||
device->run();
|
||||
device->drop();
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// This test renders 4 times the same image. Two via IGUIImage, two via draw2DImage
|
||||
|
@ -833,8 +841,8 @@ static bool moreFilterTests(video::E_DRIVER_TYPE type)
|
|||
if (!device)
|
||||
return true;
|
||||
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
gui::IGUIEnvironment* gui = device->getGUIEnvironment();
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
gui::IGUIEnvironment* gui = device->getGUIEnvironment();
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_BILINEAR_FILTER))
|
||||
{
|
||||
|
@ -848,41 +856,41 @@ static bool moreFilterTests(video::E_DRIVER_TYPE type)
|
|||
|
||||
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
|
||||
video::ITexture* tex = driver->getTexture("../media/irrlichtlogo.jpg");
|
||||
gui::IGUIImage* image = gui->addImage(core::recti(0,0,64,64));
|
||||
image->setScaleImage(true);
|
||||
image->setImage(tex);
|
||||
image->setUseAlphaChannel(true);
|
||||
gui::IGUIImage* image = gui->addImage(core::recti(0,0,64,64));
|
||||
image->setScaleImage(true);
|
||||
image->setImage(tex);
|
||||
image->setUseAlphaChannel(true);
|
||||
driver->getMaterial2D().TextureLayer[0].BilinearFilter=true;
|
||||
driver->getMaterial2D().TextureLayer[0].TrilinearFilter=true;
|
||||
|
||||
{
|
||||
driver->beginScene(true, true, irr::video::SColor(255,255,255,255));
|
||||
{
|
||||
driver->beginScene(true, true, irr::video::SColor(255,255,255,255));
|
||||
|
||||
// all three logos should be with filtering
|
||||
driver->enableMaterial2D();
|
||||
driver->enableMaterial2D();
|
||||
|
||||
driver->getMaterial2D().setTexture(0, 0);
|
||||
driver->draw2DImage(tex, irr::core::rect<irr::s32>(64, 64, 128, 128), irr::core::rect<irr::s32>(0, 0, 88, 31));
|
||||
driver->getMaterial2D().setTexture(0, 0);
|
||||
driver->draw2DImage(tex, irr::core::rect<irr::s32>(64, 64, 128, 128), irr::core::rect<irr::s32>(0, 0, 88, 31));
|
||||
|
||||
driver->getMaterial2D().setTexture(0, tex);
|
||||
driver->draw2DImage(tex, irr::core::rect<irr::s32>(64, 0, 128, 64), irr::core::rect<irr::s32>(0, 0, 88, 31));
|
||||
driver->draw2DImage(tex, irr::core::rect<irr::s32>(64, 0, 128, 64), irr::core::rect<irr::s32>(0, 0, 88, 31));
|
||||
|
||||
gui->drawAll();
|
||||
gui->drawAll();
|
||||
|
||||
// the next gui image should be without filter
|
||||
driver->enableMaterial2D(false);
|
||||
driver->enableMaterial2D(false);
|
||||
image->setRelativePosition(core::recti(0,64,64,128));
|
||||
gui->drawAll();
|
||||
gui->drawAll();
|
||||
|
||||
driver->endScene();
|
||||
}
|
||||
}
|
||||
|
||||
bool result = takeScreenshotAndCompareAgainstReference(driver, "-2dmatFilter.png");
|
||||
|
||||
device->closeDevice();
|
||||
device->run();
|
||||
device->drop();
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool twodmaterial()
|
||||
|
|
|
@ -5,49 +5,43 @@
|
|||
|
||||
using namespace irr;
|
||||
using namespace core;
|
||||
using namespace scene;
|
||||
using namespace video;
|
||||
using namespace io;
|
||||
using namespace gui;
|
||||
|
||||
namespace
|
||||
{
|
||||
// Tests MD2 animations.
|
||||
/** At the moment, this just verifies that the last frame of the animation produces the expected bitmap. */
|
||||
bool md2Animation(void)
|
||||
bool testLastFrame()
|
||||
{
|
||||
// Use EDT_BURNINGSVIDEO since it is not dependent on (e.g.) OpenGL driver versions.
|
||||
IrrlichtDevice *device = createDevice( EDT_BURNINGSVIDEO, dimension2d<u32>(160, 120), 32);
|
||||
assert(device);
|
||||
IrrlichtDevice *device = createDevice(video::EDT_BURNINGSVIDEO, dimension2d<u32>(160, 120), 32);
|
||||
if (!device)
|
||||
return false;
|
||||
|
||||
IVideoDriver* driver = device->getVideoDriver();
|
||||
ISceneManager * smgr = device->getSceneManager();
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
scene::ISceneManager * smgr = device->getSceneManager();
|
||||
|
||||
IAnimatedMesh* mesh = smgr->getMesh("../media/sydney.md2");
|
||||
IAnimatedMeshSceneNode* node;
|
||||
assert(mesh);
|
||||
scene::IAnimatedMesh* mesh = smgr->getMesh("../media/sydney.md2");
|
||||
|
||||
bool result = (mesh != 0);
|
||||
if(mesh)
|
||||
if (mesh)
|
||||
{
|
||||
node = smgr->addAnimatedMeshSceneNode(mesh);
|
||||
assert(node);
|
||||
scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
|
||||
|
||||
if(node)
|
||||
if (node)
|
||||
{
|
||||
node->setPosition(vector3df(20, 0, 30));
|
||||
node->setMaterialFlag(EMF_LIGHTING, false);
|
||||
node->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
node->setMaterialTexture(0, driver->getTexture("../media/sydney.bmp"));
|
||||
node->setLoopMode(false);
|
||||
|
||||
(void)smgr->addCameraSceneNode();
|
||||
|
||||
// Just jump to the last frame since that's all we're interested in.
|
||||
node->setMD2Animation(EMAT_DEATH_FALLBACK);
|
||||
node->setMD2Animation(scene::EMAT_DEATH_FALLBACK);
|
||||
node->setCurrentFrame((f32)(node->getEndFrame()));
|
||||
node->setAnimationSpeed(0);
|
||||
device->run();
|
||||
driver->beginScene(true, true, SColor(255, 255, 255, 0));
|
||||
driver->beginScene(true, true, video::SColor(255, 255, 255, 0));
|
||||
smgr->drawAll();
|
||||
driver->endScene();
|
||||
if (mesh->getBoundingBox() != mesh->getMesh(node->getEndFrame())->getBoundingBox())
|
||||
|
@ -79,3 +73,56 @@ bool md2Animation(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Tests MD2 normals.
|
||||
bool testNormals()
|
||||
{
|
||||
// Use EDT_BURNINGSVIDEO since it is not dependent on (e.g.) OpenGL driver versions.
|
||||
IrrlichtDevice *device = createDevice(video::EDT_BURNINGSVIDEO, dimension2d<u32>(160, 120), 32);
|
||||
if (!device)
|
||||
return false;
|
||||
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
scene::ISceneManager * smgr = device->getSceneManager();
|
||||
|
||||
scene::IAnimatedMesh* mesh = smgr->getMesh("../media/sydney.md2");
|
||||
|
||||
bool result = (mesh != 0);
|
||||
if (mesh)
|
||||
{
|
||||
scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
|
||||
if (node)
|
||||
{
|
||||
node->setPosition(vector3df(20, 0, 30));
|
||||
node->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
node->setDebugDataVisible(scene::EDS_NORMALS);
|
||||
node->setMaterialTexture(0, driver->getTexture("../media/sydney.bmp"));
|
||||
node->setLoopMode(false);
|
||||
|
||||
(void)smgr->addCameraSceneNode();
|
||||
|
||||
node->setMD2Animation(scene::EMAT_STAND);
|
||||
node->setAnimationSpeed(0);
|
||||
device->run();
|
||||
driver->beginScene(true, true, video::SColor(255, 255, 255, 0));
|
||||
smgr->drawAll();
|
||||
driver->endScene();
|
||||
}
|
||||
}
|
||||
|
||||
result &= takeScreenshotAndCompareAgainstReference(driver, "-md2Normals.png");
|
||||
device->closeDevice();
|
||||
device->run();
|
||||
device->drop();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// test md2 features
|
||||
bool md2Animation(void)
|
||||
{
|
||||
bool result = testLastFrame();
|
||||
result &= testNormals();
|
||||
return result;
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 6.3 KiB |
|
@ -41,7 +41,7 @@ bool testShots(video::E_DRIVER_TYPE type)
|
|||
smgr->drawAll();
|
||||
driver->endScene();
|
||||
|
||||
for (u32 i=0; i<video::ECF_UNKNOWN; ++i)
|
||||
for (s32 i=0; i<video::ECF_UNKNOWN; ++i)
|
||||
{
|
||||
video::IImage* img = driver->createScreenShot((video::ECOLOR_FORMAT)i);
|
||||
logTestString("Color Format %d %ssupported\n", i, (img && img->getColorFormat() == i)?"":"un");
|
||||
|
|
|
@ -10,41 +10,41 @@ namespace
|
|||
// test camera changes with terrain scene node recalculation
|
||||
bool terrainRecalc(void)
|
||||
{
|
||||
IrrlichtDevice *device =
|
||||
createDevice(video::EDT_BURNINGSVIDEO, dimension2du(160, 120), 32);
|
||||
IrrlichtDevice *device =
|
||||
createDevice(video::EDT_BURNINGSVIDEO, dimension2du(160, 120), 32);
|
||||
|
||||
if (!device)
|
||||
return true;
|
||||
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
scene::ISceneManager* smgr = device->getSceneManager();
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
scene::ISceneManager* smgr = device->getSceneManager();
|
||||
|
||||
scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode(
|
||||
"../media/terrain-heightmap.bmp");
|
||||
terrain->setScale(core::vector3df(40.f, .1f, 40.f));
|
||||
scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode(
|
||||
"../media/terrain-heightmap.bmp");
|
||||
terrain->setScale(core::vector3df(40.f, .1f, 40.f));
|
||||
|
||||
terrain->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
terrain->setMaterialTexture(0, driver->getTexture("../media/terrain-texture.jpg"));
|
||||
terrain->setDebugDataVisible(scene::EDS_FULL);
|
||||
terrain->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
terrain->setMaterialTexture(0, driver->getTexture("../media/terrain-texture.jpg"));
|
||||
terrain->setDebugDataVisible(scene::EDS_FULL);
|
||||
|
||||
scene::ICameraSceneNode* camera = smgr->addCameraSceneNode();
|
||||
scene::ICameraSceneNode* camera = smgr->addCameraSceneNode();
|
||||
|
||||
const core::vector3df center(terrain->getBoundingBox().getCenter());
|
||||
camera->setTarget(center);
|
||||
const core::vector3df center(terrain->getBoundingBox().getCenter());
|
||||
camera->setTarget(center);
|
||||
|
||||
// yes, Y is intentionally being set to X here
|
||||
const core::vector3df above (center.X, center.X, center.Z);
|
||||
camera->setPosition (above);
|
||||
// yes, Y is intentionally being set to X here
|
||||
const core::vector3df above (center.X, center.X, center.Z);
|
||||
camera->setPosition (above);
|
||||
camera->setUpVector(vector3df(1.f, 0.f, 0.f));
|
||||
camera->setFarValue(above.Y);
|
||||
camera->setFarValue(above.Y);
|
||||
|
||||
device->run();
|
||||
smgr->drawAll();
|
||||
device->run();
|
||||
smgr->drawAll();
|
||||
|
||||
|
||||
// This shouldn't cause a recalc
|
||||
camera->setUpVector(vector3df(1.f, 0.f, .01f).normalize());
|
||||
device->run();
|
||||
device->run();
|
||||
driver->beginScene(true, true, video::SColor(255,100,101,140));
|
||||
smgr->drawAll();
|
||||
driver->endScene();
|
||||
|
@ -58,7 +58,7 @@ bool terrainRecalc(void)
|
|||
|
||||
// This is big enough to cause a recalc
|
||||
camera->setUpVector(vector3df(1.f, 0.f, .1f).normalize());
|
||||
device->run();
|
||||
device->run();
|
||||
driver->beginScene(true, true, video::SColor(255,100,101,140));
|
||||
smgr->drawAll();
|
||||
driver->endScene();
|
||||
|
@ -72,7 +72,7 @@ bool terrainRecalc(void)
|
|||
device->closeDevice();
|
||||
device->run();
|
||||
device->drop();
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool terrainGaps()
|
||||
|
@ -114,7 +114,7 @@ bool terrainGaps()
|
|||
device->closeDevice();
|
||||
device->run();
|
||||
device->drop();
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -124,4 +124,5 @@ bool terrainSceneNode()
|
|||
bool result = terrainRecalc();
|
||||
result &= terrainGaps();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ inline bool compareQ(const core::vector3df& v, const core::vector3df& turn=core:
|
|||
return true;
|
||||
}
|
||||
|
||||
core::vector3df vals[] = {
|
||||
const core::vector3df vals[] = {
|
||||
core::vector3df(0.f, 0.f, 0.f),
|
||||
core::vector3df(0.f, 0.f, 24.04f),
|
||||
core::vector3df(0.f, 0.f, 71.f),
|
||||
|
@ -100,39 +100,52 @@ bool testEulerConversion()
|
|||
bool testRotationFromTo()
|
||||
{
|
||||
bool result = true;
|
||||
core::quaternion q1;
|
||||
core::matrix4 mat;
|
||||
core::quaternion q4(mat);
|
||||
core::quaternion q;
|
||||
|
||||
q4.rotationFromTo(core::vector3df(1.f,0.f,0.f), core::vector3df(1.f,0.f,0.f));
|
||||
if (q4 != q1)
|
||||
q.rotationFromTo(core::vector3df(1.f,0.f,0.f), core::vector3df(1.f,0.f,0.f));
|
||||
if (q != core::quaternion())
|
||||
{
|
||||
logTestString("Quaternion rotationFromTo method did not yield identity.\n");
|
||||
result = false;
|
||||
}
|
||||
|
||||
q1.set(0.f,0.f,core::PI);
|
||||
core::quaternion q2(0.f,core::PI,0.f);
|
||||
q4.rotationFromTo(core::vector3df(1.f,0.f,0.f), core::vector3df(-1.f,0.f,0.f));
|
||||
if ((q4 != q1)&&(q4 != q2))
|
||||
core::vector3df from(1.f,0.f,0.f);
|
||||
q.rotationFromTo(from, core::vector3df(-1.f,0.f,0.f));
|
||||
from=q*from;
|
||||
if (from != core::vector3df(-1.f,0.f,0.f))
|
||||
{
|
||||
logTestString("Quaternion rotationFromTo method did not yield x flip.\n");
|
||||
result = false;
|
||||
}
|
||||
q4.rotationFromTo(core::vector3df(10.f,20.f,30.f), core::vector3df(-10.f,-20.f,-30.f));
|
||||
if ((q4 != q1)&&(q4 != q2))
|
||||
|
||||
from.set(1.f,2.f,3.f);
|
||||
q.rotationFromTo(from, core::vector3df(-1.f,-2.f,-3.f));
|
||||
from=q*from;
|
||||
if (from != core::vector3df(-1.f,-2.f,-3.f))
|
||||
{
|
||||
logTestString("Quaternion rotationFromTo method did not yield x flip for non-axis.\n");
|
||||
result = false;
|
||||
}
|
||||
|
||||
q1.set(0.f,0.f,core::PI/2);
|
||||
q4.rotationFromTo(core::vector3df(1.f,0.f,0.f), core::vector3df(0.f,1.f,0.f));
|
||||
if (!q4.equals(q1))
|
||||
from.set(1.f,0.f,0.f);
|
||||
q.rotationFromTo(from, core::vector3df(0.f,1.f,0.f));
|
||||
from=q*from;
|
||||
if (from != core::vector3df(0.f,1.f,0.f))
|
||||
{
|
||||
logTestString("Quaternion rotationFromTo method did not yield 90 degree rotation.\n");
|
||||
result = false;
|
||||
}
|
||||
|
||||
for (u32 i=1; i<sizeof(vals)/sizeof(vals[0])-1; ++i)
|
||||
{
|
||||
from.set(vals[i]).normalize();
|
||||
core::vector3df to(vals[i+1]);
|
||||
to.normalize();
|
||||
q.rotationFromTo(from, to);
|
||||
from = q*from;
|
||||
result &= (from.equals(to, 0.00012f));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
#include "irrlicht.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define TestWithAllDrivers(X, ...) \
|
||||
#define TestWithAllDrivers(X) \
|
||||
logTestString("Running test " #X "\n"); \
|
||||
for (u32 i=1; i<video::EDT_COUNT; ++i) \
|
||||
result &= X(video::E_DRIVER_TYPE(i), ##__VA_ARGS__)
|
||||
#define TestWithAllHWDrivers(X, ...) \
|
||||
result &= X(video::E_DRIVER_TYPE(i))
|
||||
#define TestWithAllHWDrivers(X) \
|
||||
logTestString("Running test " #X "\n"); \
|
||||
for (u32 i=video::EDT_DIRECT3D8; i<video::EDT_COUNT; ++i) \
|
||||
result &= X(video::E_DRIVER_TYPE(i), ##__VA_ARGS__)
|
||||
result &= X(video::E_DRIVER_TYPE(i))
|
||||
|
||||
//! Compare two files
|
||||
/** \param fileName1 The first file for comparison.
|
||||
|
|
|
@ -59,6 +59,164 @@ static bool testGetIntersectionWithLine(core::triangle3d<T>& triangle, const cor
|
|||
return allExpected;
|
||||
}
|
||||
|
||||
// modifying the same triangle in diverse ways get some more test-cases automatically
|
||||
template<class T>
|
||||
static bool stageModifications(int stage, triangle3d<T>& triangle)
|
||||
{
|
||||
switch ( stage )
|
||||
{
|
||||
case 0:
|
||||
return true;
|
||||
case 1:
|
||||
swap(triangle.pointB, triangle.pointC);
|
||||
return true;
|
||||
case 2:
|
||||
swap(triangle.pointA, triangle.pointC);
|
||||
return true;
|
||||
case 3:
|
||||
triangle.pointA.Z += 1000;
|
||||
triangle.pointB.Z += 1000;
|
||||
triangle.pointC.Z += 1000;
|
||||
return true;
|
||||
case 4:
|
||||
swap(triangle.pointA.Y, triangle.pointA.Z);
|
||||
swap(triangle.pointB.Y, triangle.pointB.Z);
|
||||
swap(triangle.pointC.Y, triangle.pointC.Z);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void stageModifications(int stage, vector3d<T>& point)
|
||||
{
|
||||
switch ( stage )
|
||||
{
|
||||
case 3:
|
||||
point.Z += 1000;
|
||||
break;
|
||||
case 4:
|
||||
swap(point.Y, point.Z);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static bool isPointInside(triangle3d<T> triangleOrig)
|
||||
{
|
||||
bool allExpected=true;
|
||||
|
||||
array< vector3d<T> > pointsInside;
|
||||
pointsInside.push_back( vector3d<T>(0,0,0) );
|
||||
pointsInside.push_back( (triangleOrig.pointA + triangleOrig.pointB + triangleOrig.pointC) / 3 );
|
||||
pointsInside.push_back( (triangleOrig.pointA + triangleOrig.pointB)/2 + vector3d<T>(0,1,0) );
|
||||
pointsInside.push_back( (triangleOrig.pointA + triangleOrig.pointC)/2 + vector3d<T>(1,0,0) );
|
||||
pointsInside.push_back( (triangleOrig.pointB + triangleOrig.pointC)/2 - vector3d<T>(1,0,0) );
|
||||
|
||||
for (u32 stage=0; ; ++stage)
|
||||
{
|
||||
triangle3d<T> triangle = triangleOrig;
|
||||
if ( !stageModifications(stage, triangle) )
|
||||
break;
|
||||
|
||||
for ( u32 i=0; i < pointsInside.size(); ++i )
|
||||
{
|
||||
vector3d<T> point = pointsInside[i];
|
||||
stageModifications(stage, point);
|
||||
|
||||
allExpected &= triangle.isPointInside( point );
|
||||
if ( !allExpected )
|
||||
{
|
||||
logTestString("triangle3d::isPointInside pointsInside test failed in stage %d point %d\n", stage, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
allExpected &= triangle.isPointInsideFast( point );
|
||||
if ( !allExpected )
|
||||
{
|
||||
logTestString("triangle3d::isPointInsideFast pointsInside test failed in stage %d point %d\n", stage, i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array< vector3d<T> > pointsOutside;
|
||||
pointsOutside.push_back( triangleOrig.pointA - vector3d<T>(1,0,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointA - vector3d<T>(0,1,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointB + vector3d<T>(1,0,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointB - vector3d<T>(0,1,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointC - vector3d<T>(1,0,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointC + vector3d<T>(1,0,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointC + vector3d<T>(0,1,0) );
|
||||
pointsOutside.push_back( (triangleOrig.pointA + triangleOrig.pointB)/2 - vector3d<T>(0,1,0) );
|
||||
pointsOutside.push_back( (triangleOrig.pointA + triangleOrig.pointC)/2 - vector3d<T>(1,0,0) );
|
||||
pointsOutside.push_back( (triangleOrig.pointB + triangleOrig.pointC)/2 + vector3d<T>(1,0,0) );
|
||||
|
||||
for (u32 stage=0; ; ++stage)
|
||||
{
|
||||
triangle3d<T> triangle = triangleOrig;
|
||||
if ( !stageModifications(stage, triangle) )
|
||||
break;
|
||||
|
||||
for ( u32 i=0; i < pointsOutside.size(); ++i )
|
||||
{
|
||||
vector3d<T> point = pointsOutside[i];
|
||||
stageModifications(stage, point);
|
||||
|
||||
allExpected &= !triangle.isPointInside( point );
|
||||
if ( !allExpected )
|
||||
{
|
||||
logTestString("triangle3d::isPointInside pointsOutside test failed in stage %d point %d\n", stage, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
allExpected &= !triangle.isPointInsideFast( point );
|
||||
if ( !allExpected )
|
||||
{
|
||||
logTestString("triangle3d::isPointInsideFast pointsOutside test failed in stage %d point %d\n", stage, i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array< vector3d<T> > pointsBorder;
|
||||
pointsBorder.push_back( triangleOrig.pointA );
|
||||
pointsBorder.push_back( triangleOrig.pointB );
|
||||
pointsBorder.push_back( triangleOrig.pointC );
|
||||
pointsBorder.push_back( (triangleOrig.pointA + triangleOrig.pointB)/2 );
|
||||
pointsBorder.push_back( (triangleOrig.pointA + triangleOrig.pointC)/2 );
|
||||
pointsBorder.push_back( (triangleOrig.pointB + triangleOrig.pointC)/2 );
|
||||
|
||||
for (u32 stage=0; ; ++stage)
|
||||
{
|
||||
triangle3d<T> triangle = triangleOrig;
|
||||
if ( !stageModifications(stage, triangle) )
|
||||
break;
|
||||
|
||||
for ( u32 i=0; i < pointsBorder.size(); ++i )
|
||||
{
|
||||
vector3d<T> point = pointsBorder[i];
|
||||
stageModifications(stage, point);
|
||||
|
||||
allExpected &= triangle.isPointInside( point );
|
||||
if ( !allExpected )
|
||||
{
|
||||
logTestString("triangle3d::isPointInside pointsBorder test failed in stage %d point %d\n", stage, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* results for isPointInsideFast are mixed for border cases, but I guess that's fine.
|
||||
if ( triangle.isPointInsideFast( point ) )
|
||||
logTestString("+ triangle3d::isPointInsideFast pointsBorder stage %d point %d is INSIDE\n", stage, i);
|
||||
else
|
||||
logTestString("- triangle3d::isPointInsideFast pointsBorder stage %d point %d is NOT inside\n", stage, i);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
return allExpected;
|
||||
}
|
||||
|
||||
|
||||
// Test the functionality of triangle3d<T>
|
||||
/** Validation is done with asserts() against expected results. */
|
||||
|
@ -89,6 +247,29 @@ bool testTriangle3d(void)
|
|||
allExpected &= testGetIntersectionWithLine(triangle, ray);
|
||||
}
|
||||
|
||||
bool testEigen = triangle3di(vector3di(250, 0, 0), vector3di(0, 0, 500), vector3di(500, 0, 500)).isPointInside(vector3di(300,0,300));
|
||||
if ( !testEigen ) // test from Eigen from here: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=44372&p=254331#p254331
|
||||
logTestString("Test isPointInside fails with integers\n");
|
||||
allExpected &= testEigen;
|
||||
|
||||
logTestString("Test isPointInside with f32\n");
|
||||
{
|
||||
triangle3d<f32> t(vector3d<f32>(-1000,-1000,0), vector3d<f32>(1000,-1000,0), vector3d<f32>(0,1000,0));
|
||||
allExpected &= isPointInside(t);
|
||||
}
|
||||
|
||||
logTestString("Test isPointInside with f64\n");
|
||||
{
|
||||
triangle3d<f64> t(vector3d<f64>(-1000,-1000,0), vector3d<f64>(1000,-1000,0), vector3d<f64>(0,1000,0));
|
||||
allExpected &= isPointInside(t);
|
||||
}
|
||||
|
||||
logTestString("Test isPointInside with s32\n");
|
||||
{
|
||||
triangle3d<s32> t(vector3d<s32>(-1000,-1000,0), vector3d<s32>(1000,-1000,0), vector3d<s32>(0,1000,0));
|
||||
allExpected &= isPointInside(t);
|
||||
}
|
||||
|
||||
if(allExpected)
|
||||
logTestString("\nAll tests passed\n");
|
||||
else
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_layout_file>
|
||||
<ActiveTarget name="All" />
|
||||
<File name="main.cpp" open="0" top="0" tabpos="0">
|
||||
<Cursor position="1821" topLine="63" />
|
||||
<File name="main.cpp" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
|
||||
<Cursor1 position="363" topLine="6" />
|
||||
</File>
|
||||
</CodeBlocks_layout_file>
|
||||
|
|
Loading…
Reference in New Issue