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
|
||||
|
|
|
@ -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;
|
||||
|
|
185
include/irrMap.h
185
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,7 +185,6 @@ class map
|
|||
dec();
|
||||
}
|
||||
|
||||
|
||||
Node* operator->()
|
||||
{
|
||||
return getNode();
|
||||
|
@ -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. */
|
||||
|
|
|
@ -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 |
|
@ -17,7 +17,6 @@ namespace scene
|
|||
const s32 MD2_FRAME_SHIFT = 2;
|
||||
const f32 MD2_FRAME_SHIFT_RECIPROCAL = 1.f / (1 << MD2_FRAME_SHIFT);
|
||||
|
||||
|
||||
const s32 Q2_VERTEX_NORMAL_TABLE_SIZE = 162;
|
||||
|
||||
static const f32 Q2_VERTEX_NORMAL_TABLE[Q2_VERTEX_NORMAL_TABLE_SIZE][3] = {
|
||||
|
@ -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
|
||||
|
||||
|
@ -329,17 +328,22 @@ void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop,
|
|||
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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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,6 +700,9 @@ 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
|
||||
{
|
||||
if ( filename.empty() || directory.empty() )
|
||||
return filename;
|
||||
|
||||
io::path path1, file, ext;
|
||||
core::splitFilename(getAbsolutePath(filename), &path1, &file, &ext);
|
||||
io::path path2(getAbsolutePath(directory));
|
||||
|
@ -710,7 +713,34 @@ path CFileSystem::getRelativeFilename(const path& filename, const path& director
|
|||
core::list<io::path>::ConstIterator it1,it2;
|
||||
it1=list1.begin();
|
||||
it2=list2.begin();
|
||||
for (; i<list1.size() && i<list2.size() && (*it1==*it2); ++i)
|
||||
|
||||
#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;
|
||||
|
|
|
@ -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
|
||||
|
@ -1122,15 +1128,14 @@ void CGUIEditBox::breakText()
|
|||
lineBreak = false;
|
||||
|
||||
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 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)
|
||||
if (WordWrap && length + worldlgth + whitelgth > elWidth && line.size() > 0)
|
||||
{
|
||||
// break to next line
|
||||
length = worldlgth;
|
||||
|
@ -1149,8 +1154,9 @@ void CGUIEditBox::breakText()
|
|||
|
||||
word = L"";
|
||||
whitespace = L"";
|
||||
}
|
||||
|
||||
|
||||
if ( c )
|
||||
whitespace += c;
|
||||
|
||||
// compute line break
|
||||
|
@ -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 (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);
|
||||
if (flat)
|
||||
{
|
||||
// draw flat sunken pane
|
||||
|
||||
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
|
||||
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)
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -380,7 +393,10 @@ void CGUIStaticText::breakText()
|
|||
whitespace = L"";
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -36,6 +36,9 @@ namespace gui
|
|||
//! 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 another color for the text.
|
||||
virtual void setOverrideColor(video::SColor color);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -37,6 +38,7 @@ CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters& params)
|
|||
Logger->setLogLevel(CreationParams.LoggingLevel);
|
||||
|
||||
os::Printer::Logger = Logger;
|
||||
Randomizer = createDefaultRandomizer();
|
||||
|
||||
FileSystem = io::createFileSystem();
|
||||
core::stringc s = "Irrlicht Engine version ";
|
||||
|
@ -69,8 +71,12 @@ CIrrDeviceStub::~CIrrDeviceStub()
|
|||
if (Operator)
|
||||
Operator->drop();
|
||||
|
||||
if (Randomizer)
|
||||
Randomizer->drop();
|
||||
|
||||
CursorControl = 0;
|
||||
|
||||
if (Timer)
|
||||
Timer->drop();
|
||||
|
||||
if (Logger->drop())
|
||||
|
@ -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());
|
||||
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);
|
||||
|
||||
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());
|
||||
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());
|
||||
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();
|
||||
|
|
|
@ -226,8 +226,10 @@ public:
|
|||
//! 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
|
||||
|
@ -250,7 +252,8 @@ public:
|
|||
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
|
||||
|
@ -264,7 +267,7 @@ public:
|
|||
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);
|
||||
|
@ -286,7 +289,8 @@ public:
|
|||
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)
|
||||
|
@ -301,7 +305,7 @@ public:
|
|||
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
|
||||
indices.push_back((Invisible.findFirst(c) < 0) ? (int)area.spriteno
|
||||
: -1);
|
||||
offset.X += getCharWidth(area, fallback[i]);
|
||||
} // for i<text_size
|
||||
|
@ -328,8 +332,10 @@ public:
|
|||
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);
|
||||
|
||||
|
@ -343,8 +349,7 @@ public:
|
|||
|
||||
const TextureInfo& info = (fallback[n] ?
|
||||
(*(m_fallback_font->m_texture_files.find(texID))).second :
|
||||
(*(m_texture_files.find(texID))).second
|
||||
);
|
||||
(*(m_texture_files.find(texID))).second);
|
||||
float char_scale = info.m_scale;
|
||||
|
||||
core::dimension2d<s32> size = source.getSize();
|
||||
|
@ -566,21 +571,23 @@ private:
|
|||
|
||||
const TextureInfo& info = (fallback ?
|
||||
(*(m_fallback_font->m_texture_files.find(texID))).second :
|
||||
(*(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,7 +598,8 @@ 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
node = smgr->addAnimatedMeshSceneNode(mesh);
|
||||
assert(node);
|
||||
scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
|
||||
|
||||
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");
|
||||
|
|
|
@ -114,7 +114,7 @@ bool terrainGaps()
|
|||
device->closeDevice();
|
||||
device->run();
|
||||
device->drop();
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -125,3 +125,4 @@ bool terrainSceneNode()
|
|||
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