Resolve conflicts with master

This commit is contained in:
numzero 2023-03-25 10:42:11 +03:00
commit d97d1708d6
55 changed files with 474 additions and 7166 deletions

File diff suppressed because it is too large Load Diff

@ -87,8 +87,12 @@ int main(int argc, char *argv[])
const io::path mediaPath = getExampleMediaPath(); const io::path mediaPath = getExampleMediaPath();
scene::IAnimatedMesh* mesh = smgr->getMesh(mediaPath + "coolguy_opt.x"); auto mesh_file = device->getFileSystem()->createAndOpenFile(mediaPath + "coolguy_opt.x");
check(mesh_file, "mesh file loading");
scene::IAnimatedMesh* mesh = smgr->getMesh(mesh_file);
check(mesh, "mesh loading"); check(mesh, "mesh loading");
if (mesh_file)
mesh_file->drop();
if (mesh) if (mesh)
{ {
video::ITexture* tex = driver->getTexture(mediaPath + "cooltexture.png"); video::ITexture* tex = driver->getTexture(mediaPath + "cooltexture.png");

@ -75,18 +75,18 @@ namespace scene
CVertexBuffer(video::E_VERTEX_TYPE vertexType) : Vertices(0), CVertexBuffer(video::E_VERTEX_TYPE vertexType) : Vertices(0),
MappingHint(EHM_NEVER), ChangedID(1) MappingHint(EHM_NEVER), ChangedID(1)
{ {
setType(vertexType); CVertexBuffer::setType(vertexType);
} }
CVertexBuffer(const IVertexBuffer &VertexBufferCopy) : CVertexBuffer(const IVertexBuffer &VertexBufferCopy) :
Vertices(0), MappingHint(EHM_NEVER), Vertices(0), MappingHint(EHM_NEVER),
ChangedID(1) ChangedID(1)
{ {
setType(VertexBufferCopy.getType()); CVertexBuffer::setType(VertexBufferCopy.getType());
reallocate(VertexBufferCopy.size()); CVertexBuffer::reallocate(VertexBufferCopy.size());
for (u32 n=0;n<VertexBufferCopy.size();++n) for (u32 n=0;n<VertexBufferCopy.size();++n)
push_back(VertexBufferCopy[n]); CVertexBuffer::push_back(VertexBufferCopy[n]);
} }
virtual ~CVertexBuffer() virtual ~CVertexBuffer()
@ -97,6 +97,9 @@ namespace scene
void setType(video::E_VERTEX_TYPE vertexType) override void setType(video::E_VERTEX_TYPE vertexType) override
{ {
if ( Vertices && Vertices->getType() == vertexType )
return;
IVertexList *NewVertices=0; IVertexList *NewVertices=0;
switch (vertexType) switch (vertexType)

@ -25,10 +25,6 @@ namespace irr
/** This device uses Apple's Cocoa API and works in Mac OSX 10.2 and above. */ /** This device uses Apple's Cocoa API and works in Mac OSX 10.2 and above. */
EIDT_OSX, EIDT_OSX,
//! A device native to the iOS
/** This device should be used with the OpenGL-ES driver. */
EIDT_IOS,
//! A device which uses Simple DirectMedia Layer //! A device which uses Simple DirectMedia Layer
/** The SDL device works under all platforms supported by SDL but first must be compiled /** The SDL device works under all platforms supported by SDL but first must be compiled
in by setting the USE_SDL2 CMake option to ON */ in by setting the USE_SDL2 CMake option to ON */

@ -54,9 +54,9 @@ namespace gui
//! Sets text justification of the text area //! Sets text justification of the text area
/** \param horizontal: EGUIA_UPPERLEFT for left justified (default), /** \param horizontal: EGUIA_UPPERLEFT for left justified (default),
EGUIA_LOWEERRIGHT for right justified, or EGUIA_CENTER for centered text. EGUIA_LOWERRIGHT for right justified, or EGUIA_CENTER for centered text.
\param vertical: EGUIA_UPPERLEFT to align with top edge, \param vertical: EGUIA_UPPERLEFT to align with top edge,
EGUIA_LOWEERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */ EGUIA_LOWERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0; virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0;
//! Set the maximal number of rows for the selection listbox //! Set the maximal number of rows for the selection listbox

@ -433,7 +433,7 @@ public:
if (el) if (el)
{ {
// find the highest element number // find the highest element number
el->getNextElement(-1, true, IsTabGroup, first, closest, true); el->getNextElement(-1, true, IsTabGroup, first, closest, true, true);
if (first) if (first)
{ {
TabOrder = first->getTabOrder() + 1; TabOrder = first->getTabOrder() + 1;
@ -706,7 +706,7 @@ public:
} }
} }
// search within children // search within children
if ((*it)->getNextElement(startOrder, reverse, group, first, closest)) if ((*it)->getNextElement(startOrder, reverse, group, first, closest, includeInvisible, includeDisabled))
{ {
return true; return true;
} }

@ -88,9 +88,9 @@ namespace gui
//! Sets text justification mode //! Sets text justification mode
/** \param horizontal: EGUIA_UPPERLEFT for left justified (default), /** \param horizontal: EGUIA_UPPERLEFT for left justified (default),
EGUIA_LOWEERRIGHT for right justified, or EGUIA_CENTER for centered text. EGUIA_LOWERRIGHT for right justified, or EGUIA_CENTER for centered text.
\param vertical: EGUIA_UPPERLEFT to align with top edge (default), \param vertical: EGUIA_UPPERLEFT to align with top edge (default),
EGUIA_LOWEERRIGHT for bottom edge, or EGUIA_CENTER for centered text. */ EGUIA_LOWERRIGHT for bottom edge, or EGUIA_CENTER for centered text. */
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0; virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0;
//! Enables or disables word wrap for using the static text as multiline text control. //! Enables or disables word wrap for using the static text as multiline text control.

@ -26,12 +26,23 @@ public:
} }
//! Copies text to the clipboard //! Copies text to the clipboard
//! \param text: text in utf-8
virtual void copyToClipboard(const c8* text) const = 0; virtual void copyToClipboard(const c8* text) const = 0;
//! Copies text to the primary selection
//! This is a no-op on some platforms.
//! \param text: text in utf-8
virtual void copyToPrimarySelection(const c8* text) const = 0;
//! Get text from the clipboard //! Get text from the clipboard
/** \return Returns 0 if no string is in there. */ //! \return Returns 0 if no string is in there, otherwise an utf-8 string.
virtual const c8* getTextFromClipboard() const = 0; virtual const c8* getTextFromClipboard() const = 0;
//! Get text from the primary selection
//! This is a no-op on some platforms.
//! \return Returns 0 if no string is in there, otherwise an utf-8 string.
virtual const c8* getTextFromPrimarySelection() const = 0;
//! Get the total and available system RAM //! Get the total and available system RAM
/** \param totalBytes: will contain the total system memory in Kilobytes (1024 B) /** \param totalBytes: will contain the total system memory in Kilobytes (1024 B)
\param availableBytes: will contain the available memory in Kilobytes (1024 B) \param availableBytes: will contain the available memory in Kilobytes (1024 B)

@ -318,20 +318,10 @@ namespace scene
* \endcode * \endcode
* If you would like to implement and add your own file format loader to Irrlicht, * If you would like to implement and add your own file format loader to Irrlicht,
* see addExternalMeshLoader(). * see addExternalMeshLoader().
* \param filename: Filename of the mesh to load. * \param file File handle of the mesh to load.
* \param alternativeCacheName: In case you want to have the mesh under another name in the cache (to create real copies)
* \return Null if failed, otherwise pointer to the mesh. * \return Null if failed, otherwise pointer to the mesh.
* This pointer should not be dropped. See IReferenceCounted::drop() for more information. * This pointer should not be dropped. See IReferenceCounted::drop() for more information.
**/ **/
virtual IAnimatedMesh* getMesh(const io::path& filename, const io::path& alternativeCacheName=io::path("")) = 0;
//! Get pointer to an animateable mesh. Loads the file if not loaded already.
/** Works just as getMesh(const char* filename). If you want to
remove a loaded mesh from the cache again, use removeMesh().
\param file File handle of the mesh to load.
\return NULL if failed and pointer to the mesh if successful.
This pointer should not be dropped. See
IReferenceCounted::drop() for more information. */
virtual IAnimatedMesh* getMesh(io::IReadFile* file) = 0; virtual IAnimatedMesh* getMesh(io::IReadFile* file) = 0;
//! Get interface to the mesh cache which is shared between all existing scene managers. //! Get interface to the mesh cache which is shared between all existing scene managers.
@ -345,16 +335,6 @@ namespace scene
This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ This pointer should not be dropped. See IReferenceCounted::drop() for more information. */
virtual video::IVideoDriver* getVideoDriver() = 0; virtual video::IVideoDriver* getVideoDriver() = 0;
//! Get the active GUIEnvironment
/** \return Pointer to the GUIEnvironment
This pointer should not be dropped. See IReferenceCounted::drop() for more information. */
virtual gui::IGUIEnvironment* getGUIEnvironment() = 0;
//! Get the active FileSystem
/** \return Pointer to the FileSystem
This pointer should not be dropped. See IReferenceCounted::drop() for more information. */
virtual io::IFileSystem* getFileSystem() = 0;
//! Adds a scene node for rendering an animated mesh model. //! Adds a scene node for rendering an animated mesh model.
/** \param mesh: Pointer to the loaded animated mesh to be displayed. /** \param mesh: Pointer to the loaded animated mesh to be displayed.
\param parent: Parent of the scene node. Can be NULL if no parent. \param parent: Parent of the scene node. Can be NULL if no parent.

@ -747,7 +747,7 @@ namespace video
\param texture Texture to be drawn. \param texture Texture to be drawn.
\param destPos Upper left 2d destination position where the \param destPos Upper left 2d destination position where the
image will be drawn. image will be drawn.
\param sourceRect Source rectangle in the image. \param sourceRect Source rectangle in the texture (based on it's OriginalSize)
\param clipRect Pointer to rectangle on the screen where the \param clipRect Pointer to rectangle on the screen where the
image is clipped to. image is clipped to.
If this pointer is NULL the image is not clipped. If this pointer is NULL the image is not clipped.
@ -768,7 +768,7 @@ namespace video
\param texture Texture to be drawn. \param texture Texture to be drawn.
\param positions Array of upper left 2d destinations where the \param positions Array of upper left 2d destinations where the
images will be drawn. images will be drawn.
\param sourceRects Source rectangles of the image. \param sourceRects Source rectangles of the texture (based on it's OriginalSize)
\param clipRect Pointer to rectangle on the screen where the \param clipRect Pointer to rectangle on the screen where the
images are clipped to. images are clipped to.
If this pointer is 0 then the image is not clipped. If this pointer is 0 then the image is not clipped.
@ -788,7 +788,7 @@ namespace video
/** Suggested and first implemented by zola. /** Suggested and first implemented by zola.
\param texture The texture to draw from \param texture The texture to draw from
\param destRect The rectangle to draw into \param destRect The rectangle to draw into
\param sourceRect The rectangle denoting a part of the texture \param sourceRect The rectangle denoting a part of the texture (based on it's OriginalSize)
\param clipRect Clips the destination rectangle (may be 0) \param clipRect Clips the destination rectangle (may be 0)
\param colors Array of 4 colors denoting the color values of \param colors Array of 4 colors denoting the color values of
the corners of the destRect the corners of the destRect
@ -1160,7 +1160,7 @@ namespace video
E_MATERIAL_TYPE enum or a value which was returned by E_MATERIAL_TYPE enum or a value which was returned by
addMaterialRenderer(). addMaterialRenderer().
\param name: New name of the material renderer. */ \param name: New name of the material renderer. */
virtual void setMaterialRendererName(s32 idx, const c8* name) =0; virtual void setMaterialRendererName(u32 idx, const c8* name) =0;
//! Swap the material renderers used for certain id's //! Swap the material renderers used for certain id's
/** Swap the IMaterialRenderers responsible for rendering specific /** Swap the IMaterialRenderers responsible for rendering specific

@ -44,7 +44,7 @@ const char* const sBuiltInVertexTypeNames[] =
struct S3DVertex struct S3DVertex
{ {
//! default constructor //! default constructor
S3DVertex() {} S3DVertex() : Color(0xffffffff) {}
//! constructor //! constructor
S3DVertex(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv) S3DVertex(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv)
@ -142,7 +142,7 @@ struct S3DVertex2TCoords : public S3DVertex
: S3DVertex(pos, normal, color, tcoords), TCoords2(tcoords) {} : S3DVertex(pos, normal, color, tcoords), TCoords2(tcoords) {}
//! constructor from S3DVertex //! constructor from S3DVertex
S3DVertex2TCoords(S3DVertex& o) : S3DVertex(o) {} S3DVertex2TCoords(const S3DVertex& o) : S3DVertex(o) {}
//! Second set of texture coordinates //! Second set of texture coordinates
core::vector2d<f32> TCoords2; core::vector2d<f32> TCoords2;
@ -150,21 +150,21 @@ struct S3DVertex2TCoords : public S3DVertex
//! Equality operator //! Equality operator
bool operator==(const S3DVertex2TCoords& other) const bool operator==(const S3DVertex2TCoords& other) const
{ {
return ((static_cast<S3DVertex>(*this)==other) && return ((static_cast<S3DVertex>(*this)==static_cast<const S3DVertex&>(other)) &&
(TCoords2 == other.TCoords2)); (TCoords2 == other.TCoords2));
} }
//! Inequality operator //! Inequality operator
bool operator!=(const S3DVertex2TCoords& other) const bool operator!=(const S3DVertex2TCoords& other) const
{ {
return ((static_cast<S3DVertex>(*this)!=other) || return ((static_cast<S3DVertex>(*this)!=static_cast<const S3DVertex&>(other)) ||
(TCoords2 != other.TCoords2)); (TCoords2 != other.TCoords2));
} }
bool operator<(const S3DVertex2TCoords& other) const bool operator<(const S3DVertex2TCoords& other) const
{ {
return ((static_cast<S3DVertex>(*this) < other) || return ((static_cast<S3DVertex>(*this) < other) ||
((static_cast<S3DVertex>(*this) == other) && (TCoords2 < other.TCoords2))); ((static_cast<S3DVertex>(*this) == static_cast<const S3DVertex&>(other)) && (TCoords2 < other.TCoords2)));
} }
static E_VERTEX_TYPE getType() static E_VERTEX_TYPE getType()
@ -214,6 +214,9 @@ struct S3DVertexTangents : public S3DVertex
const core::vector3df& binormal=core::vector3df()) const core::vector3df& binormal=core::vector3df())
: S3DVertex(pos, normal, c, tcoords), Tangent(tangent), Binormal(binormal) { } : S3DVertex(pos, normal, c, tcoords), Tangent(tangent), Binormal(binormal) { }
//! constructor from S3DVertex
S3DVertexTangents(const S3DVertex& o) : S3DVertex(o) {}
//! Tangent vector along the x-axis of the texture //! Tangent vector along the x-axis of the texture
core::vector3df Tangent; core::vector3df Tangent;
@ -222,14 +225,14 @@ struct S3DVertexTangents : public S3DVertex
bool operator==(const S3DVertexTangents& other) const bool operator==(const S3DVertexTangents& other) const
{ {
return ((static_cast<S3DVertex>(*this)==other) && return ((static_cast<S3DVertex>(*this)==static_cast<const S3DVertex&>(other)) &&
(Tangent == other.Tangent) && (Tangent == other.Tangent) &&
(Binormal == other.Binormal)); (Binormal == other.Binormal));
} }
bool operator!=(const S3DVertexTangents& other) const bool operator!=(const S3DVertexTangents& other) const
{ {
return ((static_cast<S3DVertex>(*this)!=other) || return ((static_cast<S3DVertex>(*this)!=static_cast<const S3DVertex&>(other)) ||
(Tangent != other.Tangent) || (Tangent != other.Tangent) ||
(Binormal != other.Binormal)); (Binormal != other.Binormal));
} }
@ -237,8 +240,8 @@ struct S3DVertexTangents : public S3DVertex
bool operator<(const S3DVertexTangents& other) const bool operator<(const S3DVertexTangents& other) const
{ {
return ((static_cast<S3DVertex>(*this) < other) || return ((static_cast<S3DVertex>(*this) < other) ||
((static_cast<S3DVertex>(*this) == other) && (Tangent < other.Tangent)) || ((static_cast<S3DVertex>(*this) == static_cast<const S3DVertex&>(other)) && (Tangent < other.Tangent)) ||
((static_cast<S3DVertex>(*this) == other) && (Tangent == other.Tangent) && (Binormal < other.Binormal))); ((static_cast<S3DVertex>(*this) == static_cast<const S3DVertex&>(other)) && (Tangent == other.Tangent) && (Binormal < other.Binormal)));
} }
static E_VERTEX_TYPE getType() static E_VERTEX_TYPE getType()

@ -79,21 +79,6 @@ struct SExposedVideoData
void* Window; void* Window;
}; };
struct SOpenGLiOS
{
//! The EAGLContext object.
void* Context;
//! The subview UIView object where the drawing happens.
void* View;
//! The UIViewController object.
void* ViewController;
//! The UIWindow object.
void* Window;
};
struct SOGLESAndroid struct SOGLESAndroid
{ {
//! The ANativeWindow object. //! The ANativeWindow object.
@ -107,7 +92,6 @@ struct SExposedVideoData
SOpenGLLinux OpenGLLinux; SOpenGLLinux OpenGLLinux;
SOpenGLOSX OpenGLOSX; SOpenGLOSX OpenGLOSX;
SOpenGLFB OpenGLFB; SOpenGLFB OpenGLFB;
SOpenGLiOS OpenGLiOS;
SOGLESAndroid OGLESAndroid; SOGLESAndroid OGLESAndroid;
}; };
}; };

@ -235,7 +235,6 @@ namespace irr
/** If this is set to a value other than 0, the Irrlicht Engine /** If this is set to a value other than 0, the Irrlicht Engine
will be created in an already existing window. will be created in an already existing window.
For Windows, set this to the HWND of the window you want. For Windows, set this to the HWND of the window you want.
For iOS, assign UIView to this variable.
The windowSize and FullScreen options will be ignored when using The windowSize and FullScreen options will be ignored when using
the WindowId parameter. Default this is set to 0. the WindowId parameter. Default this is set to 0.
To make Irrlicht run inside the custom window, you still will To make Irrlicht run inside the custom window, you still will

@ -143,7 +143,7 @@ namespace core
//! Set this matrix to the product of two matrices //! Set this matrix to the product of two matrices
/** Calculate b*a, no optimization used, /** Calculate b*a, no optimization used,
use it if you know you never have a identity matrix */ use it if you know you never have an identity matrix */
CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b ); CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
//! Multiply by another matrix. //! Multiply by another matrix.
@ -151,7 +151,8 @@ namespace core
CMatrix4<T> operator*(const CMatrix4<T>& other) const; CMatrix4<T> operator*(const CMatrix4<T>& other) const;
//! Multiply by another matrix. //! Multiply by another matrix.
/** Calculate and return other*this */ /** Like calling: (*this) = (*this) * other
*/
CMatrix4<T>& operator*=(const CMatrix4<T>& other); CMatrix4<T>& operator*=(const CMatrix4<T>& other);
//! Multiply by scalar. //! Multiply by scalar.
@ -187,14 +188,25 @@ namespace core
//! Make a rotation matrix from Euler angles. The 4th row and column are unmodified. //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
CMatrix4<T>& setRotationDegrees( const vector3d<T>& rotation ); CMatrix4<T>& setRotationDegrees( const vector3d<T>& rotation );
//! Get the rotation, as set by setRotation() when you already know the scale. //! Get the rotation, as set by setRotation() when you already know the scale used to create the matrix
/** If you already know the scale then this function is faster than the other getRotationDegrees overload. /** NOTE: The scale needs to be the correct one used to create this matrix.
NOTE: You will have the same end-rotation as used in setRotation, but it might not use the same axis values. You can _not_ use the result of getScale(), but have to save your scale
variable in another place (like ISceneNode does).
NOTE: No scale value can be 0 or the result is undefined.
NOTE: It does not necessarily return the *same* Euler angles as those set by setRotationDegrees(),
but the rotation will be equivalent, i.e. will have the same result when used to rotate a vector or node.
NOTE: It will (usually) give wrong results when further transformations have been added in the matrix (like shear).
WARNING: There have been troubles with this function over the years and we may still have missed some corner cases.
It's generally safer to keep the rotation and scale you used to create the matrix around and work with those.
*/ */
core::vector3d<T> getRotationDegrees(const vector3d<T>& scale) const; core::vector3d<T> getRotationDegrees(const vector3d<T>& scale) const;
//! Returns the rotation, as set by setRotation(). //! Returns the rotation, as set by setRotation().
/** NOTE: You will have the same end-rotation as used in setRotation, but it might not use the same axis values. /** NOTE: You will have the same end-rotation as used in setRotation, but it might not use the same axis values.
NOTE: This only works correct if no other matrix operations have been done on the inner 3x3 matrix besides
setting rotation (so no scale/shear). Thought it (probably) works as long as scale doesn't flip handedness.
NOTE: It does not necessarily return the *same* Euler angles as those set by setRotationDegrees(),
but the rotation will be equivalent, i.e. will have the same result when used to rotate a vector or node.
*/ */
core::vector3d<T> getRotationDegrees() const; core::vector3d<T> getRotationDegrees() const;
@ -828,11 +840,9 @@ namespace core
//! Returns the absolute values of the scales of the matrix. //! Returns the absolute values of the scales of the matrix.
/** /**
Note that this returns the absolute (positive) values unless only scale is set. Note: You only get back original values if the matrix only set the scale.
Unfortunately it does not appear to be possible to extract any original negative Otherwise the result is a scale you can use to normalize the matrix axes,
values. The best that we could do would be to arbitrarily make one scale but it's usually no longer what you did set with setScale.
negative if one or three of them were negative.
FIXME - return the original values.
*/ */
template <class T> template <class T>
inline vector3d<T> CMatrix4<T>::getScale() const inline vector3d<T> CMatrix4<T>::getScale() const
@ -895,33 +905,16 @@ namespace core
} }
//! Returns a rotation that is equivalent to that set by setRotationDegrees(). //! Returns a rotation which (mostly) works in combination with the given scale
/** This code was sent in by Chev. Note that it does not necessarily return /**
the *same* Euler angles as those set by setRotationDegrees(), but the rotation will This code was originally written by by Chev (assuming no scaling back then,
be equivalent, i.e. will have the same result when used to rotate a vector or node. we can be blamed for all problems added by regarding scale)
This code was originally written by by Chev.
*/ */
template <class T> template <class T>
inline core::vector3d<T> CMatrix4<T>::getRotationDegrees(const vector3d<T>& scale_) const inline core::vector3d<T> CMatrix4<T>::getRotationDegrees(const vector3d<T>& scale_) const
{ {
const CMatrix4<T> &mat = *this; const CMatrix4<T> &mat = *this;
core::vector3d<T> scale(scale_); const core::vector3d<f64> scale(core::iszero(scale_.X) ? FLT_MAX : scale_.X , core::iszero(scale_.Y) ? FLT_MAX : scale_.Y, core::iszero(scale_.Z) ? FLT_MAX : scale_.Z);
// we need to check for negative scale on to axes, which would bring up wrong results
if (scale.Y<0 && scale.Z<0)
{
scale.Y =-scale.Y;
scale.Z =-scale.Z;
}
else if (scale.X<0 && scale.Z<0)
{
scale.X =-scale.X;
scale.Z =-scale.Z;
}
else if (scale.X<0 && scale.Y<0)
{
scale.X =-scale.X;
scale.Y =-scale.Y;
}
const core::vector3d<f64> invScale(core::reciprocal(scale.X),core::reciprocal(scale.Y),core::reciprocal(scale.Z)); const core::vector3d<f64> invScale(core::reciprocal(scale.X),core::reciprocal(scale.Y),core::reciprocal(scale.Z));
f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0)); f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0));
@ -930,7 +923,7 @@ namespace core
f64 rotx, roty, X, Z; f64 rotx, roty, X, Z;
if (!core::iszero(C)) if (!core::iszero((T)C))
{ {
const f64 invC = core::reciprocal(C); const f64 invC = core::reciprocal(C);
rotx = mat[10] * invC * invScale.Z; rotx = mat[10] * invC * invScale.Z;
@ -957,14 +950,37 @@ namespace core
} }
//! Returns a rotation that is equivalent to that set by setRotationDegrees(). //! Returns a rotation that is equivalent to that set by setRotationDegrees().
/** This code was sent in by Chev. Note that it does not necessarily return
the *same* Euler angles as those set by setRotationDegrees(), but the rotation will
be equivalent, i.e. will have the same result when used to rotate a vector or node.
This code was originally written by by Chev. */
template <class T> template <class T>
inline core::vector3d<T> CMatrix4<T>::getRotationDegrees() const inline core::vector3d<T> CMatrix4<T>::getRotationDegrees() const
{ {
return getRotationDegrees(getScale()); // Note: Using getScale() here make it look like it could do matrix decomposition.
// It can't! It works (or should work) as long as rotation doesn't flip the handedness
// aka scale swapping 1 or 3 axes. (I think we could catch that as well by comparing
// crossproduct of first 2 axes to direction of third axis, but TODO)
// And maybe it should also offer the solution for the simple calculation
// without regarding scaling as Irrlicht did before 1.7
core::vector3d<T> scale(getScale());
// We assume the matrix uses rotations instead of negative scaling 2 axes.
// Otherwise it fails even for some simple cases, like rotating around
// 2 axes by 180° which getScale thinks is a negative scaling.
if (scale.Y<0 && scale.Z<0)
{
scale.Y =-scale.Y;
scale.Z =-scale.Z;
}
else if (scale.X<0 && scale.Z<0)
{
scale.X =-scale.X;
scale.Z =-scale.Z;
}
else if (scale.X<0 && scale.Y<0)
{
scale.X =-scale.X;
scale.Y =-scale.Y;
}
return getRotationDegrees(scale);
} }
@ -1156,10 +1172,10 @@ namespace core
template <class T> template <class T>
inline void CMatrix4<T>::rotateVect( vector3df& vect ) const inline void CMatrix4<T>::rotateVect( vector3df& vect ) const
{ {
vector3df tmp = vect; vector3d<T> tmp(static_cast<T>(vect.X), static_cast<T>(vect.Y), static_cast<T>(vect.Z));
vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8]; vect.X = static_cast<f32>(tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8]);
vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9]; vect.Y = static_cast<f32>(tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9]);
vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10]; vect.Z = static_cast<f32>(tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10]);
} }
//! An alternate transform vector method, writing into a second vector //! An alternate transform vector method, writing into a second vector
@ -1183,24 +1199,24 @@ namespace core
template <class T> template <class T>
inline void CMatrix4<T>::inverseRotateVect( vector3df& vect ) const inline void CMatrix4<T>::inverseRotateVect( vector3df& vect ) const
{ {
vector3df tmp = vect; vector3d<T> tmp(static_cast<T>(vect.X), static_cast<T>(vect.Y), static_cast<T>(vect.Z));
vect.X = tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2]; vect.X = static_cast<f32>(tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2]);
vect.Y = tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6]; vect.Y = static_cast<f32>(tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6]);
vect.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10]; vect.Z = static_cast<f32>(tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10]);
} }
template <class T> template <class T>
inline void CMatrix4<T>::transformVect( vector3df& vect) const inline void CMatrix4<T>::transformVect( vector3df& vect) const
{ {
f32 vector[3]; T vector[3];
vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12]; vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12];
vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13]; vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13];
vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14]; vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14];
vect.X = vector[0]; vect.X = static_cast<f32>(vector[0]);
vect.Y = vector[1]; vect.Y = static_cast<f32>(vector[1]);
vect.Z = vector[2]; vect.Z = static_cast<f32>(vector[2]);
} }
template <class T> template <class T>

@ -94,7 +94,7 @@ bool CB3DMeshWriter::writeMesh(io::IWriteFile* file, IMesh* const mesh, s32 flag
u32 numTexture = texs.size(); u32 numTexture = texs.size();
for (u32 i = 0; i < numTexture; i++) for (u32 i = 0; i < numTexture; i++)
{ {
file->write(texs[i].TextureName.c_str(), texs[i].TextureName.size() + 1); file->write(texs[i].TextureName.c_str(), (size_t)texs[i].TextureName.size() + 1);
file->write(&texs[i].Flags, 7*4); file->write(&texs[i].Flags, 7*4);
} }
@ -476,7 +476,7 @@ core::array<ISkinnedMesh::SJoint*> CB3DMeshWriter::getRootJoints(const ISkinnedM
return roots; return roots;
} }
u32 CB3DMeshWriter::getUVlayerCount(IMesh* mesh) u32 CB3DMeshWriter::getUVlayerCount(const IMesh* mesh)
{ {
const u32 numBeshBuffers = mesh->getMeshBufferCount(); const u32 numBeshBuffers = mesh->getMeshBufferCount();
for (u32 i = 0; i < numBeshBuffers; i++) for (u32 i = 0; i < numBeshBuffers; i++)

@ -37,7 +37,7 @@ private:
u32 getJointChunkSize(const ISkinnedMesh* mesh, ISkinnedMesh::SJoint* joint); u32 getJointChunkSize(const ISkinnedMesh* mesh, ISkinnedMesh::SJoint* joint);
core::array<ISkinnedMesh::SJoint*> getRootJoints(const ISkinnedMesh* mesh); core::array<ISkinnedMesh::SJoint*> getRootJoints(const ISkinnedMesh* mesh);
u32 getUVlayerCount(IMesh *mesh); u32 getUVlayerCount(const IMesh *mesh);
ISkinnedMesh* getSkinned (IMesh *mesh); ISkinnedMesh* getSkinned (IMesh *mesh);
inline void writeVector2(io::IWriteFile* file, const core::vector2df& vec); inline void writeVector2(io::IWriteFile* file, const core::vector2df& vec);

@ -141,7 +141,7 @@ void CBillboardSceneNode::updateMesh(const irr::scene::ICameraSceneNode* camera)
//! returns the axis aligned bounding box of this node //! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CBillboardSceneNode::getBoundingBox() const const core::aabbox3d<f32>& CBillboardSceneNode::getBoundingBox() const
{ {
// Really wrong when scaled. // Really wrong when scaled (as the node does not scale it's vertices - maybe it should?)
return BBoxSafe; return BBoxSafe;
} }
@ -162,9 +162,9 @@ void CBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
if (core::equals(Size.Height, 0.0f)) if (core::equals(Size.Height, 0.0f))
Size.Height = 1.0f; Size.Height = 1.0f;
const f32 avg = (Size.Width + Size.Height)/6; const f32 extent = 0.5f*sqrtf(Size.Width*Size.Width + Size.Height*Size.Height);
BBoxSafe.MinEdge.set(-avg,-avg,-avg); BBoxSafe.MinEdge.set(-extent,-extent,-extent);
BBoxSafe.MaxEdge.set(avg,avg,avg); BBoxSafe.MaxEdge.set(extent,extent,extent);
} }
@ -182,9 +182,9 @@ void CBillboardSceneNode::setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWi
TopEdgeWidth = 1.0f; TopEdgeWidth = 1.0f;
} }
const f32 avg = (core::max_(Size.Width,TopEdgeWidth) + Size.Height)/6; const f32 extent = 0.5f*sqrtf(Size.Width*Size.Width + Size.Height*Size.Height);
BBoxSafe.MinEdge.set(-avg,-avg,-avg); BBoxSafe.MinEdge.set(-extent,-extent,-extent);
BBoxSafe.MaxEdge.set(avg,avg,avg); BBoxSafe.MaxEdge.set(extent,extent,extent);
} }

@ -28,16 +28,16 @@ CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 i
// set default projection // set default projection
Fovy = core::PI / 2.5f; // Field of view, in radians. Fovy = core::PI / 2.5f; // Field of view, in radians.
Aspect = 4.0f / 3.0f; // Aspect ratio.
const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0; const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0;
if (d) if (d)
{ {
if ( d->getCurrentRenderTargetSize().Height )
Aspect = (f32)d->getCurrentRenderTargetSize().Width / Aspect = (f32)d->getCurrentRenderTargetSize().Width /
(f32)d->getCurrentRenderTargetSize().Height; (f32)d->getCurrentRenderTargetSize().Height;
HasD3DStyleProjectionMatrix = d->getDriverType() != video::EDT_OPENGL; HasD3DStyleProjectionMatrix = d->getDriverType() != video::EDT_OPENGL;
} }
else
Aspect = 4.0f / 3.0f; // Aspect ratio.
ViewArea.setFarNearDistance(ZFar - ZNear); ViewArea.setFarNearDistance(ZFar - ZNear);
recalculateProjectionMatrix(); recalculateProjectionMatrix();

@ -1,86 +0,0 @@
// Copyright (C) 2015 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in Irrlicht.h
#ifndef __C_EAGL_MANAGER_H_INCLUDED__
#define __C_EAGL_MANAGER_H_INCLUDED__
#ifdef _IRR_COMPILE_WITH_EAGL_MANAGER_
#include "SIrrCreationParameters.h"
#include "SExposedVideoData.h"
#include "IContextManager.h"
namespace irr
{
namespace video
{
// EAGL manager.
class CEAGLManager : public IContextManager
{
public:
//! Constructor.
CEAGLManager();
//! Destructor.
virtual ~CEAGLManager();
// Initialize EAGL.
/* This method checks if a view has CAEAGLLayer and grabs it if it does, anyway surface and context
aren't create. */
bool initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data);
// Terminate EAGL.
/* Terminate EAGL context. This method break both existed surface and context. */
void terminate();
// Create EAGL surface.
/* This method configure CAEAGLLayer. */
bool generateSurface();
// Destroy EAGL surface.
/* This method reset CAEAGLLayer states. */
void destroySurface();
// Create EAGL context.
/* This method create and activate EAGL context. */
bool generateContext();
// Destroy EAGL context.
/* This method destroy EAGL context. */
void destroyContext();
const SExposedVideoData& getContext() const;
bool activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero);
// Swap buffers.
bool swapBuffers();
private:
SIrrlichtCreationParameters Params;
SExposedVideoData Data;
bool Configured;
void* DataStorage;
struct SFrameBuffer
{
SFrameBuffer() : BufferID(0), ColorBuffer(0), DepthBuffer(0)
{
}
u32 BufferID;
u32 ColorBuffer;
u32 DepthBuffer;
};
SFrameBuffer FrameBuffer;
};
}
}
#endif
#endif

@ -1,273 +0,0 @@
// Copyright (C) 2015 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in Irrlicht.h
#include "CEAGLManager.h"
#ifdef _IRR_COMPILE_WITH_EAGL_MANAGER_
#include "irrString.h"
#include "os.h"
#import <UIKit/UIKit.h>
#import <OpenGLES/EAGL.h>
#if defined(_IRR_COMPILE_WITH_OGLES1_)
#include <OpenGLES/ES1/gl.h>
#include <OpenGLES/ES1/glext.h>
#elif defined(_IRR_COMPILE_WITH_OGLES2_)
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#endif
namespace irr
{
namespace video
{
struct SEAGLManagerDataStorage
{
SEAGLManagerDataStorage() : Layer(0), Context(0)
{
}
CAEAGLLayer* Layer;
EAGLContext* Context;
};
CEAGLManager::CEAGLManager() : IContextManager(), Configured(false), DataStorage(0)
{
#ifdef _DEBUG
setDebugName("CEAGLManager");
#endif
DataStorage = new SEAGLManagerDataStorage();
}
CEAGLManager::~CEAGLManager()
{
destroyContext();
destroySurface();
terminate();
delete static_cast<SEAGLManagerDataStorage*>(DataStorage);
}
bool CEAGLManager::initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data)
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
if (dataStorage->Layer != nil)
return true;
Params = params;
Data = data;
UIView* view = (__bridge UIView*)data.OpenGLiOS.View;
if (view == nil || ![[view layer] isKindOfClass:[CAEAGLLayer class]])
{
os::Printer::log("Could not get EAGL display.");
return false;
}
dataStorage->Layer = (CAEAGLLayer*)[view layer];
return true;
}
void CEAGLManager::terminate()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
[EAGLContext setCurrentContext:0];
destroySurface();
if (dataStorage->Layer != nil)
dataStorage->Layer = 0;
}
bool CEAGLManager::generateSurface()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
CAEAGLLayer* layer = dataStorage->Layer;
if (layer == nil)
return false;
if (Configured)
return true;
NSDictionary* attribs = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO],
kEAGLDrawablePropertyRetainedBacking,
(Params.Bits > 16) ? kEAGLColorFormatRGBA8 : kEAGLColorFormatRGB565,
kEAGLDrawablePropertyColorFormat,
nil];
[layer setOpaque:(Params.WithAlphaChannel) ? YES : NO];
[layer setDrawableProperties:attribs];
Configured = true;
return true;
}
void CEAGLManager::destroySurface()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
CAEAGLLayer* layer = dataStorage->Layer;
if (layer == nil)
return;
[layer setOpaque:NO];
[layer setDrawableProperties:nil];
Configured = false;
}
bool CEAGLManager::generateContext()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
if (dataStorage->Context != nil || !Configured)
return false;
EAGLRenderingAPI OpenGLESVersion = kEAGLRenderingAPIOpenGLES2;
switch (Params.DriverType)
{
case EDT_OGLES1:
OpenGLESVersion = kEAGLRenderingAPIOpenGLES1;
break;
case EDT_OGLES2:
OpenGLESVersion = kEAGLRenderingAPIOpenGLES2;
break;
default:
break;
}
dataStorage->Context = [[EAGLContext alloc] initWithAPI:OpenGLESVersion];
if (dataStorage->Context == nil)
{
os::Printer::log("Could not create EAGL context.", ELL_ERROR);
return false;
}
Data.OpenGLiOS.Context = (__bridge void*)dataStorage->Context;
os::Printer::log("EAGL context created with OpenGLESVersion: ", core::stringc(static_cast<int>(OpenGLESVersion)), ELL_DEBUG);
return true;
}
void CEAGLManager::destroyContext()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
[dataStorage->Context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:nil];
if (FrameBuffer.BufferID != 0)
{
glDeleteFramebuffersOES(1, &FrameBuffer.BufferID);
FrameBuffer.BufferID = 0;
}
if (FrameBuffer.ColorBuffer != 0)
{
glDeleteRenderbuffersOES(1, &FrameBuffer.ColorBuffer);
FrameBuffer.ColorBuffer = 0;
}
if (FrameBuffer.DepthBuffer != 0)
{
glDeleteRenderbuffersOES(1, &FrameBuffer.DepthBuffer);
FrameBuffer.DepthBuffer = 0;
}
[EAGLContext setCurrentContext:0];
if (dataStorage->Context != nil)
dataStorage->Context = 0;
Data.OpenGLiOS.Context = 0;
}
bool CEAGLManager::activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero)
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
EAGLContext* context = dataStorage->Context;
bool status = false;
if (context != nil)
{
status = ([EAGLContext currentContext] == context || [EAGLContext setCurrentContext:context]);
}
if (status)
{
if (FrameBuffer.ColorBuffer == 0)
{
glGenRenderbuffersOES(1, &FrameBuffer.ColorBuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, FrameBuffer.ColorBuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:dataStorage->Layer];
}
if (FrameBuffer.DepthBuffer == 0)
{
GLenum depth = (Params.ZBufferBits >= 24) ? GL_DEPTH_COMPONENT24_OES : GL_DEPTH_COMPONENT16_OES;
glGenRenderbuffersOES(1, &FrameBuffer.DepthBuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, FrameBuffer.DepthBuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depth, Params.WindowSize.Width, Params.WindowSize.Height);
}
if (FrameBuffer.BufferID == 0)
{
glGenFramebuffersOES(1, &FrameBuffer.BufferID);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, FrameBuffer.BufferID);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, FrameBuffer.ColorBuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, FrameBuffer.DepthBuffer);
}
glBindFramebufferOES(GL_FRAMEBUFFER_OES, FrameBuffer.BufferID);
}
else
{
os::Printer::log("Could not make EGL context current.");
}
return status;
}
const SExposedVideoData& CEAGLManager::getContext() const
{
return Data;
}
bool CEAGLManager::swapBuffers()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
EAGLContext* context = dataStorage->Context;
bool status = false;
if (context != nil && context == [EAGLContext currentContext])
{
glBindRenderbufferOES(GL_RENDERBUFFER_OES, FrameBuffer.ColorBuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
status = true;
}
return status;
}
}
}
#endif

@ -24,7 +24,7 @@
#include <direct.h> // for _chdir #include <direct.h> // for _chdir
#include <io.h> // for _access #include <io.h> // for _access
#include <tchar.h> #include <tchar.h>
#elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_) || defined(_IRR_IOS_PLATFORM_) || defined(_IRR_ANDROID_PLATFORM_)) #elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_) || defined(_IRR_ANDROID_PLATFORM_))
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

@ -1135,6 +1135,34 @@ bool CGUIEditBox::processMouse(const SEvent& event)
return true; return true;
} }
} }
case EMIE_MMOUSE_PRESSED_DOWN: {
if (!AbsoluteClippingRect.isPointInside(core::position2d<s32>(
event.MouseInput.X, event.MouseInput.Y)))
return false;
if (!Environment->hasFocus(this)) {
BlinkStartTime = os::Timer::getTime();
}
// move cursor and disable marking
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
MouseMarking = false;
setTextMarkers(CursorPos, CursorPos);
// paste from the primary selection
inputString([&] {
irr::core::stringw inserted_text;
if (!Operator)
return inserted_text;
const c8 *inserted_text_utf8 = Operator->getTextFromPrimarySelection();
if (!inserted_text_utf8)
return inserted_text;
core::multibyteToWString(inserted_text, inserted_text_utf8);
return inserted_text;
}());
return true;
}
default: default:
break; break;
} }
@ -1624,6 +1652,17 @@ void CGUIEditBox::setTextMarkers(s32 begin, s32 end)
{ {
MarkBegin = begin; MarkBegin = begin;
MarkEnd = end; MarkEnd = end;
if (!PasswordBox && Operator && MarkBegin != MarkEnd) {
// copy to primary selection
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
core::stringc s;
wStringToMultibyte(s, Text.subString(realmbgn, realmend - realmbgn));
Operator->copyToPrimarySelection(s.c_str());
}
sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED); sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED);
} }
} }

@ -22,10 +22,10 @@ namespace gui
CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool clip, s32 id, core::rect<s32> rectangle, bool clip,
bool drawBack, bool moveOverSelect) bool drawBack, bool moveOverSelect)
: IGUIListBox(environment, parent, id, rectangle), Selected(-1), : IGUIListBox(environment, parent, id, rectangle), Selected(-1), HoverSelected(-1),
ItemHeight(0),ItemHeightOverride(0), ItemHeight(0),ItemHeightOverride(0),
TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0), TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0),
ScrollBar(0), selectTime(0), LastKeyTime(0), Selecting(false), DrawBack(drawBack), ScrollBar(0), SelectTime(0), LastKeyTime(0), Selecting(false), DrawBack(drawBack),
MoveOverSelect(moveOverSelect), AutoScroll(true), HighlightWhenNotFocused(true) MoveOverSelect(moveOverSelect), AutoScroll(true), HighlightWhenNotFocused(true)
{ {
#ifdef _DEBUG #ifdef _DEBUG
@ -116,7 +116,7 @@ void CGUIListBox::removeItem(u32 id)
else if ((u32)Selected > id) else if ((u32)Selected > id)
{ {
Selected -= 1; Selected -= 1;
selectTime = os::Timer::getTime(); SelectTime = os::Timer::getTime();
} }
Items.erase(id); Items.erase(id);
@ -148,6 +148,7 @@ void CGUIListBox::clear()
Items.clear(); Items.clear();
ItemsIconWidth = 0; ItemsIconWidth = 0;
Selected = -1; Selected = -1;
HoverSelected = -1;
ScrollBar->setPos(0); ScrollBar->setPos(0);
@ -192,7 +193,7 @@ void CGUIListBox::recalculateItemHeight()
//! returns id of selected item. returns -1 if no item is selected. //! returns id of selected item. returns -1 if no item is selected.
s32 CGUIListBox::getSelected() const s32 CGUIListBox::getSelected() const
{ {
return Selected; return HoverSelected >= 0 ? HoverSelected : Selected;
} }
@ -204,7 +205,8 @@ void CGUIListBox::setSelected(s32 id)
else else
Selected = id; Selected = id;
selectTime = os::Timer::getTime(); HoverSelected = -1;
SelectTime = os::Timer::getTime();
recalculateScrollPos(); recalculateScrollPos();
} }
@ -454,14 +456,19 @@ void CGUIListBox::selectNew(s32 ypos, bool onlyHover)
u32 now = os::Timer::getTime(); u32 now = os::Timer::getTime();
s32 oldSelected = Selected; s32 oldSelected = Selected;
Selected = getItemAt(AbsoluteRect.UpperLeftCorner.X, ypos); HoverSelected = getItemAt(AbsoluteRect.UpperLeftCorner.X, ypos);
if (Selected<0 && !Items.empty()) if (HoverSelected<0 && !Items.empty())
Selected = 0; HoverSelected = 0;
if (!onlyHover)
{
Selected = HoverSelected;
HoverSelected = -1;
}
recalculateScrollPos(); recalculateScrollPos();
gui::EGUI_EVENT_TYPE eventType = (Selected == oldSelected && now < selectTime + 500) ? EGET_LISTBOX_SELECTED_AGAIN : EGET_LISTBOX_CHANGED; gui::EGUI_EVENT_TYPE eventType = (Selected == oldSelected && now < SelectTime + 500) ? EGET_LISTBOX_SELECTED_AGAIN : EGET_LISTBOX_CHANGED;
selectTime = now; SelectTime = now;
// post the news // post the news
if (Parent && !onlyHover) if (Parent && !onlyHover)
{ {
@ -527,13 +534,14 @@ void CGUIListBox::draw()
frameRect.LowerRightCorner.Y -= ScrollBar->getPos(); frameRect.LowerRightCorner.Y -= ScrollBar->getPos();
bool hl = (HighlightWhenNotFocused || Environment->hasFocus(this) || Environment->hasFocus(ScrollBar)); bool hl = (HighlightWhenNotFocused || Environment->hasFocus(this) || Environment->hasFocus(ScrollBar));
const irr::s32 selected = getSelected();
for (s32 i=0; i<(s32)Items.size(); ++i) for (s32 i=0; i<(s32)Items.size(); ++i)
{ {
if (frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y && if (frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y &&
frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y) frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y)
{ {
if (i == Selected && hl) if (i == selected && hl)
skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), frameRect, &clientClip); skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), frameRect, &clientClip);
core::rect<s32> textRect = frameRect; core::rect<s32> textRect = frameRect;
@ -547,24 +555,24 @@ void CGUIListBox::draw()
iconPos.Y += textRect.getHeight() / 2; iconPos.Y += textRect.getHeight() / 2;
iconPos.X += ItemsIconWidth/2; iconPos.X += ItemsIconWidth/2;
if ( i==Selected && hl ) if ( i==selected && hl )
{ {
IconBank->draw2DSprite( (u32)Items[i].Icon, iconPos, &clientClip, IconBank->draw2DSprite( (u32)Items[i].Icon, iconPos, &clientClip,
hasItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) ? hasItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) ?
getItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_ICON_HIGHLIGHT), getItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_ICON_HIGHLIGHT),
selectTime, os::Timer::getTime(), false, true); SelectTime, os::Timer::getTime(), false, true);
} }
else else
{ {
IconBank->draw2DSprite( (u32)Items[i].Icon, iconPos, &clientClip, IconBank->draw2DSprite( (u32)Items[i].Icon, iconPos, &clientClip,
hasItemOverrideColor(i, EGUI_LBC_ICON) ? getItemOverrideColor(i, EGUI_LBC_ICON) : getItemDefaultColor(EGUI_LBC_ICON), hasItemOverrideColor(i, EGUI_LBC_ICON) ? getItemOverrideColor(i, EGUI_LBC_ICON) : getItemDefaultColor(EGUI_LBC_ICON),
0 , (i==Selected) ? os::Timer::getTime() : 0, false, true); 0 , (i==selected) ? os::Timer::getTime() : 0, false, true);
} }
} }
textRect.UpperLeftCorner.X += ItemsIconWidth+3; textRect.UpperLeftCorner.X += ItemsIconWidth+3;
if ( i==Selected && hl ) if ( i==selected && hl )
{ {
Font->draw(Items[i].Text.c_str(), textRect, Font->draw(Items[i].Text.c_str(), textRect,
hasItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) ? hasItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) ?

@ -154,6 +154,7 @@ namespace gui
core::array< ListItem > Items; core::array< ListItem > Items;
s32 Selected; s32 Selected;
s32 HoverSelected; // When >= 0 we're in the middle of changing selection while mouse is pressed. We need to know so selected again isn't called too often.
s32 ItemHeight; s32 ItemHeight;
s32 ItemHeightOverride; s32 ItemHeightOverride;
s32 TotalItemHeight; s32 TotalItemHeight;
@ -161,7 +162,7 @@ namespace gui
gui::IGUIFont* Font; gui::IGUIFont* Font;
gui::IGUISpriteBank* IconBank; gui::IGUISpriteBank* IconBank;
gui::IGUIScrollBar* ScrollBar; gui::IGUIScrollBar* ScrollBar;
u32 selectTime; u32 SelectTime;
u32 LastKeyTime; u32 LastKeyTime;
core::stringw KeyBuffer; core::stringw KeyBuffer;
bool Selecting; bool Selecting;

@ -31,10 +31,7 @@ CGUISpriteBank::CGUISpriteBank(IGUIEnvironment* env) :
CGUISpriteBank::~CGUISpriteBank() CGUISpriteBank::~CGUISpriteBank()
{ {
// drop textures clear();
for (u32 i=0; i<Textures.size(); ++i)
if (Textures[i])
Textures[i]->drop();
// drop video driver // drop video driver
if (Driver) if (Driver)
@ -132,15 +129,38 @@ s32 CGUISpriteBank::addTextureAsSprite(video::ITexture* texture)
return Sprites.size() - 1; return Sprites.size() - 1;
} }
// get FrameNr for time. return true on exisiting frame
inline bool CGUISpriteBank::getFrameNr(u32& frame,u32 index, u32 time, bool loop) const
{
frame = 0;
if (index >= Sprites.size())
return false;
const SGUISprite& sprite = Sprites[index];
const u32 frameSize = sprite.Frames.size();
if (frameSize < 1)
return false;
if (sprite.frameTime)
{
u32 f = (time / sprite.frameTime);
if (loop)
frame = f % frameSize;
else
frame = (f >= frameSize) ? frameSize - 1 : f;
}
return true;
}
//! draws a sprite in 2d with scale and color //! draws a sprite in 2d with scale and color
void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos, void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos,
const core::rect<s32>* clip, const video::SColor& color, const core::rect<s32>* clip, const video::SColor& color,
u32 starttime, u32 currenttime, bool loop, bool center) u32 starttime, u32 currenttime, bool loop, bool center)
{ {
if (index >= Sprites.size() || Sprites[index].Frames.empty() ) u32 frame = 0;
if (!getFrameNr(frame, index, currenttime - starttime, loop))
return; return;
u32 frame = getFrameNr(index, currenttime - starttime, loop);
const video::ITexture* tex = getTexture(Sprites[index].Frames[frame].textureNumber); const video::ITexture* tex = getTexture(Sprites[index].Frames[frame].textureNumber);
if (!tex) if (!tex)
return; return;
@ -162,10 +182,10 @@ void CGUISpriteBank::draw2DSprite(u32 index, const core::rect<s32>& destRect,
const core::rect<s32>* clip, const video::SColor * const colors, const core::rect<s32>* clip, const video::SColor * const colors,
u32 timeTicks, bool loop) u32 timeTicks, bool loop)
{ {
if (index >= Sprites.size() || Sprites[index].Frames.empty() ) u32 frame = 0;
if (!getFrameNr(frame,index, timeTicks, loop))
return; return;
u32 frame = getFrameNr(index, timeTicks, loop);
const video::ITexture* tex = getTexture(Sprites[index].Frames[frame].textureNumber); const video::ITexture* tex = getTexture(Sprites[index].Frames[frame].textureNumber);
if (!tex) if (!tex)
return; return;
@ -200,21 +220,16 @@ void CGUISpriteBank::draw2DSpriteBatch( const core::array<u32>& indices,
{ {
const u32 index = indices[i]; const u32 index = indices[i];
if (index >= Sprites.size() || Sprites[index].Frames.empty() )
continue;
// work out frame number // work out frame number
u32 frame = 0; u32 frame = 0;
if (Sprites[index].frameTime) if (!getFrameNr(frame, index, currenttime - starttime, loop))
{ return;
u32 f = ((currenttime - starttime) / Sprites[index].frameTime);
if (loop)
frame = f % Sprites[index].Frames.size();
else
frame = (f >= Sprites[index].Frames.size()) ? Sprites[index].Frames.size()-1 : f;
}
const u32 texNum = Sprites[index].Frames[frame].textureNumber; const u32 texNum = Sprites[index].Frames[frame].textureNumber;
if (texNum >= drawBatches.size())
{
continue;
}
SDrawBatch& currentBatch = drawBatches[texNum]; SDrawBatch& currentBatch = drawBatches[texNum];
const u32 rn = Sprites[index].Frames[frame].rectNumber; const u32 rn = Sprites[index].Frames[frame].rectNumber;

@ -64,19 +64,7 @@ public:
protected: protected:
inline u32 getFrameNr(u32 index, u32 time, bool loop) const bool getFrameNr(u32& frameNr, u32 index, u32 time, bool loop) const;
{
u32 frame = 0;
if (Sprites[index].frameTime && Sprites[index].Frames.size() )
{
u32 f = (time / Sprites[index].frameTime);
if (loop)
frame = f % Sprites[index].Frames.size();
else
frame = (f >= Sprites[index].Frames.size()) ? Sprites[index].Frames.size()-1 : f;
}
return frame;
}
struct SDrawBatch struct SDrawBatch
{ {

@ -194,7 +194,7 @@ void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT fo
{ {
if (pitch==Pitch) if (pitch==Pitch)
{ {
memcpy(target, Data, height*pitch); memcpy(target, Data, (size_t)height*pitch);
return; return;
} }
else else

@ -80,14 +80,14 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
// Read the first few bytes of the PNG file // Read the first few bytes of the PNG file
if( file->read(buffer, 8) != 8 ) if( file->read(buffer, 8) != 8 )
{ {
os::Printer::log("LOAD PNG: can't read file\n", file->getFileName(), ELL_ERROR); os::Printer::log("LOAD PNG: can't read file (filesize < 8)", file->getFileName(), ELL_ERROR);
return 0; return 0;
} }
// Check if it really is a PNG file // Check if it really is a PNG file
if( png_sig_cmp(buffer, 0, 8) ) if( png_sig_cmp(buffer, 0, 8) )
{ {
os::Printer::log("LOAD PNG: not really a png\n", file->getFileName(), ELL_ERROR); os::Printer::log("LOAD PNG: not really a png (wrong signature)", file->getFileName(), ELL_ERROR);
return 0; return 0;
} }
@ -96,7 +96,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warn); NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warn);
if (!png_ptr) if (!png_ptr)
{ {
os::Printer::log("LOAD PNG: Internal PNG create read struct failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("LOAD PNG: Internal PNG create read struct failure", file->getFileName(), ELL_ERROR);
return 0; return 0;
} }
@ -104,7 +104,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
png_infop info_ptr = png_create_info_struct(png_ptr); png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) if (!info_ptr)
{ {
os::Printer::log("LOAD PNG: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("LOAD PNG: Internal PNG create info struct failure", file->getFileName(), ELL_ERROR);
png_destroy_read_struct(&png_ptr, NULL, NULL); png_destroy_read_struct(&png_ptr, NULL, NULL);
return 0; return 0;
} }
@ -212,7 +212,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
image = new CImage(ECF_R8G8B8, core::dimension2d<u32>(Width, Height)); image = new CImage(ECF_R8G8B8, core::dimension2d<u32>(Width, Height));
if (!image) if (!image)
{ {
os::Printer::log("LOAD PNG: Internal PNG create image struct failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("LOAD PNG: Internal PNG create image struct failure", file->getFileName(), ELL_ERROR);
png_destroy_read_struct(&png_ptr, NULL, NULL); png_destroy_read_struct(&png_ptr, NULL, NULL);
return 0; return 0;
} }
@ -221,7 +221,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
RowPointers = new png_bytep[Height]; RowPointers = new png_bytep[Height];
if (!RowPointers) if (!RowPointers)
{ {
os::Printer::log("LOAD PNG: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("LOAD PNG: Internal PNG create row pointers failure", file->getFileName(), ELL_ERROR);
png_destroy_read_struct(&png_ptr, NULL, NULL); png_destroy_read_struct(&png_ptr, NULL, NULL);
delete image; delete image;
return 0; return 0;

@ -106,7 +106,7 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const
if (!checkImageDimensions(header.ImageWidth, header.ImageHeight)) if (!checkImageDimensions(header.ImageWidth, header.ImageHeight))
{ {
os::Printer::log("Rejecting TGA with unreasonable size.", ELL_ERROR); os::Printer::log("Image dimensions too large in file", file->getFileName(), ELL_ERROR);
return 0; return 0;
} }

@ -69,7 +69,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param)
NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warning); NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warning);
if (!png_ptr) if (!png_ptr)
{ {
os::Printer::log("PNGWriter: Internal PNG create write struct failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("PNGWriter: Internal PNG create write struct failure", file->getFileName(), ELL_ERROR);
return false; return false;
} }
@ -77,7 +77,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param)
png_infop info_ptr = png_create_info_struct(png_ptr); png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) if (!info_ptr)
{ {
os::Printer::log("PNGWriter: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("PNGWriter: Internal PNG create info struct failure", file->getFileName(), ELL_ERROR);
png_destroy_write_struct(&png_ptr, NULL); png_destroy_write_struct(&png_ptr, NULL);
return false; return false;
} }
@ -126,7 +126,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param)
u8* tmpImage = new u8[image->getDimension().Height*lineWidth]; u8* tmpImage = new u8[image->getDimension().Height*lineWidth];
if (!tmpImage) if (!tmpImage)
{ {
os::Printer::log("PNGWriter: Internal PNG create image failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("PNGWriter: Internal PNG create image failure", file->getFileName(), ELL_ERROR);
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
return false; return false;
} }
@ -160,7 +160,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param)
u8** RowPointers = new png_bytep[image->getDimension().Height]; u8** RowPointers = new png_bytep[image->getDimension().Height];
if (!RowPointers) if (!RowPointers)
{ {
os::Printer::log("PNGWriter: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR); os::Printer::log("PNGWriter: Internal PNG create row pointers failure", file->getFileName(), ELL_ERROR);
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
delete [] tmpImage; delete [] tmpImage;
return false; return false;

@ -287,26 +287,26 @@ void IrrPrintXGrabError(int grabResult, const c8 * grabCommand )
{ {
if ( grabResult == GrabSuccess ) if ( grabResult == GrabSuccess )
{ {
// os::Printer::log(grabCommand, ": GrabSuccess", ELL_INFORMATION); // os::Printer::log(grabCommand, "GrabSuccess", ELL_INFORMATION);
return; return;
} }
switch ( grabResult ) switch ( grabResult )
{ {
case AlreadyGrabbed: case AlreadyGrabbed:
os::Printer::log(grabCommand, ": AlreadyGrabbed", ELL_WARNING); os::Printer::log(grabCommand, "AlreadyGrabbed", ELL_WARNING);
break; break;
case GrabNotViewable: case GrabNotViewable:
os::Printer::log(grabCommand, ": GrabNotViewable", ELL_WARNING); os::Printer::log(grabCommand, "GrabNotViewable", ELL_WARNING);
break; break;
case GrabFrozen: case GrabFrozen:
os::Printer::log(grabCommand, ": GrabFrozen", ELL_WARNING); os::Printer::log(grabCommand, "GrabFrozen", ELL_WARNING);
break; break;
case GrabInvalidTime: case GrabInvalidTime:
os::Printer::log(grabCommand, ": GrabInvalidTime", ELL_WARNING); os::Printer::log(grabCommand, "GrabInvalidTime", ELL_WARNING);
break; break;
default: default:
os::Printer::log(grabCommand, ": grab failed with unknown problem", ELL_WARNING); os::Printer::log(grabCommand, "grab failed with unknown problem", ELL_WARNING);
break; break;
} }
} }
@ -380,7 +380,7 @@ bool CIrrDeviceLinux::createWindow()
} }
#ifdef _DEBUG #ifdef _DEBUG
else else
os::Printer::log("Visual chosen: ", core::stringc(static_cast<u32>(VisualInfo->visualid)).c_str(), ELL_DEBUG); os::Printer::log("Visual chosen", core::stringc(static_cast<u32>(VisualInfo->visualid)).c_str(), ELL_DEBUG);
#endif #endif
// create color map // create color map
@ -1000,12 +1000,15 @@ bool CIrrDeviceLinux::run()
send_response(req->property); send_response(req->property);
}; };
if (req->selection != X_ATOM_CLIPBOARD || if ((req->selection != X_ATOM_CLIPBOARD &&
req->selection != XA_PRIMARY) ||
req->owner != XWindow) { req->owner != XWindow) {
// we are not the owner, refuse request // we are not the owner, refuse request
send_response_refuse(); send_response_refuse();
break; break;
} }
const core::stringc &text_buffer = req->selection == X_ATOM_CLIPBOARD ?
Clipboard : PrimarySelection;
// for debugging: // for debugging:
//~ { //~ {
@ -1026,8 +1029,8 @@ bool CIrrDeviceLinux::run()
req->target, X_ATOM_UTF8_STRING, req->target, X_ATOM_UTF8_STRING,
8, // format = 8-bit 8, // format = 8-bit
PropModeReplace, PropModeReplace,
(unsigned char *)Clipboard.c_str(), (unsigned char *)text_buffer.c_str(),
Clipboard.size()); text_buffer.size());
send_response(req->target); send_response(req->target);
break; break;
} }
@ -1052,8 +1055,8 @@ bool CIrrDeviceLinux::run()
set_property_and_notify( set_property_and_notify(
X_ATOM_UTF8_STRING, X_ATOM_UTF8_STRING,
8, 8,
Clipboard.c_str(), text_buffer.c_str(),
Clipboard.size() text_buffer.size()
); );
} else { } else {
@ -1676,47 +1679,49 @@ void CIrrDeviceLinux::pollJoysticks()
} }
#if defined(_IRR_COMPILE_WITH_X11_)
//! gets text from the clipboard //! gets text from the clipboard
//! \return Returns 0 if no string is in there, otherwise utf-8 text. //! \return Returns 0 if no string is in there, otherwise utf-8 text.
const c8 *CIrrDeviceLinux::getTextFromClipboard() const const c8 *CIrrDeviceLinux::getTextFromSelection(Atom selection, core::stringc &text_buffer) const
{ {
#if defined(_IRR_COMPILE_WITH_X11_) Window ownerWindow = XGetSelectionOwner(XDisplay, selection);
Window ownerWindow = XGetSelectionOwner(XDisplay, X_ATOM_CLIPBOARD);
if (ownerWindow == XWindow) { if (ownerWindow == XWindow) {
return Clipboard.c_str(); return text_buffer.c_str();
} }
Clipboard = ""; text_buffer = "";
if (ownerWindow == None) { if (ownerWindow == None) {
return Clipboard.c_str(); return text_buffer.c_str();
} }
// delete the property to be set beforehand // delete the property to be set beforehand
XDeleteProperty(XDisplay, XWindow, XA_PRIMARY); XDeleteProperty(XDisplay, XWindow, XA_PRIMARY);
XConvertSelection(XDisplay, X_ATOM_CLIPBOARD, X_ATOM_UTF8_STRING, XA_PRIMARY, XConvertSelection(XDisplay, selection, X_ATOM_UTF8_STRING, XA_PRIMARY,
XWindow, CurrentTime); XWindow, CurrentTime);
XFlush(XDisplay); XFlush(XDisplay);
// wait for event via a blocking call // wait for event via a blocking call
XEvent event_ret; XEvent event_ret;
std::pair<Window, Atom> args(XWindow, selection);
XIfEvent(XDisplay, &event_ret, [](Display *_display, XEvent *event, XPointer arg) { XIfEvent(XDisplay, &event_ret, [](Display *_display, XEvent *event, XPointer arg) {
auto p = reinterpret_cast<std::pair<Window, Atom> *>(arg);
return (Bool) (event->type == SelectionNotify && return (Bool) (event->type == SelectionNotify &&
event->xselection.requestor == *(Window *)arg && event->xselection.requestor == p->first &&
event->xselection.selection == X_ATOM_CLIPBOARD && event->xselection.selection == p->second &&
event->xselection.target == X_ATOM_UTF8_STRING); event->xselection.target == X_ATOM_UTF8_STRING);
}, (XPointer)&XWindow); }, (XPointer)&args);
_IRR_DEBUG_BREAK_IF(!(event_ret.type == SelectionNotify && _IRR_DEBUG_BREAK_IF(!(event_ret.type == SelectionNotify &&
event_ret.xselection.requestor == XWindow && event_ret.xselection.requestor == XWindow &&
event_ret.xselection.selection == X_ATOM_CLIPBOARD && event_ret.xselection.selection == selection &&
event_ret.xselection.target == X_ATOM_UTF8_STRING)); event_ret.xselection.target == X_ATOM_UTF8_STRING));
Atom property_set = event_ret.xselection.property; Atom property_set = event_ret.xselection.property;
if (event_ret.xselection.property == None) { if (event_ret.xselection.property == None) {
// request failed => empty string // request failed => empty string
return Clipboard.c_str(); return text_buffer.c_str();
} }
// check for data // check for data
@ -1743,15 +1748,15 @@ const c8 *CIrrDeviceLinux::getTextFromClipboard() const
// for debugging: // for debugging:
//~ { //~ {
//~ char *type_name = XGetAtomName(XDisplay, type); //~ char *type_name = XGetAtomName(XDisplay, type);
//~ fprintf(stderr, "CIrrDeviceLinux::getTextFromClipboard: actual type: %s (=%ld)\n", //~ fprintf(stderr, "CIrrDeviceLinux::getTextFromSelection: actual type: %s (=%ld)\n",
//~ type_name, type); //~ type_name, type);
//~ XFree(type_name); //~ XFree(type_name);
//~ } //~ }
if (type != X_ATOM_UTF8_STRING && type != X_ATOM_UTF8_MIME_TYPE) { if (type != X_ATOM_UTF8_STRING && type != X_ATOM_UTF8_MIME_TYPE) {
os::Printer::log("CIrrDeviceLinux::getTextFromClipboard: did not get utf-8 string", os::Printer::log("CIrrDeviceLinux::getTextFromSelection: did not get utf-8 string",
ELL_WARNING); ELL_WARNING);
return Clipboard.c_str(); return text_buffer.c_str();
} }
if (bytesLeft > 0) { if (bytesLeft > 0) {
@ -1760,20 +1765,49 @@ const c8 *CIrrDeviceLinux::getTextFromClipboard() const
bytesLeft, 0, AnyPropertyType, &type, &format, bytesLeft, 0, AnyPropertyType, &type, &format,
&numItems, &dummy, &data); &numItems, &dummy, &data);
if (result == Success) if (result == Success)
Clipboard = (irr::c8 *)data; text_buffer = (irr::c8 *)data;
XFree (data); XFree (data);
} }
// delete the property again, to inform the owner about the successful transfer // delete the property again, to inform the owner about the successful transfer
XDeleteProperty(XDisplay, XWindow, property_set); XDeleteProperty(XDisplay, XWindow, property_set);
return Clipboard.c_str(); return text_buffer.c_str();
}
#endif
//! gets text from the clipboard
//! \return Returns 0 if no string is in there, otherwise utf-8 text.
const c8 *CIrrDeviceLinux::getTextFromClipboard() const
{
#if defined(_IRR_COMPILE_WITH_X11_)
return getTextFromSelection(X_ATOM_CLIPBOARD, Clipboard);
#else #else
return nullptr; return nullptr;
#endif #endif
} }
//! gets text from the primary selection
//! \return Returns 0 if no string is in there, otherwise utf-8 text.
const c8 *CIrrDeviceLinux::getTextFromPrimarySelection() const
{
#if defined(_IRR_COMPILE_WITH_X11_)
return getTextFromSelection(XA_PRIMARY, PrimarySelection);
#else
return nullptr;
#endif
}
#if defined(_IRR_COMPILE_WITH_X11_)
bool CIrrDeviceLinux::becomeSelectionOwner(Atom selection) const
{
XSetSelectionOwner (XDisplay, selection, XWindow, CurrentTime);
XFlush (XDisplay);
Window owner = XGetSelectionOwner(XDisplay, selection);
return owner == XWindow;
}
#endif
//! copies text to the clipboard //! copies text to the clipboard
void CIrrDeviceLinux::copyToClipboard(const c8 *text) const void CIrrDeviceLinux::copyToClipboard(const c8 *text) const
{ {
@ -1781,22 +1815,30 @@ void CIrrDeviceLinux::copyToClipboard(const c8 *text) const
// Actually there is no clipboard on X but applications just say they own the clipboard and return text when asked. // Actually there is no clipboard on X but applications just say they own the clipboard and return text when asked.
// Which btw. also means that on X you lose clipboard content when closing applications. // Which btw. also means that on X you lose clipboard content when closing applications.
Clipboard = text; Clipboard = text;
XSetSelectionOwner (XDisplay, X_ATOM_CLIPBOARD, XWindow, CurrentTime); if (!becomeSelectionOwner(X_ATOM_CLIPBOARD)) {
XFlush (XDisplay);
Window owner = XGetSelectionOwner(XDisplay, X_ATOM_CLIPBOARD);
if (owner != XWindow) {
os::Printer::log("CIrrDeviceLinux::copyToClipboard: failed to set owner", ELL_WARNING); os::Printer::log("CIrrDeviceLinux::copyToClipboard: failed to set owner", ELL_WARNING);
} }
#endif #endif
} }
//! copies text to the primary selection
void CIrrDeviceLinux::copyToPrimarySelection(const c8 *text) const
{
#if defined(_IRR_COMPILE_WITH_X11_)
PrimarySelection = text;
if (!becomeSelectionOwner(XA_PRIMARY)) {
os::Printer::log("CIrrDeviceLinux::copyToPrimarySelection: failed to set owner", ELL_WARNING);
}
#endif
}
#ifdef _IRR_COMPILE_WITH_X11_ #ifdef _IRR_COMPILE_WITH_X11_
// return true if the passed event has the type passed in parameter arg // return true if the passed event has the type passed in parameter arg
Bool PredicateIsEventType(Display *display, XEvent *event, XPointer arg) Bool PredicateIsEventType(Display *display, XEvent *event, XPointer arg)
{ {
if ( event && event->type == *(int*)arg ) if ( event && event->type == *(int*)arg )
{ {
// os::Printer::log("remove event:", core::stringc((int)arg).c_str(), ELL_INFORMATION); // os::Printer::log("remove event", core::stringc((int)arg).c_str(), ELL_INFORMATION);
return True; return True;
} }
return False; return False;

@ -97,11 +97,20 @@ namespace irr
//! \return Returns 0 if no string is in there, otherwise utf-8 text. //! \return Returns 0 if no string is in there, otherwise utf-8 text.
virtual const c8 *getTextFromClipboard() const; virtual const c8 *getTextFromClipboard() const;
//! gets text from the primary selection
//! \return Returns 0 if no string is in there, otherwise utf-8 text.
virtual const c8 *getTextFromPrimarySelection() const;
//! copies text to the clipboard //! copies text to the clipboard
//! This sets the clipboard selection and _not_ the primary selection which you have on X on the middle mouse button. //! This sets the clipboard selection and _not_ the primary selection.
//! @param text The text in utf-8 //! @param text The text in utf-8
virtual void copyToClipboard(const c8 *text) const; virtual void copyToClipboard(const c8 *text) const;
//! copies text to the primary selection
//! This sets the primary selection which you have on X on the middle mouse button.
//! @param text The text in utf-8
virtual void copyToPrimarySelection(const c8 *text) const;
//! Remove all messages pending in the system message loop //! Remove all messages pending in the system message loop
void clearSystemMessages() override; void clearSystemMessages() override;
@ -141,6 +150,9 @@ namespace irr
bool createInputContext(); bool createInputContext();
void destroyInputContext(); void destroyInputContext();
EKEY_CODE getKeyCode(XEvent &event); EKEY_CODE getKeyCode(XEvent &event);
const c8 *getTextFromSelection(Atom selection, core::stringc &text_buffer) const;
bool becomeSelectionOwner(Atom selection) const;
#endif #endif
//! Implementation of the linux cursor control //! Implementation of the linux cursor control
@ -413,6 +425,7 @@ namespace irr
bool HasNetWM; bool HasNetWM;
// text is utf-8 // text is utf-8
mutable core::stringc Clipboard; mutable core::stringc Clipboard;
mutable core::stringc PrimarySelection;
#endif #endif
#if defined(_IRR_LINUX_X11_XINPUT2_) #if defined(_IRR_LINUX_X11_XINPUT2_)
int currentTouchedCount; int currentTouchedCount;

@ -243,7 +243,7 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param)
#endif #endif
if (SDL_Init(flags) < 0) if (SDL_Init(flags) < 0)
{ {
os::Printer::log( "Unable to initialize SDL!", SDL_GetError()); os::Printer::log("Unable to initialize SDL!", SDL_GetError());
Close = true; Close = true;
} }
else else

@ -92,7 +92,7 @@ void CIrrDeviceStub::createGUIAndScene()
GUIEnvironment = gui::createGUIEnvironment(FileSystem, VideoDriver, Operator); GUIEnvironment = gui::createGUIEnvironment(FileSystem, VideoDriver, Operator);
// create Scene manager // create Scene manager
SceneManager = scene::createSceneManager(VideoDriver, FileSystem, CursorControl, GUIEnvironment); SceneManager = scene::createSceneManager(VideoDriver, CursorControl);
setEventReceiver(UserReceiver); setEventReceiver(UserReceiver);
} }

@ -24,8 +24,7 @@ namespace irr
namespace scene namespace scene
{ {
ISceneManager* createSceneManager(video::IVideoDriver* driver, ISceneManager* createSceneManager(video::IVideoDriver* driver, gui::ICursorControl* cc);
io::IFileSystem* fs, gui::ICursorControl* cc, gui::IGUIEnvironment *gui);
} }
namespace io namespace io

@ -121,9 +121,9 @@ namespace irr
if (dev) if (dev)
{ {
dev->Unacquire(); dev->Unacquire();
}
dev->Release(); dev->Release();
} }
}
if (DirectInputDevice) if (DirectInputDevice)
DirectInputDevice->Release(); DirectInputDevice->Release();

@ -1,76 +0,0 @@
// Copyright (C) 2002-2008 Nikolaus Gebhardt
// Copyright (C) 2008 Redshift Software, Inc.
// Copyright (C) 2012-2015 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_IRR_DEVICE_IOS_H_INCLUDED__
#define __C_IRR_DEVICE_IOS_H_INCLUDED__
#ifdef _IRR_COMPILE_WITH_IOS_DEVICE_
#include "CIrrDeviceStub.h"
#include "IrrlichtDevice.h"
namespace irr
{
class CIrrDeviceiOS : public CIrrDeviceStub
{
public:
CIrrDeviceiOS(const SIrrlichtCreationParameters& params);
virtual ~CIrrDeviceiOS();
bool run() override;
void yield() override;
void sleep(u32 timeMs, bool pauseTimer) override;
void setWindowCaption(const wchar_t* text) override;
bool isWindowActive() const override;
bool isWindowFocused() const override;
bool isWindowMinimized() const override;
void closeDevice() override;
void setResizable(bool resize = false) override;
void minimizeWindow() override;
void maximizeWindow() override;
void restoreWindow() override;
core::position2di getWindowPosition() override;
bool activateAccelerometer(float updateInterval = 0.016666f) override;
bool deactivateAccelerometer() override;
bool isAccelerometerActive() override;
bool isAccelerometerAvailable() override;
bool activateGyroscope(float updateInterval = 0.016666f) override;
bool deactivateGyroscope() override;
bool isGyroscopeActive() override;
bool isGyroscopeAvailable() override;
bool activateDeviceMotion(float updateInterval = 0.016666f) override;
bool deactivateDeviceMotion() override;
bool isDeviceMotionActive() override;
bool isDeviceMotionAvailable() override;
E_DEVICE_TYPE getType() const override;
private:
void createWindow();
void createViewAndDriver();
void* DataStorage;
bool Close;
};
}
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
extern void irrlicht_main();
#endif
#endif
#endif

@ -1,819 +0,0 @@
// Copyright (C) 2002-2008 Nikolaus Gebhardt
// Copyright (C) 2008 Redshift Software, Inc.
// Copyright (C) 2012 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#import "CIrrDeviceiOS.h"
#ifdef _IRR_COMPILE_WITH_IOS_DEVICE_
#include "IFileSystem.h"
#include "CTimer.h"
#include "CEAGLManager.h"
#import <UIKit/UIKit.h>
#import <CoreMotion/CoreMotion.h>
/* Important information */
// The application state events and following methods: IrrlichtDevice::isWindowActive, IrrlichtDevice::isWindowFocused
// and IrrlichtDevice::isWindowMinimized works out of box only if you'll use built-in CIrrDelegateiOS,
// so _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_ must be enabled in this case. If you need a custom UIApplicationDelegate you must
// handle all application events yourself.
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
namespace irr
{
class CIrrDeviceiOS;
}
/* CIrrDelegateiOS */
@interface CIrrDelegateiOS : NSObject<UIApplicationDelegate>
- (void)setDevice:(irr::CIrrDeviceiOS*)device;
- (bool)isActive;
- (bool)hasFocus;
@property (strong, nonatomic) UIWindow* window;
@end
@implementation CIrrDelegateiOS
{
irr::CIrrDeviceiOS* Device;
bool Active;
bool Focus;
}
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)options
{
Device = nil;
Active = true;
Focus = false;
[self performSelectorOnMainThread:@selector(runIrrlicht) withObject:nil waitUntilDone:NO];
return YES;
}
- (void)applicationWillTerminate:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_WILL_TERMINATE;
Device->postEventFromUser(ev);
Device->closeDevice();
}
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_MEMORY_WARNING;
Device->postEventFromUser(ev);
}
}
- (void)applicationWillResignActive:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_WILL_PAUSE;
Device->postEventFromUser(ev);
}
Focus = false;
}
- (void)applicationDidEnterBackground:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_DID_PAUSE;
Device->postEventFromUser(ev);
}
Active = false;
}
- (void)applicationWillEnterForeground:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_WILL_RESUME;
Device->postEventFromUser(ev);
}
Active = true;
}
- (void)applicationDidBecomeActive:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_DID_RESUME;
Device->postEventFromUser(ev);
}
Focus = true;
}
- (void)runIrrlicht
{
irrlicht_main();
}
- (void)setDevice:(irr::CIrrDeviceiOS*)device
{
Device = device;
}
- (bool)isActive
{
return Active;
}
- (bool)hasFocus
{
return Focus;
}
@end
#endif
/* CIrrViewiOS */
@interface CIrrViewiOS : UIView
- (id)initWithFrame:(CGRect)frame forDevice:(irr::CIrrDeviceiOS*)device;
@end
@implementation CIrrViewiOS
{
irr::CIrrDeviceiOS* Device;
float Scale;
}
- (id)initWithFrame:(CGRect)frame forDevice:(irr::CIrrDeviceiOS*)device;
{
self = [super initWithFrame:frame];
if (self)
{
Device = device;
Scale = ([self respondsToSelector:@selector(setContentScaleFactor:)]) ? [[UIScreen mainScreen] scale] : 1.f;
}
return self;
}
- (BOOL)isMultipleTouchEnabled
{
return YES;
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_PRESSED_DOWN;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = (size_t)touch;
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x*Scale;
ev.TouchInput.Y = touchPoint.y*Scale;
Device->postEventFromUser(ev);
}
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_MOVED;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = (size_t)touch;
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x*Scale;
ev.TouchInput.Y = touchPoint.y*Scale;
Device->postEventFromUser(ev);
}
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_LEFT_UP;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = (size_t)touch;
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x*Scale;
ev.TouchInput.Y = touchPoint.y*Scale;
Device->postEventFromUser(ev);
}
}
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_LEFT_UP;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = (size_t)touch;
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x*Scale;
ev.TouchInput.Y = touchPoint.y*Scale;
Device->postEventFromUser(ev);
}
}
@end
/* CIrrViewEAGLiOS */
@interface CIrrViewEAGLiOS : CIrrViewiOS
@end
@implementation CIrrViewEAGLiOS
+ (Class)layerClass
{
return [CAEAGLLayer class];
}
@end
namespace irr
{
namespace video
{
IVideoDriver* createOGLES1Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, IContextManager* contextManager);
IVideoDriver* createOGLES2Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, IContextManager* contextManager);
}
struct SIrrDeviceiOSDataStorage
{
SIrrDeviceiOSDataStorage() : Window(0), ViewController(0), View(0), MotionManager(0), ReferenceAttitude(0)
{
MotionManager = [[CMMotionManager alloc] init];
}
UIWindow* Window;
UIViewController* ViewController;
CIrrViewiOS* View;
CMMotionManager* MotionManager;
CMAttitude* ReferenceAttitude;
};
CIrrDeviceiOS::CIrrDeviceiOS(const SIrrlichtCreationParameters& params) : CIrrDeviceStub(params), DataStorage(0), Close(false)
{
#ifdef _DEBUG
setDebugName("CIrrDeviceiOS");
#endif
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
[delegate setDevice:this];
#endif
DataStorage = new SIrrDeviceiOSDataStorage();
FileSystem->changeWorkingDirectoryTo([[[NSBundle mainBundle] resourcePath] UTF8String]);
createWindow();
createViewAndDriver();
if (!VideoDriver)
return;
createGUIAndScene();
}
CIrrDeviceiOS::~CIrrDeviceiOS()
{
deactivateDeviceMotion();
deactivateGyroscope();
deactivateAccelerometer();
delete static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
[delegate setDevice:nil];
#endif
}
bool CIrrDeviceiOS::run()
{
if (!Close)
{
const CFTimeInterval timeInSeconds = 0.000002;
s32 result = 0;
do
{
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeInSeconds, TRUE);
}
while (result == kCFRunLoopRunHandledSource);
os::Timer::tick();
//! Update events
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
//! Accelerometer
if (motionManager.isAccelerometerActive)
{
irr::SEvent ev;
ev.EventType = irr::EET_ACCELEROMETER_EVENT;
ev.AccelerometerEvent.X = motionManager.accelerometerData.acceleration.x;
ev.AccelerometerEvent.Y = motionManager.accelerometerData.acceleration.y;
ev.AccelerometerEvent.Z = motionManager.accelerometerData.acceleration.z;
postEventFromUser(ev);
}
//! Gyroscope
if (motionManager.isGyroActive)
{
irr::SEvent ev;
ev.EventType = irr::EET_GYROSCOPE_EVENT;
ev.GyroscopeEvent.X = motionManager.gyroData.rotationRate.x;
ev.GyroscopeEvent.Y = motionManager.gyroData.rotationRate.y;
ev.GyroscopeEvent.Z = motionManager.gyroData.rotationRate.z;
postEventFromUser(ev);
}
//! Device Motion
if (motionManager.isDeviceMotionActive)
{
CMAttitude* currentAttitude = motionManager.deviceMotion.attitude;
CMAttitude* referenceAttitude = dataStorage->ReferenceAttitude;
if (referenceAttitude != nil)
[currentAttitude multiplyByInverseOfAttitude: referenceAttitude];
else
referenceAttitude = motionManager.deviceMotion.attitude;
irr::SEvent ev;
ev.EventType = irr::EET_DEVICE_MOTION_EVENT;
ev.AccelerometerEvent.X = currentAttitude.roll;
ev.AccelerometerEvent.Y = currentAttitude.pitch;
ev.AccelerometerEvent.Z = currentAttitude.yaw;
postEventFromUser(ev);
}
}
return !Close;
}
void CIrrDeviceiOS::yield()
{
struct timespec ts = {0,0};
nanosleep(&ts, NULL);
}
void CIrrDeviceiOS::sleep(u32 timeMs, bool pauseTimer=false)
{
bool wasStopped = Timer ? Timer->isStopped() : true;
struct timespec ts;
ts.tv_sec = (time_t) (timeMs / 1000);
ts.tv_nsec = (long) (timeMs % 1000) * 1000000;
if (pauseTimer && !wasStopped)
Timer->stop();
nanosleep(&ts, NULL);
if (pauseTimer && !wasStopped)
Timer->start();
}
void CIrrDeviceiOS::setWindowCaption(const wchar_t* text)
{
}
bool CIrrDeviceiOS::isWindowActive() const
{
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
return [delegate isActive];
#else
return false;
#endif
}
bool CIrrDeviceiOS::isWindowFocused() const
{
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
return [delegate hasFocus];
#else
return false;
#endif
}
bool CIrrDeviceiOS::isWindowMinimized() const
{
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
return ![delegate isActive];
#else
return false;
#endif
}
void CIrrDeviceiOS::closeDevice()
{
CFRunLoopStop(CFRunLoopGetMain());
Close = true;
}
void CIrrDeviceiOS::setResizable(bool resize)
{
}
void CIrrDeviceiOS::minimizeWindow()
{
}
void CIrrDeviceiOS::maximizeWindow()
{
}
void CIrrDeviceiOS::restoreWindow()
{
}
core::position2di CIrrDeviceiOS::getWindowPosition()
{
return core::position2di(0, 0);
}
bool CIrrDeviceiOS::activateAccelerometer(float updateInterval)
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isAccelerometerAvailable)
{
if (!motionManager.isAccelerometerActive)
{
motionManager.accelerometerUpdateInterval = updateInterval;
[motionManager startAccelerometerUpdates];
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::deactivateAccelerometer()
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isAccelerometerAvailable)
{
if (motionManager.isAccelerometerActive)
[motionManager stopAccelerometerUpdates];
status = true;
}
return status;
}
bool CIrrDeviceiOS::isAccelerometerActive()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isAccelerometerActive);
}
bool CIrrDeviceiOS::isAccelerometerAvailable()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isAccelerometerAvailable);
}
bool CIrrDeviceiOS::activateGyroscope(float updateInterval)
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isGyroAvailable)
{
if (!motionManager.isGyroActive)
{
motionManager.gyroUpdateInterval = updateInterval;
[motionManager startGyroUpdates];
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::deactivateGyroscope()
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isGyroAvailable)
{
if (motionManager.isGyroActive)
[motionManager stopGyroUpdates];
status = true;
}
return status;
}
bool CIrrDeviceiOS::isGyroscopeActive()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isGyroActive);
}
bool CIrrDeviceiOS::isGyroscopeAvailable()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isGyroAvailable);
}
bool CIrrDeviceiOS::activateDeviceMotion(float updateInterval)
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isDeviceMotionAvailable)
{
if (!motionManager.isDeviceMotionActive)
{
dataStorage->ReferenceAttitude = nil;
motionManager.deviceMotionUpdateInterval = updateInterval;
[motionManager startDeviceMotionUpdates];
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::deactivateDeviceMotion()
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isDeviceMotionAvailable)
{
if (motionManager.isDeviceMotionActive)
{
[motionManager stopDeviceMotionUpdates];
dataStorage->ReferenceAttitude = nil;
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::isDeviceMotionActive()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isDeviceMotionActive);
}
bool CIrrDeviceiOS::isDeviceMotionAvailable()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isDeviceMotionAvailable);
}
E_DEVICE_TYPE CIrrDeviceiOS::getType() const
{
return EIDT_IOS;
}
void CIrrDeviceiOS::createWindow()
{
if (CreationParams.DriverType != video::EDT_NULL)
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
UIView* externalView = (__bridge UIView*)CreationParams.WindowId;
if (externalView == nil)
{
dataStorage->Window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
dataStorage->ViewController = [[UIViewController alloc] init];
dataStorage->Window.rootViewController = dataStorage->ViewController;
[dataStorage->Window makeKeyAndVisible];
}
else
{
dataStorage->Window = externalView.window;
UIResponder* currentResponder = externalView.nextResponder;
do
{
if ([currentResponder isKindOfClass:[UIViewController class]])
{
dataStorage->ViewController = (UIViewController*)currentResponder;
currentResponder = nil;
}
else if ([currentResponder isKindOfClass:[UIView class]])
{
currentResponder = currentResponder.nextResponder;
}
else
{
currentResponder = nil;
// Could not find view controller.
_IRR_DEBUG_BREAK_IF(true);
}
}
while (currentResponder != nil);
}
}
}
void CIrrDeviceiOS::createViewAndDriver()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
video::SExposedVideoData data;
data.OpenGLiOS.Window = (__bridge void*)dataStorage->Window;
data.OpenGLiOS.ViewController = (__bridge void*)dataStorage->ViewController;
UIView* externalView = (__bridge UIView*)CreationParams.WindowId;
CGRect resolution = (externalView == nil) ? [[UIScreen mainScreen] bounds] : externalView.bounds;
switch (CreationParams.DriverType)
{
case video::EDT_OGLES1:
#ifdef _IRR_COMPILE_WITH_OGLES1_
{
CIrrViewEAGLiOS* view = [[CIrrViewEAGLiOS alloc] initWithFrame:resolution forDevice:this];
CreationParams.WindowSize = core::dimension2d<u32>(view.frame.size.width, view.frame.size.height);
dataStorage->View = view;
data.OpenGLiOS.View = (__bridge void*)view;
ContextManager = new video::CEAGLManager();
ContextManager->initialize(CreationParams, data);
VideoDriver = video::createOGLES1Driver(CreationParams, FileSystem, ContextManager);
if (!VideoDriver)
os::Printer::log("Could not create OpenGL ES 1.x driver.", ELL_ERROR);
}
#else
os::Printer::log("No OpenGL ES 1.x support compiled in.", ELL_ERROR);
#endif
break;
case video::EDT_OGLES2:
#ifdef _IRR_COMPILE_WITH_OGLES2_
{
CIrrViewEAGLiOS* view = [[CIrrViewEAGLiOS alloc] initWithFrame:resolution forDevice:this];
CreationParams.WindowSize = core::dimension2d<u32>(view.frame.size.width, view.frame.size.height);
dataStorage->View = view;
data.OpenGLiOS.View = (__bridge void*)view;
ContextManager = new video::CEAGLManager();
ContextManager->initialize(CreationParams, data);
VideoDriver = video::createOGLES2Driver(CreationParams, FileSystem, ContextManager);
if (!VideoDriver)
os::Printer::log("Could not create OpenGL ES 2.x driver.", ELL_ERROR);
}
#else
os::Printer::log("No OpenGL ES 2.x support compiled in.", ELL_ERROR);
#endif
break;
case video::EDT_SOFTWARE:
case video::EDT_BURNINGSVIDEO:
case video::DEPRECATED_EDT_DIRECT3D8_NO_LONGER_EXISTS:
case video::EDT_DIRECT3D9:
case video::EDT_OPENGL:
os::Printer::log("This driver is not available in iOS. Try OpenGL ES.", ELL_ERROR);
break;
case video::EDT_NULL:
VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize);
break;
default:
os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR);
break;
}
if (externalView == nil)
dataStorage->ViewController.view = dataStorage->View;
else
[externalView addSubview:dataStorage->View];
}
}
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
int main(int argc, char** argv)
{
int result = UIApplicationMain(argc, argv, 0, NSStringFromClass([CIrrDelegateiOS class]));
return result;
}
#endif
#endif

@ -77,22 +77,13 @@ add_definitions(
if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
set(SOLARIS TRUE) set(SOLARIS TRUE)
endif() endif()
if(APPLE AND NOT IOS)
set(OSX TRUE)
endif()
# Device # Device
if(WIN32) if(WIN32)
add_definitions(-D_IRR_WINDOWS_ -D_IRR_WINDOWS_API_) add_definitions(-D_IRR_WINDOWS_ -D_IRR_WINDOWS_API_)
set(DEVICE "WINDOWS") set(DEVICE "WINDOWS")
elseif(IOS) elseif(APPLE)
add_definitions(-D_IRR_IOS_PLATFORM_ -D_IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_)
if(USE_SDL2)
message(SEND_ERROR "SDL2 backend is not supported on iOS")
endif()
set(DEVICE "IOS")
elseif(OSX)
add_definitions(-D_IRR_OSX_PLATFORM_) add_definitions(-D_IRR_OSX_PLATFORM_)
set(DEVICE "OSX") set(DEVICE "OSX")
elseif(ANDROID) elseif(ANDROID)
@ -150,26 +141,26 @@ endif()
option(ENABLE_OPENGL3 "Enable OpenGL 3+" FALSE) option(ENABLE_OPENGL3 "Enable OpenGL 3+" FALSE)
if(IOS OR ANDROID OR EMSCRIPTEN) if(ANDROID OR EMSCRIPTEN)
set(ENABLE_OPENGL FALSE) set(ENABLE_OPENGL FALSE)
else() else()
option(ENABLE_OPENGL "Enable OpenGL" TRUE) option(ENABLE_OPENGL "Enable OpenGL" TRUE)
endif() endif()
if(EMSCRIPTEN OR OSX) if(EMSCRIPTEN OR APPLE)
set(ENABLE_GLES1 FALSE) set(ENABLE_GLES1 FALSE)
else() else()
if(ANDROID OR IOS) if(ANDROID)
set(DEFAULT_GLES1 TRUE) set(DEFAULT_GLES1 TRUE)
endif() endif()
option(ENABLE_GLES1 "Enable OpenGL ES" ${DEFAULT_GLES1}) option(ENABLE_GLES1 "Enable OpenGL ES" ${DEFAULT_GLES1})
endif() endif()
if(OSX) if(APPLE)
set(ENABLE_GLES2 FALSE) set(ENABLE_GLES2 FALSE)
set(ENABLE_WEBGL1 FALSE) set(ENABLE_WEBGL1 FALSE)
else() else()
if(ANDROID OR IOS OR EMSCRIPTEN) if(ANDROID OR EMSCRIPTEN)
set(DEFAULT_GLES2 TRUE) set(DEFAULT_GLES2 TRUE)
endif() endif()
if(EMSCRIPTEN) if(EMSCRIPTEN)
@ -210,8 +201,6 @@ if(ENABLE_GLES1)
add_definitions(-D_IRR_COMPILE_WITH_OGLES1_) add_definitions(-D_IRR_COMPILE_WITH_OGLES1_)
if(DEVICE MATCHES "^(WINDOWS|X11|ANDROID)$") if(DEVICE MATCHES "^(WINDOWS|X11|ANDROID)$")
add_definitions(-D_IRR_COMPILE_WITH_EGL_MANAGER_ -D_IRR_OGLES1_USE_EXTPOINTER_) add_definitions(-D_IRR_COMPILE_WITH_EGL_MANAGER_ -D_IRR_OGLES1_USE_EXTPOINTER_)
elseif(DEVICE STREQUAL "IOS")
add_definitions(-D_IRR_COMPILE_WITH_EAGL_MANAGER_)
endif() endif()
endif() endif()
@ -219,8 +208,6 @@ if(ENABLE_GLES2)
add_definitions(-D_IRR_COMPILE_WITH_OGLES2_) add_definitions(-D_IRR_COMPILE_WITH_OGLES2_)
if(DEVICE MATCHES "^(WINDOWS|X11|ANDROID)$" OR EMSCRIPTEN) if(DEVICE MATCHES "^(WINDOWS|X11|ANDROID)$" OR EMSCRIPTEN)
add_definitions(-D_IRR_COMPILE_WITH_EGL_MANAGER_ -D_IRR_OGLES2_USE_EXTPOINTER_) add_definitions(-D_IRR_COMPILE_WITH_EGL_MANAGER_ -D_IRR_OGLES2_USE_EXTPOINTER_)
elseif(DEVICE STREQUAL "IOS")
add_definitions(-D_IRR_COMPILE_WITH_EAGL_MANAGER_)
elseif(DEVICE STREQUAL "SDL") elseif(DEVICE STREQUAL "SDL")
set(USE_SDLGL ON) set(USE_SDLGL ON)
set(USE_SDLGLES2 ON) set(USE_SDLGLES2 ON)

@ -1717,10 +1717,10 @@ s32 CNullDriver::addMaterialRenderer(IMaterialRenderer* renderer, const char* na
//! Sets the name of a material renderer. //! Sets the name of a material renderer.
void CNullDriver::setMaterialRendererName(s32 idx, const char* name) void CNullDriver::setMaterialRendererName(u32 idx, const char* name)
{ {
if (idx < s32(sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 || if (idx < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ||
idx >= (s32)MaterialRenderers.size()) idx >= MaterialRenderers.size())
return; return;
MaterialRenderers[idx].Name = name; MaterialRenderers[idx].Name = name;

@ -584,7 +584,7 @@ namespace video
bool writeImageToFile(IImage* image, io::IWriteFile * file, u32 param = 0) override; bool writeImageToFile(IImage* image, io::IWriteFile * file, u32 param = 0) override;
//! Sets the name of a material renderer. //! Sets the name of a material renderer.
void setMaterialRendererName(s32 idx, const char* name) override; void setMaterialRendererName(u32 idx, const char* name) override;
//! Swap the material renderers used for certain id's //! Swap the material renderers used for certain id's
void swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames) override; void swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames) override;

@ -24,23 +24,18 @@ namespace scene
#endif #endif
//! Constructor //! Constructor
COBJMeshFileLoader::COBJMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) COBJMeshFileLoader::COBJMeshFileLoader(scene::ISceneManager* smgr)
: SceneManager(smgr), FileSystem(fs) : SceneManager(smgr)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("COBJMeshFileLoader"); setDebugName("COBJMeshFileLoader");
#endif #endif
if (FileSystem)
FileSystem->grab();
} }
//! destructor //! destructor
COBJMeshFileLoader::~COBJMeshFileLoader() COBJMeshFileLoader::~COBJMeshFileLoader()
{ {
if (FileSystem)
FileSystem->drop();
} }
@ -76,7 +71,6 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
u32 smoothingGroup=0; u32 smoothingGroup=0;
const io::path fullName = file->getFileName(); const io::path fullName = file->getFileName();
const io::path relPath = FileSystem->getFileDir(fullName)+"/";
c8* buf = new c8[filesize]; c8* buf = new c8[filesize];
memset(buf, 0, filesize); memset(buf, 0, filesize);
@ -230,7 +224,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
v.Pos = vertexBuffer[Idx[0]]; v.Pos = vertexBuffer[Idx[0]];
else else
{ {
os::Printer::log("Invalid vertex index in this line:", wordBuffer.c_str(), ELL_ERROR); os::Printer::log("Invalid vertex index in this line", wordBuffer.c_str(), ELL_ERROR);
delete [] buf; delete [] buf;
return 0; return 0;
} }

@ -7,7 +7,6 @@
#include <map> #include <map>
#include "IMeshLoader.h" #include "IMeshLoader.h"
#include "IFileSystem.h"
#include "ISceneManager.h" #include "ISceneManager.h"
#include "irrString.h" #include "irrString.h"
#include "SMeshBuffer.h" #include "SMeshBuffer.h"
@ -23,7 +22,7 @@ class COBJMeshFileLoader : public IMeshLoader
public: public:
//! Constructor //! Constructor
COBJMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); COBJMeshFileLoader(scene::ISceneManager* smgr);
//! destructor //! destructor
virtual ~COBJMeshFileLoader(); virtual ~COBJMeshFileLoader();
@ -104,7 +103,6 @@ private:
void cleanUp(); void cleanUp();
scene::ISceneManager* SceneManager; scene::ISceneManager* SceneManager;
io::IFileSystem* FileSystem;
core::array<SObjMtl*> Materials; core::array<SObjMtl*> Materials;
}; };

@ -17,7 +17,10 @@
#endif #endif
#endif #endif
#if defined(_IRR_COMPILE_WITH_X11_DEVICE_) #if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
#include <SDL_clipboard.h>
#include <SDL_version.h>
#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_)
#include "CIrrDeviceLinux.h" #include "CIrrDeviceLinux.h"
#endif #endif
#if defined(_IRR_COMPILE_WITH_OSX_DEVICE_) #if defined(_IRR_COMPILE_WITH_OSX_DEVICE_)
@ -26,6 +29,19 @@
#include "fast_atof.h" #include "fast_atof.h"
#if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
static bool sdl_supports_primary_selection = [] {
#if SDL_VERSION_ATLEAST(2, 25, 0)
SDL_version linked_version;
SDL_GetVersion(&linked_version);
return (linked_version.major == 2 && linked_version.minor >= 25)
|| linked_version.major > 2;
#else
return false;
#endif
}();
#endif
namespace irr namespace irr
{ {
@ -54,14 +70,15 @@ const core::stringc& COSOperator::getOperatingSystemVersion() const
//! copies text to the clipboard //! copies text to the clipboard
//! \param text: text in utf-8
void COSOperator::copyToClipboard(const c8 *text) const void COSOperator::copyToClipboard(const c8 *text) const
{ {
if (strlen(text)==0) if (strlen(text)==0)
return; return;
// Windows version #if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
#if defined(_IRR_WINDOWS_API_) SDL_SetClipboardText(text);
#elif defined(_IRR_WINDOWS_API_)
if (!OpenClipboard(NULL) || text == 0) if (!OpenClipboard(NULL) || text == 0)
return; return;
@ -102,11 +119,36 @@ void COSOperator::copyToClipboard(const c8 *text) const
} }
//! copies text to the primary selection
void COSOperator::copyToPrimarySelection(const c8 *text) const
{
if (strlen(text)==0)
return;
#if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
#if SDL_VERSION_ATLEAST(2, 25, 0)
if (sdl_supports_primary_selection)
SDL_SetPrimarySelectionText(text);
#endif
#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_)
if ( IrrDeviceLinux )
IrrDeviceLinux->copyToPrimarySelection(text);
#endif
}
//! gets text from the clipboard //! gets text from the clipboard
//! \return Returns 0 if no string is in there, otherwise an utf-8 string.
const c8* COSOperator::getTextFromClipboard() const const c8* COSOperator::getTextFromClipboard() const
{ {
#if defined(_IRR_WINDOWS_API_) #if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
static char *text = nullptr;
if (text)
SDL_free(text);
text = SDL_GetClipboardText();
return text;
#elif defined(_IRR_WINDOWS_API_)
if (!OpenClipboard(NULL)) if (!OpenClipboard(NULL))
return 0; return 0;
@ -147,6 +189,33 @@ const c8* COSOperator::getTextFromClipboard() const
} }
//! gets text from the primary selection
const c8* COSOperator::getTextFromPrimarySelection() const
{
#if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
#if SDL_VERSION_ATLEAST(2, 25, 0)
if (sdl_supports_primary_selection) {
static char *text = nullptr;
if (text)
SDL_free(text);
text = SDL_GetPrimarySelectionText();
return text;
}
#endif
return 0;
#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_)
if ( IrrDeviceLinux )
return IrrDeviceLinux->getTextFromPrimarySelection();
return 0;
#else
return 0;
#endif
}
bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const
{ {
#if defined(_IRR_WINDOWS_API_) #if defined(_IRR_WINDOWS_API_)

@ -27,13 +27,17 @@ public:
const core::stringc& getOperatingSystemVersion() const override; const core::stringc& getOperatingSystemVersion() const override;
//! copies text to the clipboard //! copies text to the clipboard
//! \param text: text in utf-8
void copyToClipboard(const c8 *text) const override; void copyToClipboard(const c8 *text) const override;
//! copies text to the primary selection
void copyToPrimarySelection(const c8 *text) const override;
//! gets text from the clipboard //! gets text from the clipboard
//! \return Returns 0 if no string is in there, otherwise an utf-8 string.
const c8* getTextFromClipboard() const override; const c8* getTextFromClipboard() const override;
//! gets text from the primary selection
const c8* getTextFromPrimarySelection() const override;
//! gets the total and available system RAM in kB //! gets the total and available system RAM in kB
//! \param Total: will contain the total system memory //! \param Total: will contain the total system memory
//! \param Avail: will contain the available memory //! \param Avail: will contain the available memory

@ -746,10 +746,10 @@ IRenderTarget* COpenGLDriver::addRenderTarget()
} }
// small helper function to create vertex buffer object adress offsets // small helper function to create vertex buffer object address offsets
static inline u8* buffer_offset(const long offset) static inline const GLvoid * buffer_offset(const long offset)
{ {
return ((u8*)0 + offset); return (const GLvoid *)offset;
} }

@ -33,10 +33,9 @@ namespace scene
{ {
//! constructor //! constructor
CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, CSceneManager::CSceneManager(video::IVideoDriver* driver,
gui::ICursorControl* cursorControl, IMeshCache* cache, gui::ICursorControl* cursorControl, IMeshCache* cache)
gui::IGUIEnvironment* gui) : ISceneNode(0, 0), Driver(driver),
: ISceneNode(0, 0), Driver(driver), FileSystem(fs), GUIEnvironment(gui),
CursorControl(cursorControl), CursorControl(cursorControl),
ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0), Parameters(0), ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0), Parameters(0),
MeshCache(cache), CurrentRenderPass(ESNRP_NONE) MeshCache(cache), CurrentRenderPass(ESNRP_NONE)
@ -52,15 +51,9 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
if (Driver) if (Driver)
Driver->grab(); Driver->grab();
if (FileSystem)
FileSystem->grab();
if (CursorControl) if (CursorControl)
CursorControl->grab(); CursorControl->grab();
if (GUIEnvironment)
GUIEnvironment->grab();
// create mesh cache if not there already // create mesh cache if not there already
if (!MeshCache) if (!MeshCache)
MeshCache = new CMeshCache(); MeshCache = new CMeshCache();
@ -79,8 +72,8 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
// TODO: now that we have multiple scene managers, these should be // TODO: now that we have multiple scene managers, these should be
// shallow copies from the previous manager if there is one. // shallow copies from the previous manager if there is one.
MeshLoaderList.push_back(new CXMeshFileLoader(this, FileSystem)); MeshLoaderList.push_back(new CXMeshFileLoader(this));
MeshLoaderList.push_back(new COBJMeshFileLoader(this, FileSystem)); MeshLoaderList.push_back(new COBJMeshFileLoader(this));
MeshLoaderList.push_back(new CB3DMeshFileLoader(this)); MeshLoaderList.push_back(new CB3DMeshFileLoader(this));
} }
@ -96,18 +89,12 @@ CSceneManager::~CSceneManager()
if (Driver) if (Driver)
Driver->removeAllHardwareBuffers(); Driver->removeAllHardwareBuffers();
if (FileSystem)
FileSystem->drop();
if (CursorControl) if (CursorControl)
CursorControl->drop(); CursorControl->drop();
if (CollisionManager) if (CollisionManager)
CollisionManager->drop(); CollisionManager->drop();
if (GUIEnvironment)
GUIEnvironment->drop();
u32 i; u32 i;
for (i=0; i<MeshLoaderList.size(); ++i) for (i=0; i<MeshLoaderList.size(); ++i)
MeshLoaderList[i]->drop(); MeshLoaderList[i]->drop();
@ -132,29 +119,6 @@ CSceneManager::~CSceneManager()
} }
//! gets an animateable mesh. loads it if needed. returned pointer must not be dropped.
IAnimatedMesh* CSceneManager::getMesh(const io::path& filename, const io::path& alternativeCacheName)
{
io::path cacheName = alternativeCacheName.empty() ? filename : alternativeCacheName;
IAnimatedMesh* msh = MeshCache->getMeshByName(cacheName);
if (msh)
return msh;
io::IReadFile* file = FileSystem->createAndOpenFile(filename);
if (!file)
{
os::Printer::log("Could not load mesh, because file could not be opened: ", filename, ELL_ERROR);
return 0;
}
msh = getUncachedMesh(file, filename, cacheName);
file->drop();
return msh;
}
//! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped.
IAnimatedMesh* CSceneManager::getMesh(io::IReadFile* file) IAnimatedMesh* CSceneManager::getMesh(io::IReadFile* file)
{ {
@ -209,21 +173,6 @@ video::IVideoDriver* CSceneManager::getVideoDriver()
} }
//! returns the GUI Environment
gui::IGUIEnvironment* CSceneManager::getGUIEnvironment()
{
return GUIEnvironment;
}
//! Get the active FileSystem
/** \return Pointer to the FileSystem
This pointer should not be dropped. See IReferenceCounted::drop() for more information. */
io::IFileSystem* CSceneManager::getFileSystem()
{
return FileSystem;
}
//! adds a scene node for rendering a static mesh //! adds a scene node for rendering a static mesh
//! the returned pointer must not be dropped. //! the returned pointer must not be dropped.
IMeshSceneNode* CSceneManager::addMeshSceneNode(IMesh* mesh, ISceneNode* parent, s32 id, IMeshSceneNode* CSceneManager::addMeshSceneNode(IMesh* mesh, ISceneNode* parent, s32 id,
@ -888,7 +837,7 @@ IMeshCache* CSceneManager::getMeshCache()
//! Creates a new scene manager. //! Creates a new scene manager.
ISceneManager* CSceneManager::createNewSceneManager(bool cloneContent) ISceneManager* CSceneManager::createNewSceneManager(bool cloneContent)
{ {
CSceneManager* manager = new CSceneManager(Driver, FileSystem, CursorControl, MeshCache, GUIEnvironment); CSceneManager* manager = new CSceneManager(Driver, CursorControl, MeshCache);
if (cloneContent) if (cloneContent)
manager->cloneMembers(this, manager); manager->cloneMembers(this, manager);
@ -925,11 +874,9 @@ IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type)
// creates a scenemanager // creates a scenemanager
ISceneManager* createSceneManager(video::IVideoDriver* driver, ISceneManager* createSceneManager(video::IVideoDriver* driver, gui::ICursorControl* cursorcontrol)
io::IFileSystem* fs, gui::ICursorControl* cursorcontrol,
gui::IGUIEnvironment *guiEnvironment)
{ {
return new CSceneManager(driver, fs, cursorcontrol, 0, guiEnvironment ); return new CSceneManager(driver, cursorcontrol, nullptr);
} }

@ -31,16 +31,11 @@ namespace scene
public: public:
//! constructor //! constructor
CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, CSceneManager(video::IVideoDriver* driver, gui::ICursorControl* cursorControl, IMeshCache* cache = 0);
gui::ICursorControl* cursorControl, IMeshCache* cache = 0,
gui::IGUIEnvironment *guiEnvironment = 0);
//! destructor //! destructor
virtual ~CSceneManager(); virtual ~CSceneManager();
//! gets an animateable mesh. loads it if needed. returned pointer must not be dropped.
IAnimatedMesh* getMesh(const io::path& filename, const io::path& alternativeCacheName) override;
//! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped.
IAnimatedMesh* getMesh(io::IReadFile* file) override; IAnimatedMesh* getMesh(io::IReadFile* file) override;
@ -50,12 +45,6 @@ namespace scene
//! returns the video driver //! returns the video driver
video::IVideoDriver* getVideoDriver() override; video::IVideoDriver* getVideoDriver() override;
//! return the gui environment
gui::IGUIEnvironment* getGUIEnvironment() override;
//! return the filesystem
io::IFileSystem* getFileSystem() override;
//! adds a scene node for rendering an animated mesh model //! adds a scene node for rendering an animated mesh model
virtual IAnimatedMeshSceneNode* addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, virtual IAnimatedMeshSceneNode* addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1,
const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& position = core::vector3df(0,0,0),
@ -282,12 +271,6 @@ namespace scene
//! video driver //! video driver
video::IVideoDriver* Driver; video::IVideoDriver* Driver;
//! file system
io::IFileSystem* FileSystem;
//! GUI Enviroment ( Debug Purpose )
gui::IGUIEnvironment* GUIEnvironment;
//! cursor control //! cursor control
gui::ICursorControl* CursorControl; gui::ICursorControl* CursorControl;

@ -1134,27 +1134,27 @@ void CSkinnedMesh::finalize()
if ( redundantPosKeys > 0 ) if ( redundantPosKeys > 0 )
{ {
os::Printer::log("Skinned Mesh - redundant position frames kicked:", core::stringc(redundantPosKeys).c_str(), ELL_DEBUG); os::Printer::log("Skinned Mesh - redundant position frames kicked", core::stringc(redundantPosKeys).c_str(), ELL_DEBUG);
} }
if ( unorderedPosKeys > 0 ) if ( unorderedPosKeys > 0 )
{ {
irr::os::Printer::log("Skinned Mesh - unsorted position frames kicked:", irr::core::stringc(unorderedPosKeys).c_str(), irr::ELL_DEBUG); irr::os::Printer::log("Skinned Mesh - unsorted position frames kicked", irr::core::stringc(unorderedPosKeys).c_str(), irr::ELL_DEBUG);
} }
if ( redundantScaleKeys > 0 ) if ( redundantScaleKeys > 0 )
{ {
os::Printer::log("Skinned Mesh - redundant scale frames kicked:", core::stringc(redundantScaleKeys).c_str(), ELL_DEBUG); os::Printer::log("Skinned Mesh - redundant scale frames kicked", core::stringc(redundantScaleKeys).c_str(), ELL_DEBUG);
} }
if ( unorderedScaleKeys > 0 ) if ( unorderedScaleKeys > 0 )
{ {
irr::os::Printer::log("Skinned Mesh - unsorted scale frames kicked:", irr::core::stringc(unorderedScaleKeys).c_str(), irr::ELL_DEBUG); irr::os::Printer::log("Skinned Mesh - unsorted scale frames kicked", irr::core::stringc(unorderedScaleKeys).c_str(), irr::ELL_DEBUG);
} }
if ( redundantRotationKeys > 0 ) if ( redundantRotationKeys > 0 )
{ {
os::Printer::log("Skinned Mesh - redundant rotation frames kicked:", core::stringc(redundantRotationKeys).c_str(), ELL_DEBUG); os::Printer::log("Skinned Mesh - redundant rotation frames kicked", core::stringc(redundantRotationKeys).c_str(), ELL_DEBUG);
} }
if ( unorderedRotationKeys > 0 ) if ( unorderedRotationKeys > 0 )
{ {
irr::os::Printer::log("Skinned Mesh - unsorted rotation frames kicked:", irr::core::stringc(unorderedRotationKeys).c_str(), irr::ELL_DEBUG); irr::os::Printer::log("Skinned Mesh - unsorted rotation frames kicked", irr::core::stringc(unorderedRotationKeys).c_str(), irr::ELL_DEBUG);
} }
} }
@ -1347,9 +1347,24 @@ void CSkinnedMesh::recoverJointsFromMesh(core::array<IBoneSceneNode*> &jointChil
{ {
IBoneSceneNode* node=jointChildSceneNodes[i]; IBoneSceneNode* node=jointChildSceneNodes[i];
SJoint *joint=AllJoints[i]; SJoint *joint=AllJoints[i];
if ( joint->UseAnimationFrom ) // Seems to work better (else solution seems to mess up sometimes) and would be faster. Any disadvantage?
{
node->setPosition(joint->Animatedposition);
core::quaternion qrot = joint->Animatedrotation;
qrot.W *= -1.f; // Animation system uses right-handed rotations? Argh...
irr::core::vector3df euler;
qrot.toEuler(euler);
euler *= core::RADTODEG;
node->setRotation(euler);
node->setScale(joint->Animatedscale);
}
else
{
node->setPosition(joint->LocalAnimatedMatrix.getTranslation()); node->setPosition(joint->LocalAnimatedMatrix.getTranslation());
node->setRotation(joint->LocalAnimatedMatrix.getRotationDegrees()); node->setRotation(joint->LocalAnimatedMatrix.getRotationDegrees());
node->setScale(joint->LocalAnimatedMatrix.getScale()); node->setScale(joint->LocalAnimatedMatrix.getScale());
}
node->positionHint=joint->positionHint; node->positionHint=joint->positionHint;
node->scaleHint=joint->scaleHint; node->scaleHint=joint->scaleHint;

@ -464,7 +464,7 @@ bool CWGLManager::activateContext(const SExposedVideoData& videoData, bool resto
{ {
if (!wglMakeCurrent((HDC)PrimaryContext.OpenGLWin32.HDc, (HGLRC)PrimaryContext.OpenGLWin32.HRc)) if (!wglMakeCurrent((HDC)PrimaryContext.OpenGLWin32.HDc, (HGLRC)PrimaryContext.OpenGLWin32.HRc))
{ {
os::Printer::log("Render Context switch failed."); os::Printer::log("Render Context switch (back to main) failed.");
return false; return false;
} }
CurrentContext=PrimaryContext; CurrentContext=PrimaryContext;

@ -10,7 +10,6 @@
#include "coreutil.h" #include "coreutil.h"
#include "ISceneManager.h" #include "ISceneManager.h"
#include "IVideoDriver.h" #include "IVideoDriver.h"
#include "IFileSystem.h"
#include "IReadFile.h" #include "IReadFile.h"
#ifdef _DEBUG #ifdef _DEBUG
@ -24,7 +23,7 @@ namespace scene
{ {
//! Constructor //! Constructor
CXMeshFileLoader::CXMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) CXMeshFileLoader::CXMeshFileLoader(scene::ISceneManager* smgr)
: AnimatedMesh(0), Buffer(0), P(0), End(0), BinaryNumCount(0), Line(0), : AnimatedMesh(0), Buffer(0), P(0), End(0), BinaryNumCount(0), Line(0),
CurFrame(0), MajorVersion(0), MinorVersion(0), BinaryFormat(false), FloatSize(0) CurFrame(0), MajorVersion(0), MinorVersion(0), BinaryFormat(false), FloatSize(0)
{ {
@ -480,7 +479,7 @@ bool CXMeshFileLoader::parseDataObject()
// parse specific object // parse specific object
#ifdef _XREADER_DEBUG #ifdef _XREADER_DEBUG
os::Printer::log("debug DataObject:", objectName.c_str(), ELL_DEBUG); os::Printer::log("debug DataObject", objectName.c_str(), ELL_DEBUG);
#endif #endif
if (objectName == "template") if (objectName == "template")
@ -833,7 +832,7 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh)
} }
#ifdef _XREADER_DEBUG #ifdef _XREADER_DEBUG
os::Printer::log("debug DataObject in mesh:", objectName.c_str(), ELL_DEBUG); os::Printer::log("debug DataObject in mesh", objectName.c_str(), ELL_DEBUG);
#endif #endif
if (objectName == "MeshNormals") if (objectName == "MeshNormals")

@ -14,7 +14,6 @@ namespace irr
{ {
namespace io namespace io
{ {
class IFileSystem;
class IReadFile; class IReadFile;
} // end namespace io } // end namespace io
namespace scene namespace scene
@ -27,7 +26,7 @@ class CXMeshFileLoader : public IMeshLoader
public: public:
//! Constructor //! Constructor
CXMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); CXMeshFileLoader(scene::ISceneManager* smgr);
//! returns true if the file maybe is able to be loaded by this class //! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".cob") //! based on the file extension (e.g. ".cob")

@ -29,10 +29,6 @@ static const char* const copyright = "Irrlicht Engine (c) 2002-2017 Nikolaus Geb
#include "CIrrDeviceSDL.h" #include "CIrrDeviceSDL.h"
#endif #endif
#ifdef _IRR_COMPILE_WITH_IOS_DEVICE_
#include "CIrrDeviceiOS.h"
#endif
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_ #ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
#include "Android/CIrrDeviceAndroid.h" #include "Android/CIrrDeviceAndroid.h"
#endif #endif
@ -79,11 +75,6 @@ namespace irr
dev = new CIrrDeviceLinux(params); dev = new CIrrDeviceLinux(params);
#endif #endif
#ifdef _IRR_COMPILE_WITH_IOS_DEVICE_
if (params.DeviceType == EIDT_IOS || (!dev && params.DeviceType == EIDT_BEST))
dev = new CIrrDeviceiOS(params);
#endif
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_ #ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
if (params.DeviceType == EIDT_ANDROID || (!dev && params.DeviceType == EIDT_BEST)) if (params.DeviceType == EIDT_ANDROID || (!dev && params.DeviceType == EIDT_BEST))
dev = new CIrrDeviceAndroid(params); dev = new CIrrDeviceAndroid(params);

@ -17,7 +17,7 @@
#define bswap_32(X) _byteswap_ulong(X) #define bswap_32(X) _byteswap_ulong(X)
#define bswap_64(X) _byteswap_uint64(X) #define bswap_64(X) _byteswap_uint64(X)
#define localtime _localtime_s #define localtime _localtime_s
#elif defined(_IRR_OSX_PLATFORM_) || defined(_IRR_IOS_PLATFORM_) #elif defined(_IRR_OSX_PLATFORM_)
#include <libkern/OSByteOrder.h> #include <libkern/OSByteOrder.h>
#define bswap_16(X) OSReadSwapInt16(&X,0) #define bswap_16(X) OSReadSwapInt16(&X,0)
#define bswap_32(X) OSReadSwapInt32(&X,0) #define bswap_32(X) OSReadSwapInt32(&X,0)

@ -38,6 +38,8 @@ namespace os
static void print(const c8* message, ELOG_LEVEL ll = ELL_INFORMATION); static void print(const c8* message, ELOG_LEVEL ll = ELL_INFORMATION);
static void log(const c8* message, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const c8* message, ELOG_LEVEL ll = ELL_INFORMATION);
static void log(const wchar_t* message, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const wchar_t* message, ELOG_LEVEL ll = ELL_INFORMATION);
// The string ": " is added between message and hint
static void log(const c8* message, const c8* hint, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const c8* message, const c8* hint, ELOG_LEVEL ll = ELL_INFORMATION);
static void log(const c8* message, const io::path& hint, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const c8* message, const io::path& hint, ELOG_LEVEL ll = ELL_INFORMATION);
static ILogger* Logger; static ILogger* Logger;