SuperTuxKart 1.5 upstream source (from official release tarball)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,225 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IAnimatedMeshSceneNode.h"
|
||||
#include "IAnimatedMesh.h"
|
||||
|
||||
#include "matrix4.h"
|
||||
|
||||
#include <memory>
|
||||
namespace GE
|
||||
{
|
||||
class GERenderInfo;
|
||||
}
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class IDummyTransformationSceneNode;
|
||||
|
||||
class CAnimatedMeshSceneNode : public IAnimatedMeshSceneNode
|
||||
{
|
||||
private:
|
||||
core::array<u32> m_animation_set;
|
||||
std::shared_ptr<GE::GERenderInfo> m_first_render_info;
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position = core::vector3df(0,0,0),
|
||||
const core::vector3df& rotation = core::vector3df(0,0,0),
|
||||
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
|
||||
//! destructor
|
||||
virtual ~CAnimatedMeshSceneNode();
|
||||
|
||||
//! sets the current frame. from now on the animation is played from this frame.
|
||||
virtual void setCurrentFrame(f32 frame);
|
||||
|
||||
//! frame
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! OnAnimate() is called just before rendering the whole scene.
|
||||
virtual void OnAnimate(u32 timeMs);
|
||||
|
||||
//! renders the node.
|
||||
virtual void render();
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! sets the frames between the animation is looped.
|
||||
//! the default is 0 - MaximalFrameCount of the mesh.
|
||||
virtual bool setFrameLoop(s32 begin, s32 end);
|
||||
|
||||
//! Sets looping mode which is on by default. If set to false,
|
||||
//! animations will not be looped.
|
||||
virtual void setLoopMode(bool playAnimationLooped);
|
||||
|
||||
//! returns the current loop mode
|
||||
virtual bool getLoopMode() const;
|
||||
|
||||
//! Sets a callback interface which will be called if an animation
|
||||
//! playback has ended. Set this to 0 to disable the callback again.
|
||||
virtual void setAnimationEndCallback(IAnimationEndCallBack* callback=0);
|
||||
|
||||
//! sets the speed with which the animation is played
|
||||
virtual void setAnimationSpeed(f32 framesPerSecond);
|
||||
|
||||
//! gets the speed with which the animation is played
|
||||
virtual f32 getAnimationSpeed() const;
|
||||
|
||||
//! Sets the animation strength (how important the animation is)
|
||||
/** \param strength: The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
|
||||
virtual void setAnimationStrength(f32 strength);
|
||||
|
||||
//! Gets the animation strength (how important the animation is)
|
||||
/** \return The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
|
||||
virtual f32 getAnimationStrength() const;
|
||||
|
||||
//! returns the material based on the zero based index i. To get the amount
|
||||
//! of materials used by this scene node, use getMaterialCount().
|
||||
//! This function is needed for inserting the node into the scene hirachy on a
|
||||
//! optimal position for minimizing renderstate changes, but can also be used
|
||||
//! to directly modify the material of a scene node.
|
||||
virtual video::SMaterial& getMaterial(u32 i);
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
virtual u32 getMaterialCount() const;
|
||||
|
||||
//! Returns a pointer to a child node, which has the same transformation as
|
||||
//! the corrsesponding joint, if the mesh in this scene node is a skinned mesh.
|
||||
virtual IBoneSceneNode* getJointNode(const c8* jointName);
|
||||
|
||||
//! same as getJointNode(const c8* jointName), but based on id
|
||||
virtual IBoneSceneNode* getJointNode(u32 jointID);
|
||||
|
||||
//! Gets joint count.
|
||||
virtual u32 getJointCount() const;
|
||||
|
||||
//! Deprecated command, please use getJointNode.
|
||||
virtual ISceneNode* getMS3DJointNode(const c8* jointName);
|
||||
|
||||
//! Deprecated command, please use getJointNode.
|
||||
virtual ISceneNode* getXJointNode(const c8* jointName);
|
||||
|
||||
//! Removes a child from this scene node.
|
||||
//! Implemented here, to be able to remove the shadow properly, if there is one,
|
||||
//! or to remove attached childs.
|
||||
virtual bool removeChild(ISceneNode* child);
|
||||
|
||||
//! Returns the current displayed frame number.
|
||||
virtual f32 getFrameNr() const;
|
||||
//! Returns the current start frame number.
|
||||
virtual s32 getStartFrame() const;
|
||||
//! Returns the current end frame number.
|
||||
virtual s32 getEndFrame() const;
|
||||
|
||||
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
|
||||
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes
|
||||
referencing this mesh to change too. */
|
||||
virtual void setReadOnlyMaterials(bool readonly);
|
||||
|
||||
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
|
||||
virtual bool isReadOnlyMaterials() const;
|
||||
|
||||
//! Sets a new mesh
|
||||
virtual void setMesh(IAnimatedMesh* mesh);
|
||||
|
||||
//! Returns the current mesh
|
||||
virtual IAnimatedMesh* getMesh(void) { return Mesh; }
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_ANIMATED_MESH; }
|
||||
|
||||
//! updates the absolute position based on the relative and the parents position
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
|
||||
//! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set)
|
||||
virtual void setJointMode(E_JOINT_UPDATE_ON_RENDER mode);
|
||||
|
||||
//! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2)
|
||||
//! you must call animateJoints(), or the mesh will not animate
|
||||
virtual void setTransitionTime(f32 Time);
|
||||
|
||||
//! updates the joint positions of this mesh
|
||||
virtual void animateJoints(bool CalculateAbsolutePositions=true);
|
||||
|
||||
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
|
||||
virtual void setRenderFromIdentity( bool On );
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
/** \param newParent An optional new parent.
|
||||
\param newManager An optional new scene manager.
|
||||
\return The newly created clone of this node. */
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
virtual u32 getAnimationSetNum() { return m_animation_set.size() / 2; }
|
||||
virtual s32 getAnimationSet() const;
|
||||
virtual void addAnimationSet(u32 start, u32 end)
|
||||
{
|
||||
m_animation_set.push_back(start);
|
||||
m_animation_set.push_back(end);
|
||||
}
|
||||
virtual void removeAllAnimationSet() { m_animation_set.clear(); }
|
||||
virtual void useAnimationSet(u32 set_num);
|
||||
virtual void setFrameLoopOnce(s32 begin, s32 end);
|
||||
virtual core::array<u32>& getAnimationSetFrames() { return m_animation_set; }
|
||||
virtual void resetFirstRenderInfo(std::shared_ptr<GE::GERenderInfo> ri);
|
||||
protected:
|
||||
|
||||
//! Get a static mesh for the current frame of this animated mesh
|
||||
virtual IMesh* getMeshForCurrentFrame();
|
||||
|
||||
void buildFrameNr(u32 timeMs);
|
||||
virtual void checkJoints();
|
||||
void beginTransition();
|
||||
|
||||
core::array<video::SMaterial> Materials;
|
||||
core::aabbox3d<f32> Box;
|
||||
IAnimatedMesh* Mesh;
|
||||
|
||||
s32 StartFrame;
|
||||
s32 EndFrame;
|
||||
f32 FramesPerSecond;
|
||||
f32 CurrentFrameNr;
|
||||
|
||||
f32 AnimationStrength;
|
||||
|
||||
u32 LastTimeMs;
|
||||
u32 TransitionTime; //Transition time in millisecs
|
||||
f32 Transiting; //is mesh transiting (plus cache of TransitionTime)
|
||||
f32 TransitingBlend; //0-1, calculated on buildFrameNr
|
||||
|
||||
//0-unused, 1-get joints only, 2-set joints only, 3-move and set
|
||||
E_JOINT_UPDATE_ON_RENDER JointMode;
|
||||
bool JointsUsed;
|
||||
|
||||
bool Looping;
|
||||
bool ReadOnlyMaterials;
|
||||
bool RenderFromIdentity;
|
||||
|
||||
IAnimationEndCallBack* LoopCallBack;
|
||||
s32 PassCount;
|
||||
|
||||
core::array<IBoneSceneNode* > JointChildSceneNodes;
|
||||
core::array<core::matrix4> PretransitingSave;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,712 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_ATTRIBUTES_H_INCLUDED__
|
||||
#define __C_ATTRIBUTES_H_INCLUDED__
|
||||
|
||||
#include "IAttributes.h"
|
||||
#include "IAttribute.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
class ITexture;
|
||||
class IVideoDriver;
|
||||
}
|
||||
namespace io
|
||||
{
|
||||
|
||||
|
||||
//! Implementation of the IAttributes interface
|
||||
class CAttributes : public IAttributes
|
||||
{
|
||||
public:
|
||||
|
||||
CAttributes(video::IVideoDriver* driver=0);
|
||||
~CAttributes();
|
||||
|
||||
//! Returns amount of attributes in this collection of attributes.
|
||||
virtual u32 getAttributeCount() const;
|
||||
|
||||
//! Returns attribute name by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual const c8* getAttributeName(s32 index);
|
||||
|
||||
//! Returns the type of an attribute
|
||||
//! \param attributeName: Name for the attribute
|
||||
virtual E_ATTRIBUTE_TYPE getAttributeType(const c8* attributeName);
|
||||
|
||||
//! Returns attribute type by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual E_ATTRIBUTE_TYPE getAttributeType(s32 index);
|
||||
|
||||
//! Returns the type string of the attribute
|
||||
//! \param attributeName: String for the attribute type
|
||||
virtual const wchar_t* getAttributeTypeString(const c8* attributeName);
|
||||
|
||||
//! Returns the type string of the attribute by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual const wchar_t* getAttributeTypeString(s32 index);
|
||||
|
||||
//! Returns if an attribute with a name exists
|
||||
virtual bool existsAttribute(const c8* attributeName);
|
||||
|
||||
//! Returns attribute index from name, -1 if not found
|
||||
virtual s32 findAttribute(const c8* attributeName) const;
|
||||
|
||||
//! Removes all attributes
|
||||
virtual void clear();
|
||||
|
||||
//! Reads attributes from a xml file.
|
||||
//! \param readCurrentElementOnly: If set to true, reading only works if current element has the name 'attributes'.
|
||||
//! IF set to false, the first appearing list attributes are read.
|
||||
virtual bool read(io::IXMLReader* reader, bool readCurrentElementOnly=false,
|
||||
const wchar_t* nonDefaultElementName = 0);
|
||||
|
||||
//! Write these attributes into a xml file
|
||||
virtual bool write(io::IXMLWriter* writer, bool writeXMLHeader=false, const wchar_t* nonDefaultElementName=0);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Integer Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as integer
|
||||
virtual void addInt(const c8* attributeName, s32 value);
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
virtual void setAttribute(const c8* attributeName, s32 value);
|
||||
|
||||
//! Gets an attribute as integer value
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual s32 getAttributeAsInt(const c8* attributeName) const;
|
||||
|
||||
//! Gets an attribute as integer value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual s32 getAttributeAsInt(s32 index) const;
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
virtual void setAttribute(s32 index, s32 value);
|
||||
|
||||
/*
|
||||
|
||||
Float Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as float
|
||||
virtual void addFloat(const c8* attributeName, f32 value);
|
||||
|
||||
//! Sets a attribute as float value
|
||||
virtual void setAttribute(const c8* attributeName, f32 value);
|
||||
|
||||
//! Gets an attribute as float value
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual f32 getAttributeAsFloat(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as float value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual f32 getAttributeAsFloat(s32 index);
|
||||
|
||||
//! Sets an attribute as float value
|
||||
virtual void setAttribute(s32 index, f32 value);
|
||||
|
||||
/*
|
||||
|
||||
String Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as string
|
||||
virtual void addString(const c8* attributeName, const c8* value);
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
//! \param value: Value for the attribute. Set this to 0 to delete the attribute
|
||||
virtual void setAttribute(const c8* attributeName, const c8* value);
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
//! or 0 if attribute is not set.
|
||||
virtual core::stringc getAttributeAsString(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \param target: Buffer where the string is copied to.
|
||||
virtual void getAttributeAsString(const c8* attributeName, c8* target);
|
||||
|
||||
//! Returns attribute value as string by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::stringc getAttributeAsString(s32 index);
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
virtual void setAttribute(s32 index, const c8* value);
|
||||
|
||||
// wide strings
|
||||
|
||||
//! Adds an attribute as string
|
||||
virtual void addString(const c8* attributeName, const wchar_t* value);
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
//! \param value: Value for the attribute. Set this to 0 to delete the attribute
|
||||
virtual void setAttribute(const c8* attributeName, const wchar_t* value);
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
//! or 0 if attribute is not set.
|
||||
virtual core::stringw getAttributeAsStringW(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \param target: Buffer where the string is copied to.
|
||||
virtual void getAttributeAsStringW(const c8* attributeName, wchar_t* target);
|
||||
|
||||
//! Returns attribute value as string by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::stringw getAttributeAsStringW(s32 index);
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
virtual void setAttribute(s32 index, const wchar_t* value);
|
||||
|
||||
/*
|
||||
|
||||
Binary Data Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as binary data
|
||||
virtual void addBinary(const c8* attributeName, void* data, s32 dataSizeInBytes);
|
||||
|
||||
//! Sets an attribute as binary data
|
||||
virtual void setAttribute(const c8* attributeName, void* data, s32 dataSizeInBytes);
|
||||
|
||||
//! Gets an attribute as binary data
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
virtual void getAttributeAsBinaryData(const c8* attributeName, void* outData, s32 maxSizeInBytes);
|
||||
|
||||
//! Gets an attribute as binary data
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual void getAttributeAsBinaryData(s32 index, void* outData, s32 maxSizeInBytes);
|
||||
|
||||
//! Sets an attribute as binary data
|
||||
virtual void setAttribute(s32 index, void* data, s32 dataSizeInBytes);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Array Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as wide string array
|
||||
virtual void addArray(const c8* attributeName, const core::array<core::stringw>& value);
|
||||
|
||||
//! Sets an attribute value as a wide string array.
|
||||
//! \param attributeName: Name for the attribute
|
||||
//! \param value: Value for the attribute. Set this to 0 to delete the attribute
|
||||
virtual void setAttribute(const c8* attributeName, const core::array<core::stringw>& value);
|
||||
|
||||
//! Gets an attribute as an array of wide strings.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
//! or 0 if attribute is not set.
|
||||
virtual core::array<core::stringw> getAttributeAsArray(const c8* attributeName);
|
||||
|
||||
//! Returns attribute value as an array of wide strings by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::array<core::stringw> getAttributeAsArray(s32 index);
|
||||
|
||||
//! Sets an attribute as an array of wide strings
|
||||
virtual void setAttribute(s32 index, const core::array<core::stringw>& value);
|
||||
|
||||
/*
|
||||
|
||||
Bool Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as bool
|
||||
virtual void addBool(const c8* attributeName, bool value);
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
virtual void setAttribute(const c8* attributeName, bool value);
|
||||
|
||||
//! Gets an attribute as boolean value
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual bool getAttributeAsBool(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as boolean value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual bool getAttributeAsBool(s32 index);
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
virtual void setAttribute(s32 index, bool value);
|
||||
|
||||
/*
|
||||
|
||||
Enumeration Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as enum
|
||||
virtual void addEnum(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals);
|
||||
|
||||
//! Adds an attribute as enum
|
||||
virtual void addEnum(const c8* attributeName, s32 enumValue, const c8* const* enumerationLiterals);
|
||||
|
||||
//! Sets an attribute as enumeration
|
||||
virtual void setAttribute(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals);
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual const c8* getAttributeAsEnumeration(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \param enumerationLiteralsToUse: Use these enumeration literals to get the index value instead of the set ones.
|
||||
//! This is useful when the attribute list maybe was read from an xml file, and only contains the enumeration string, but
|
||||
//! no information about its index.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual s32 getAttributeAsEnumeration(const c8* attributeName, const c8* const* enumerationLiteralsToUse);
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual s32 getAttributeAsEnumeration(s32 index, const c8* const* enumerationLiteralsToUse);
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual const c8* getAttributeAsEnumeration(s32 index);
|
||||
|
||||
//! Gets the list of enumeration literals of an enumeration attribute
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
virtual void getAttributeEnumerationLiteralsOfEnumeration(const c8* attributeName, core::array<core::stringc>& outLiterals);
|
||||
|
||||
//! Gets the list of enumeration literals of an enumeration attribute
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual void getAttributeEnumerationLiteralsOfEnumeration(s32 index, core::array<core::stringc>& outLiterals);
|
||||
|
||||
//! Sets an attribute as enumeration
|
||||
virtual void setAttribute(s32 index, const c8* enumValue, const c8* const* enumerationLiterals);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
SColor Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as color
|
||||
virtual void addColor(const c8* attributeName, video::SColor value);
|
||||
|
||||
//! Sets a attribute as color
|
||||
virtual void setAttribute(const c8* attributeName, video::SColor color);
|
||||
|
||||
//! Gets an attribute as color
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual video::SColor getAttributeAsColor(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as color
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual video::SColor getAttributeAsColor(s32 index);
|
||||
|
||||
//! Sets an attribute as color
|
||||
virtual void setAttribute(s32 index, video::SColor color);
|
||||
|
||||
/*
|
||||
|
||||
SColorf Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as floating point color
|
||||
virtual void addColorf(const c8* attributeName, video::SColorf value);
|
||||
|
||||
//! Sets a attribute as floating point color
|
||||
virtual void setAttribute(const c8* attributeName, video::SColorf color);
|
||||
|
||||
//! Gets an attribute as floating point color
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual video::SColorf getAttributeAsColorf(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as floating point color
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual video::SColorf getAttributeAsColorf(s32 index);
|
||||
|
||||
//! Sets an attribute as floating point color
|
||||
virtual void setAttribute(s32 index, video::SColorf color);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Vector3d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 3d vector
|
||||
virtual void addVector3d(const c8* attributeName, core::vector3df value);
|
||||
|
||||
//! Sets a attribute as 3d vector
|
||||
virtual void setAttribute(const c8* attributeName, core::vector3df v);
|
||||
|
||||
//! Gets an attribute as 3d vector
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::vector3df getAttributeAsVector3d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as 3d vector
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::vector3df getAttributeAsVector3d(s32 index);
|
||||
|
||||
//! Sets an attribute as vector
|
||||
virtual void setAttribute(s32 index, core::vector3df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Vector2d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 2d vector
|
||||
virtual void addVector2d(const c8* attributeName, core::vector2df value);
|
||||
|
||||
//! Sets a attribute as 2d vector
|
||||
virtual void setAttribute(const c8* attributeName, core::vector2df v);
|
||||
|
||||
//! Gets an attribute as 2d vector
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::vector2df getAttributeAsVector2d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as 3d vector
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::vector2df getAttributeAsVector2d(s32 index);
|
||||
|
||||
//! Sets an attribute as vector
|
||||
virtual void setAttribute(s32 index, core::vector2df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Position2d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 2d position
|
||||
virtual void addPosition2d(const c8* attributeName, core::position2di value);
|
||||
|
||||
//! Sets a attribute as 2d position
|
||||
virtual void setAttribute(const c8* attributeName, core::position2di v);
|
||||
|
||||
//! Gets an attribute as position
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::position2di getAttributeAsPosition2d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as position
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::position2di getAttributeAsPosition2d(s32 index);
|
||||
|
||||
//! Sets an attribute as 2d position
|
||||
virtual void setAttribute(s32 index, core::position2di v);
|
||||
|
||||
/*
|
||||
|
||||
Rectangle Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as rectangle
|
||||
virtual void addRect(const c8* attributeName, core::rect<s32> value);
|
||||
|
||||
//! Sets an attribute as rectangle
|
||||
virtual void setAttribute(const c8* attributeName, core::rect<s32> v);
|
||||
|
||||
//! Gets an attribute as rectangle
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::rect<s32> getAttributeAsRect(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as rectangle
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::rect<s32> getAttributeAsRect(s32 index);
|
||||
|
||||
//! Sets an attribute as rectangle
|
||||
virtual void setAttribute(s32 index, core::rect<s32> v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Dimension2d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as dimension2d
|
||||
virtual void addDimension2d(const c8* attributeName, core::dimension2d<u32> value);
|
||||
|
||||
//! Sets an attribute as dimension2d
|
||||
virtual void setAttribute(const c8* attributeName, core::dimension2d<u32> v);
|
||||
|
||||
//! Gets an attribute as dimension2d
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::dimension2d<u32> getAttributeAsDimension2d(const c8* attributeName) const;
|
||||
|
||||
//! Gets an attribute as dimension2d
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::dimension2d<u32> getAttributeAsDimension2d(s32 index) const;
|
||||
|
||||
//! Sets an attribute as dimension2d
|
||||
virtual void setAttribute(s32 index, core::dimension2d<u32> v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
matrix attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as matrix
|
||||
virtual void addMatrix(const c8* attributeName, const core::matrix4& v);
|
||||
|
||||
//! Sets an attribute as matrix
|
||||
virtual void setAttribute(const c8* attributeName, const core::matrix4& v);
|
||||
|
||||
//! Gets an attribute as a matrix4
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::matrix4 getAttributeAsMatrix(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as matrix
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::matrix4 getAttributeAsMatrix(s32 index);
|
||||
|
||||
//! Sets an attribute as matrix
|
||||
virtual void setAttribute(s32 index, const core::matrix4& v);
|
||||
|
||||
/*
|
||||
quaternion attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as quaternion
|
||||
virtual void addQuaternion(const c8* attributeName, core::quaternion v);
|
||||
|
||||
//! Sets an attribute as quaternion
|
||||
virtual void setAttribute(const c8* attributeName, core::quaternion v);
|
||||
|
||||
//! Gets an attribute as a quaternion
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::quaternion getAttributeAsQuaternion(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as quaternion
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::quaternion getAttributeAsQuaternion(s32 index);
|
||||
|
||||
//! Sets an attribute as quaternion
|
||||
virtual void setAttribute(s32 index, core::quaternion v);
|
||||
|
||||
/*
|
||||
|
||||
3d bounding box
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as axis aligned bounding box
|
||||
virtual void addBox3d(const c8* attributeName, core::aabbox3df v);
|
||||
|
||||
//! Sets an attribute as axis aligned bounding box
|
||||
virtual void setAttribute(const c8* attributeName, core::aabbox3df v);
|
||||
|
||||
//! Gets an attribute as a axis aligned bounding box
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::aabbox3df getAttributeAsBox3d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as axis aligned bounding box
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::aabbox3df getAttributeAsBox3d(s32 index);
|
||||
|
||||
//! Sets an attribute as axis aligned bounding box
|
||||
virtual void setAttribute(s32 index, core::aabbox3df v);
|
||||
|
||||
/*
|
||||
|
||||
plane
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 3d plane
|
||||
virtual void addPlane3d(const c8* attributeName, core::plane3df v);
|
||||
|
||||
//! Sets an attribute as 3d plane
|
||||
virtual void setAttribute(const c8* attributeName, core::plane3df v);
|
||||
|
||||
//! Gets an attribute as a 3d plane
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::plane3df getAttributeAsPlane3d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as 3d plane
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::plane3df getAttributeAsPlane3d(s32 index);
|
||||
|
||||
//! Sets an attribute as 3d plane
|
||||
virtual void setAttribute(s32 index, core::plane3df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
3d triangle
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 3d triangle
|
||||
virtual void addTriangle3d(const c8* attributeName, core::triangle3df v);
|
||||
|
||||
//! Sets an attribute as 3d trianle
|
||||
virtual void setAttribute(const c8* attributeName, core::triangle3df v);
|
||||
|
||||
//! Gets an attribute as a 3d triangle
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::triangle3df getAttributeAsTriangle3d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as 3d triangle
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::triangle3df getAttributeAsTriangle3d(s32 index);
|
||||
|
||||
//! Sets an attribute as 3d triangle
|
||||
virtual void setAttribute(s32 index, core::triangle3df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
line 2d
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as a 2d line
|
||||
virtual void addLine2d(const c8* attributeName, core::line2df v);
|
||||
|
||||
//! Sets an attribute as a 2d line
|
||||
virtual void setAttribute(const c8* attributeName, core::line2df v);
|
||||
|
||||
//! Gets an attribute as a 2d line
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::line2df getAttributeAsLine2d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as a 2d line
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::line2df getAttributeAsLine2d(s32 index);
|
||||
|
||||
//! Sets an attribute as a 2d line
|
||||
virtual void setAttribute(s32 index, core::line2df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
line 3d
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as a 3d line
|
||||
virtual void addLine3d(const c8* attributeName, core::line3df v);
|
||||
|
||||
//! Sets an attribute as a 3d line
|
||||
virtual void setAttribute(const c8* attributeName, core::line3df v);
|
||||
|
||||
//! Gets an attribute as a 3d line
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::line3df getAttributeAsLine3d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as a 3d line
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::line3df getAttributeAsLine3d(s32 index);
|
||||
|
||||
//! Sets an attribute as a 3d line
|
||||
virtual void setAttribute(s32 index, core::line3df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Texture Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as texture reference
|
||||
virtual void addTexture(const c8* attributeName, video::ITexture* texture, const io::path& filename = "");
|
||||
|
||||
//! Sets an attribute as texture reference
|
||||
virtual void setAttribute(const c8* attributeName, video::ITexture* texture, const io::path& filename = "");
|
||||
|
||||
//! Gets an attribute as texture reference
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
virtual video::ITexture* getAttributeAsTexture(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as texture reference
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual video::ITexture* getAttributeAsTexture(s32 index);
|
||||
|
||||
//! Sets an attribute as texture reference
|
||||
virtual void setAttribute(s32 index, video::ITexture* texture, const io::path& filename = "");
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
User Pointer Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as user pointner
|
||||
virtual void addUserPointer(const c8* attributeName, void* userPointer);
|
||||
|
||||
//! Sets an attribute as user pointer
|
||||
virtual void setAttribute(const c8* attributeName, void* userPointer);
|
||||
|
||||
//! Gets an attribute as user pointer
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
virtual void* getAttributeAsUserPointer(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as user pointer
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual void* getAttributeAsUserPointer(s32 index);
|
||||
|
||||
//! Sets an attribute as user pointer
|
||||
virtual void setAttribute(s32 index, void* userPointer);
|
||||
|
||||
protected:
|
||||
|
||||
void readAttributeFromXML(io::IXMLReader* reader);
|
||||
|
||||
core::array<IAttribute*> Attributes;
|
||||
|
||||
IAttribute* getAttributeP(const c8* attributeName) const;
|
||||
|
||||
video::IVideoDriver* Driver;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,294 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CBillboardSceneNode.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CBillboardSceneNode::CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position, const core::dimension2d<f32>& size,
|
||||
video::SColor colorTop, video::SColor colorBottom)
|
||||
: IBillboardSceneNode(parent, mgr, id, position)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBillboardSceneNode");
|
||||
#endif
|
||||
|
||||
setSize(size);
|
||||
|
||||
indices[0] = 0;
|
||||
indices[1] = 2;
|
||||
indices[2] = 1;
|
||||
indices[3] = 0;
|
||||
indices[4] = 3;
|
||||
indices[5] = 2;
|
||||
|
||||
vertices[0].TCoords.set(1.0f, 1.0f);
|
||||
vertices[0].Color = colorBottom;
|
||||
|
||||
vertices[1].TCoords.set(1.0f, 0.0f);
|
||||
vertices[1].Color = colorTop;
|
||||
|
||||
vertices[2].TCoords.set(0.0f, 0.0f);
|
||||
vertices[2].Color = colorTop;
|
||||
|
||||
vertices[3].TCoords.set(0.0f, 1.0f);
|
||||
vertices[3].Color = colorBottom;
|
||||
}
|
||||
|
||||
|
||||
//! pre render event
|
||||
void CBillboardSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void CBillboardSceneNode::render()
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
ICameraSceneNode* camera = SceneManager->getActiveCamera();
|
||||
|
||||
if (!camera || !driver)
|
||||
return;
|
||||
|
||||
// make billboard look to camera
|
||||
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
|
||||
core::vector3df campos = camera->getAbsolutePosition();
|
||||
core::vector3df target = camera->getTarget();
|
||||
core::vector3df up = camera->getUpVector();
|
||||
core::vector3df view = target - campos;
|
||||
view.normalize();
|
||||
|
||||
core::vector3df horizontal = up.crossProduct(view);
|
||||
if ( horizontal.getLength() == 0 )
|
||||
{
|
||||
horizontal.set(up.Y,up.X,up.Z);
|
||||
}
|
||||
horizontal.normalize();
|
||||
core::vector3df topHorizontal = horizontal * 0.5f * TopEdgeWidth;
|
||||
horizontal *= 0.5f * Size.Width;
|
||||
|
||||
// pointing down!
|
||||
core::vector3df vertical = horizontal.crossProduct(view);
|
||||
vertical.normalize();
|
||||
vertical *= 0.5f * Size.Height;
|
||||
|
||||
view *= -1.0f;
|
||||
|
||||
for (s32 i=0; i<4; ++i)
|
||||
vertices[i].Normal = view;
|
||||
|
||||
/* Vertices are:
|
||||
2--1
|
||||
|\ |
|
||||
| \|
|
||||
3--0
|
||||
*/
|
||||
vertices[0].Pos = pos + horizontal + vertical;
|
||||
vertices[1].Pos = pos + topHorizontal - vertical;
|
||||
vertices[2].Pos = pos - topHorizontal - vertical;
|
||||
vertices[3].Pos = pos - horizontal + vertical;
|
||||
|
||||
// draw
|
||||
|
||||
if (DebugDataVisible & scene::EDS_BBOX)
|
||||
{
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
video::SMaterial m;
|
||||
m.Lighting = false;
|
||||
driver->setMaterial(m);
|
||||
driver->draw3DBox(BBox, video::SColor(0,208,195,152));
|
||||
}
|
||||
|
||||
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
|
||||
|
||||
driver->setMaterial(Material);
|
||||
|
||||
driver->drawIndexedTriangleList(vertices, 4, indices, 2);
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CBillboardSceneNode::getBoundingBox() const
|
||||
{
|
||||
return BBox;
|
||||
}
|
||||
|
||||
|
||||
//! sets the size of the billboard
|
||||
void CBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
|
||||
{
|
||||
Size = size;
|
||||
|
||||
if (core::equals(Size.Width, 0.0f))
|
||||
Size.Width = 1.0f;
|
||||
TopEdgeWidth = Size.Width;
|
||||
|
||||
if (core::equals(Size.Height, 0.0f))
|
||||
Size.Height = 1.0f;
|
||||
|
||||
const f32 avg = (Size.Width + Size.Height)/6;
|
||||
BBox.MinEdge.set(-avg,-avg,-avg);
|
||||
BBox.MaxEdge.set(avg,avg,avg);
|
||||
}
|
||||
|
||||
|
||||
void CBillboardSceneNode::setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth)
|
||||
{
|
||||
Size.set(bottomEdgeWidth, height);
|
||||
TopEdgeWidth = topEdgeWidth;
|
||||
|
||||
if (core::equals(Size.Height, 0.0f))
|
||||
Size.Height = 1.0f;
|
||||
|
||||
if (core::equals(Size.Width, 0.f) && core::equals(TopEdgeWidth, 0.f))
|
||||
{
|
||||
Size.Width = 1.0f;
|
||||
TopEdgeWidth = 1.0f;
|
||||
}
|
||||
|
||||
const f32 avg = (core::max_(Size.Width,TopEdgeWidth) + Size.Height)/6;
|
||||
BBox.MinEdge.set(-avg,-avg,-avg);
|
||||
BBox.MaxEdge.set(avg,avg,avg);
|
||||
}
|
||||
|
||||
|
||||
video::SMaterial& CBillboardSceneNode::getMaterial(u32 i)
|
||||
{
|
||||
return Material;
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
u32 CBillboardSceneNode::getMaterialCount() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! gets the size of the billboard
|
||||
const core::dimension2d<f32>& CBillboardSceneNode::getSize() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the widths of the top and bottom edges of the billboard.
|
||||
void CBillboardSceneNode::getSize(f32& height, f32& bottomEdgeWidth,
|
||||
f32& topEdgeWidth) const
|
||||
{
|
||||
height = Size.Height;
|
||||
bottomEdgeWidth = Size.Width;
|
||||
topEdgeWidth = TopEdgeWidth;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
void CBillboardSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
IBillboardSceneNode::serializeAttributes(out, options);
|
||||
|
||||
out->addFloat("Width", Size.Width);
|
||||
out->addFloat("TopEdgeWidth", TopEdgeWidth);
|
||||
out->addFloat("Height", Size.Height);
|
||||
out->addColor("Shade_Top", vertices[1].Color);
|
||||
out->addColor("Shade_Down", vertices[0].Color);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
void CBillboardSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
IBillboardSceneNode::deserializeAttributes(in, options);
|
||||
|
||||
Size.Width = in->getAttributeAsFloat("Width");
|
||||
Size.Height = in->getAttributeAsFloat("Height");
|
||||
|
||||
if (in->existsAttribute("TopEdgeWidth"))
|
||||
{
|
||||
TopEdgeWidth = in->getAttributeAsFloat("TopEdgeWidth");
|
||||
if (Size.Width != TopEdgeWidth)
|
||||
setSize(Size.Height, Size.Width, TopEdgeWidth);
|
||||
}
|
||||
else
|
||||
setSize(Size);
|
||||
vertices[1].Color = in->getAttributeAsColor("Shade_Top");
|
||||
vertices[0].Color = in->getAttributeAsColor("Shade_Down");
|
||||
vertices[2].Color = vertices[1].Color;
|
||||
vertices[3].Color = vertices[0].Color;
|
||||
}
|
||||
|
||||
|
||||
//! Set the color of all vertices of the billboard
|
||||
//! \param overallColor: the color to set
|
||||
void CBillboardSceneNode::setColor(const video::SColor& overallColor)
|
||||
{
|
||||
for(u32 vertex = 0; vertex < 4; ++vertex)
|
||||
vertices[vertex].Color = overallColor;
|
||||
}
|
||||
|
||||
|
||||
//! Set the color of the top and bottom vertices of the billboard
|
||||
//! \param topColor: the color to set the top vertices
|
||||
//! \param bottomColor: the color to set the bottom vertices
|
||||
void CBillboardSceneNode::setColor(const video::SColor& topColor,
|
||||
const video::SColor& bottomColor)
|
||||
{
|
||||
vertices[0].Color = bottomColor;
|
||||
vertices[1].Color = topColor;
|
||||
vertices[2].Color = topColor;
|
||||
vertices[3].Color = bottomColor;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the color of the top and bottom vertices of the billboard
|
||||
//! \param[out] topColor: stores the color of the top vertices
|
||||
//! \param[out] bottomColor: stores the color of the bottom vertices
|
||||
void CBillboardSceneNode::getColor(video::SColor& topColor,
|
||||
video::SColor& bottomColor) const
|
||||
{
|
||||
bottomColor = vertices[0].Color;
|
||||
topColor = vertices[1].Color;
|
||||
}
|
||||
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CBillboardSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CBillboardSceneNode* nb = new CBillboardSceneNode(newParent,
|
||||
newManager, ID, RelativeTranslation, Size);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->Material = Material;
|
||||
nb->TopEdgeWidth = this->TopEdgeWidth;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IBillboardSceneNode.h"
|
||||
#include "S3DVertex.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Scene node which is a billboard. A billboard is like a 3d sprite: A 2d element,
|
||||
//! which always looks to the camera.
|
||||
class CBillboardSceneNode : virtual public IBillboardSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position, const core::dimension2d<f32>& size,
|
||||
video::SColor colorTop=video::SColor(0xFFFFFFFF),
|
||||
video::SColor colorBottom=video::SColor(0xFFFFFFFF));
|
||||
|
||||
//! pre render event
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! render
|
||||
virtual void render();
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! sets the size of the billboard
|
||||
virtual void setSize(const core::dimension2d<f32>& size);
|
||||
|
||||
//! Sets the widths of the top and bottom edges of the billboard independently.
|
||||
virtual void setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth);
|
||||
|
||||
//! gets the size of the billboard
|
||||
virtual const core::dimension2d<f32>& getSize() const;
|
||||
|
||||
//! Gets the widths of the top and bottom edges of the billboard.
|
||||
virtual void getSize(f32& height, f32& bottomEdgeWidth, f32& topEdgeWidth) const;
|
||||
|
||||
virtual video::SMaterial& getMaterial(u32 i);
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
virtual u32 getMaterialCount() const;
|
||||
|
||||
//! Set the color of all vertices of the billboard
|
||||
//! \param overallColor: the color to set
|
||||
virtual void setColor(const video::SColor& overallColor);
|
||||
|
||||
//! Set the color of the top and bottom vertices of the billboard
|
||||
//! \param topColor: the color to set the top vertices
|
||||
//! \param bottomColor: the color to set the bottom vertices
|
||||
virtual void setColor(const video::SColor& topColor,
|
||||
const video::SColor& bottomColor);
|
||||
|
||||
//! Gets the color of the top and bottom vertices of the billboard
|
||||
//! \param[out] topColor: stores the color of the top vertices
|
||||
//! \param[out] bottomColor: stores the color of the bottom vertices
|
||||
virtual void getColor(video::SColor& topColor,
|
||||
video::SColor& bottomColor) const;
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_BILLBOARD; }
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
protected:
|
||||
|
||||
//! Size.Width is the bottom edge width
|
||||
core::dimension2d<f32> Size;
|
||||
f32 TopEdgeWidth;
|
||||
core::aabbox3d<f32> BBox;
|
||||
video::SMaterial Material;
|
||||
|
||||
video::S3DVertex vertices[4];
|
||||
u16 indices[6];
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,812 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef _C_BLIT_H_INCLUDED_
|
||||
#define _C_BLIT_H_INCLUDED_
|
||||
|
||||
#include "SoftwareDriver2_helper.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
struct SBlitJob
|
||||
{
|
||||
AbsRectangle Dest;
|
||||
AbsRectangle Source;
|
||||
|
||||
u32 argb;
|
||||
|
||||
void * src;
|
||||
void * dst;
|
||||
|
||||
s32 width;
|
||||
s32 height;
|
||||
|
||||
u32 srcPitch;
|
||||
u32 dstPitch;
|
||||
|
||||
u32 srcPixelMul;
|
||||
u32 dstPixelMul;
|
||||
|
||||
bool stretch;
|
||||
float x_stretch;
|
||||
float y_stretch;
|
||||
|
||||
SBlitJob() : stretch(false) {}
|
||||
};
|
||||
|
||||
// Bitfields Cohen Sutherland
|
||||
enum eClipCode
|
||||
{
|
||||
CLIPCODE_EMPTY = 0,
|
||||
CLIPCODE_BOTTOM = 1,
|
||||
CLIPCODE_TOP = 2,
|
||||
CLIPCODE_LEFT = 4,
|
||||
CLIPCODE_RIGHT = 8
|
||||
};
|
||||
|
||||
inline u32 GetClipCode( const AbsRectangle &r, const core::position2d<s32> &p )
|
||||
{
|
||||
u32 code = CLIPCODE_EMPTY;
|
||||
|
||||
if ( p.X < r.x0 )
|
||||
code = CLIPCODE_LEFT;
|
||||
else
|
||||
if ( p.X > r.x1 )
|
||||
code = CLIPCODE_RIGHT;
|
||||
|
||||
if ( p.Y < r.y0 )
|
||||
code |= CLIPCODE_TOP;
|
||||
else
|
||||
if ( p.Y > r.y1 )
|
||||
code |= CLIPCODE_BOTTOM;
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
inline void GetClip(AbsRectangle &clipping, video::IImage * t)
|
||||
{
|
||||
clipping.x0 = 0;
|
||||
clipping.y0 = 0;
|
||||
clipping.x1 = t->getDimension().Width - 1;
|
||||
clipping.y1 = t->getDimension().Height - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
return alpha in [0;256] Granularity from 32-Bit ARGB
|
||||
add highbit alpha ( alpha > 127 ? + 1 )
|
||||
*/
|
||||
static inline u32 extractAlpha(const u32 c)
|
||||
{
|
||||
return ( c >> 24 ) + ( c >> 31 );
|
||||
}
|
||||
|
||||
/*
|
||||
return alpha in [0;255] Granularity and 32-Bit ARGB
|
||||
add highbit alpha ( alpha > 127 ? + 1 )
|
||||
*/
|
||||
static inline u32 packAlpha(const u32 c)
|
||||
{
|
||||
return (c > 127 ? c - 1 : c) << 24;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Scale Color by (1/value)
|
||||
value 0 - 256 ( alpha )
|
||||
*/
|
||||
inline u32 PixelLerp32(const u32 source, const u32 value)
|
||||
{
|
||||
u32 srcRB = source & 0x00FF00FF;
|
||||
u32 srcXG = (source & 0xFF00FF00) >> 8;
|
||||
|
||||
srcRB *= value;
|
||||
srcXG *= value;
|
||||
|
||||
srcRB >>= 8;
|
||||
//srcXG >>= 8;
|
||||
|
||||
srcXG &= 0xFF00FF00;
|
||||
srcRB &= 0x00FF00FF;
|
||||
|
||||
return srcRB | srcXG;
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_TextureCopy_x_to_x( const SBlitJob * job )
|
||||
{
|
||||
const u32 w = job->width;
|
||||
const u32 h = job->height;
|
||||
if (job->stretch)
|
||||
{
|
||||
const u32 *src = static_cast<const u32*>(job->src);
|
||||
u32 *dst = static_cast<u32*>(job->dst);
|
||||
const float wscale = 1.f/job->x_stretch;
|
||||
const float hscale = 1.f/job->y_stretch;
|
||||
|
||||
for ( u32 dy = 0; dy < h; ++dy )
|
||||
{
|
||||
const u32 src_y = (u32)(dy*hscale);
|
||||
src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
|
||||
|
||||
for ( u32 dx = 0; dx < w; ++dx )
|
||||
{
|
||||
const u32 src_x = (u32)(dx*wscale);
|
||||
dst[dx] = src[src_x];
|
||||
}
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 widthPitch = job->width * job->dstPixelMul;
|
||||
const void *src = (void*) job->src;
|
||||
void *dst = (void*) job->dst;
|
||||
|
||||
for ( u32 dy = 0; dy != h; ++dy )
|
||||
{
|
||||
memcpy( dst, src, widthPitch );
|
||||
|
||||
src = (void*) ( (u8*) (src) + job->srcPitch );
|
||||
dst = (void*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_TextureCopy_32_to_16( const SBlitJob * job )
|
||||
{
|
||||
const u32 w = job->width;
|
||||
const u32 h = job->height;
|
||||
const u32 *src = static_cast<const u32*>(job->src);
|
||||
u16 *dst = static_cast<u16*>(job->dst);
|
||||
|
||||
if (job->stretch)
|
||||
{
|
||||
const float wscale = 1.f/job->x_stretch;
|
||||
const float hscale = 1.f/job->y_stretch;
|
||||
|
||||
for ( u32 dy = 0; dy < h; ++dy )
|
||||
{
|
||||
const u32 src_y = (u32)(dy*hscale);
|
||||
src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
|
||||
|
||||
for ( u32 dx = 0; dx < w; ++dx )
|
||||
{
|
||||
const u32 src_x = (u32)(dx*wscale);
|
||||
//16 bit Blitter depends on pre-multiplied color
|
||||
const u32 s = PixelLerp32( src[src_x] | 0xFF000000, extractAlpha( src[src_x] ) );
|
||||
dst[dx] = video::A8R8G8B8toA1R5G5B5( s );
|
||||
}
|
||||
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( u32 dy = 0; dy != h; ++dy )
|
||||
{
|
||||
for ( u32 dx = 0; dx != w; ++dx )
|
||||
{
|
||||
//16 bit Blitter depends on pre-multiplied color
|
||||
const u32 s = PixelLerp32( src[dx] | 0xFF000000, extractAlpha( src[dx] ) );
|
||||
dst[dx] = video::A8R8G8B8toA1R5G5B5( s );
|
||||
}
|
||||
|
||||
src = (u32*) ( (u8*) (src) + job->srcPitch );
|
||||
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_TextureCopy_24_to_16( const SBlitJob * job )
|
||||
{
|
||||
const u32 w = job->width;
|
||||
const u32 h = job->height;
|
||||
const u8 *src = static_cast<const u8*>(job->src);
|
||||
u16 *dst = static_cast<u16*>(job->dst);
|
||||
|
||||
if (job->stretch)
|
||||
{
|
||||
const float wscale = 3.f/job->x_stretch;
|
||||
const float hscale = 1.f/job->y_stretch;
|
||||
|
||||
for ( u32 dy = 0; dy < h; ++dy )
|
||||
{
|
||||
const u32 src_y = (u32)(dy*hscale);
|
||||
src = (u8*)(job->src) + job->srcPitch*src_y;
|
||||
|
||||
for ( u32 dx = 0; dx < w; ++dx )
|
||||
{
|
||||
const u8* src_x = src+(u32)(dx*wscale);
|
||||
dst[dx] = video::RGBA16(src_x[0], src_x[1], src_x[2]);
|
||||
}
|
||||
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( u32 dy = 0; dy != h; ++dy )
|
||||
{
|
||||
const u8* s = src;
|
||||
for ( u32 dx = 0; dx != w; ++dx )
|
||||
{
|
||||
dst[dx] = video::RGBA16(s[0], s[1], s[2]);
|
||||
s += 3;
|
||||
}
|
||||
|
||||
src = src+job->srcPitch;
|
||||
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_TextureCopy_16_to_32( const SBlitJob * job )
|
||||
{
|
||||
const u32 w = job->width;
|
||||
const u32 h = job->height;
|
||||
const u16 *src = static_cast<const u16*>(job->src);
|
||||
u32 *dst = static_cast<u32*>(job->dst);
|
||||
|
||||
if (job->stretch)
|
||||
{
|
||||
const float wscale = 1.f/job->x_stretch;
|
||||
const float hscale = 1.f/job->y_stretch;
|
||||
|
||||
for ( u32 dy = 0; dy < h; ++dy )
|
||||
{
|
||||
const u32 src_y = (u32)(dy*hscale);
|
||||
src = (u16*) ( (u8*) (job->src) + job->srcPitch*src_y );
|
||||
|
||||
for ( u32 dx = 0; dx < w; ++dx )
|
||||
{
|
||||
const u32 src_x = (u32)(dx*wscale);
|
||||
dst[dx] = video::A1R5G5B5toA8R8G8B8(src[src_x]);
|
||||
}
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( u32 dy = 0; dy != h; ++dy )
|
||||
{
|
||||
for ( u32 dx = 0; dx != w; ++dx )
|
||||
{
|
||||
dst[dx] = video::A1R5G5B5toA8R8G8B8( src[dx] );
|
||||
}
|
||||
|
||||
src = (u16*) ( (u8*) (src) + job->srcPitch );
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void executeBlit_TextureCopy_16_to_24( const SBlitJob * job )
|
||||
{
|
||||
const u32 w = job->width;
|
||||
const u32 h = job->height;
|
||||
const u16 *src = static_cast<const u16*>(job->src);
|
||||
u8 *dst = static_cast<u8*>(job->dst);
|
||||
|
||||
if (job->stretch)
|
||||
{
|
||||
const float wscale = 1.f/job->x_stretch;
|
||||
const float hscale = 1.f/job->y_stretch;
|
||||
|
||||
for ( u32 dy = 0; dy < h; ++dy )
|
||||
{
|
||||
const u32 src_y = (u32)(dy*hscale);
|
||||
src = (u16*) ( (u8*) (job->src) + job->srcPitch*src_y );
|
||||
|
||||
for ( u32 dx = 0; dx < w; ++dx )
|
||||
{
|
||||
const u32 src_x = (u32)(dx*wscale);
|
||||
u32 color = video::A1R5G5B5toA8R8G8B8(src[src_x]);
|
||||
u8 * writeTo = &dst[dx * 3];
|
||||
*writeTo++ = (color >> 16)& 0xFF;
|
||||
*writeTo++ = (color >> 8) & 0xFF;
|
||||
*writeTo++ = color & 0xFF;
|
||||
}
|
||||
dst += job->dstPitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( u32 dy = 0; dy != h; ++dy )
|
||||
{
|
||||
for ( u32 dx = 0; dx != w; ++dx )
|
||||
{
|
||||
u32 color = video::A1R5G5B5toA8R8G8B8(src[dx]);
|
||||
u8 * writeTo = &dst[dx * 3];
|
||||
*writeTo++ = (color >> 16)& 0xFF;
|
||||
*writeTo++ = (color >> 8) & 0xFF;
|
||||
*writeTo++ = color & 0xFF;
|
||||
}
|
||||
|
||||
src = (u16*) ( (u8*) (src) + job->srcPitch );
|
||||
dst += job->dstPitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_TextureCopy_24_to_32( const SBlitJob * job )
|
||||
{
|
||||
const u32 w = job->width;
|
||||
const u32 h = job->height;
|
||||
const u8 *src = static_cast<const u8*>(job->src);
|
||||
u32 *dst = static_cast<u32*>(job->dst);
|
||||
|
||||
if (job->stretch)
|
||||
{
|
||||
const float wscale = 3.f/job->x_stretch;
|
||||
const float hscale = 1.f/job->y_stretch;
|
||||
|
||||
for ( u32 dy = 0; dy < h; ++dy )
|
||||
{
|
||||
const u32 src_y = (u32)(dy*hscale);
|
||||
src = (const u8*)job->src+(job->srcPitch*src_y);
|
||||
|
||||
for ( u32 dx = 0; dx < w; ++dx )
|
||||
{
|
||||
const u8* s = src+(u32)(dx*wscale);
|
||||
dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2];
|
||||
}
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( s32 dy = 0; dy != job->height; ++dy )
|
||||
{
|
||||
const u8* s = src;
|
||||
|
||||
for ( s32 dx = 0; dx != job->width; ++dx )
|
||||
{
|
||||
dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2];
|
||||
s += 3;
|
||||
}
|
||||
|
||||
src = src + job->srcPitch;
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void executeBlit_TextureCopy_32_to_24( const SBlitJob * job )
|
||||
{
|
||||
const u32 w = job->width;
|
||||
const u32 h = job->height;
|
||||
const u32 *src = static_cast<const u32*>(job->src);
|
||||
u8 *dst = static_cast<u8*>(job->dst);
|
||||
|
||||
if (job->stretch)
|
||||
{
|
||||
const float wscale = 1.f/job->x_stretch;
|
||||
const float hscale = 1.f/job->y_stretch;
|
||||
|
||||
for ( u32 dy = 0; dy < h; ++dy )
|
||||
{
|
||||
const u32 src_y = (u32)(dy*hscale);
|
||||
src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y);
|
||||
|
||||
for ( u32 dx = 0; dx < w; ++dx )
|
||||
{
|
||||
const u32 src_x = src[(u32)(dx*wscale)];
|
||||
u8 * writeTo = &dst[dx * 3];
|
||||
*writeTo++ = (src_x >> 16)& 0xFF;
|
||||
*writeTo++ = (src_x >> 8) & 0xFF;
|
||||
*writeTo++ = src_x & 0xFF;
|
||||
}
|
||||
dst += job->dstPitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( u32 dy = 0; dy != h; ++dy )
|
||||
{
|
||||
for ( u32 dx = 0; dx != w; ++dx )
|
||||
{
|
||||
u8 * writeTo = &dst[dx * 3];
|
||||
*writeTo++ = (src[dx] >> 16)& 0xFF;
|
||||
*writeTo++ = (src[dx] >> 8) & 0xFF;
|
||||
*writeTo++ = src[dx] & 0xFF;
|
||||
}
|
||||
|
||||
src = (u32*) ( (u8*) (src) + job->srcPitch );
|
||||
dst += job->dstPitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_TextureBlend_16_to_16( const SBlitJob * job )
|
||||
{
|
||||
const u32 w = job->width;
|
||||
const u32 h = job->height;
|
||||
const u32 rdx = w>>1;
|
||||
|
||||
const u32 *src = (u32*) job->src;
|
||||
u32 *dst = (u32*) job->dst;
|
||||
|
||||
if (job->stretch)
|
||||
{
|
||||
const float wscale = 1.f/job->x_stretch;
|
||||
const float hscale = 1.f/job->y_stretch;
|
||||
const u32 off = core::if_c_a_else_b(w&1, (u32)((w-1)*wscale), 0);
|
||||
for ( u32 dy = 0; dy < h; ++dy )
|
||||
{
|
||||
const u32 src_y = (u32)(dy*hscale);
|
||||
src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
|
||||
|
||||
for ( u32 dx = 0; dx < rdx; ++dx )
|
||||
{
|
||||
const u32 src_x = (u32)(dx*wscale);
|
||||
dst[dx] = PixelBlend16_simd( dst[dx], src[src_x] );
|
||||
}
|
||||
if ( off )
|
||||
{
|
||||
((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] );
|
||||
}
|
||||
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 off = core::if_c_a_else_b(w&1, w-1, 0);
|
||||
for (u32 dy = 0; dy != h; ++dy )
|
||||
{
|
||||
for (u32 dx = 0; dx != rdx; ++dx )
|
||||
{
|
||||
dst[dx] = PixelBlend16_simd( dst[dx], src[dx] );
|
||||
}
|
||||
|
||||
if ( off )
|
||||
{
|
||||
((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] );
|
||||
}
|
||||
|
||||
src = (u32*) ( (u8*) (src) + job->srcPitch );
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_TextureBlend_32_to_32( const SBlitJob * job )
|
||||
{
|
||||
const u32 w = job->width;
|
||||
const u32 h = job->height;
|
||||
const u32 *src = (u32*) job->src;
|
||||
u32 *dst = (u32*) job->dst;
|
||||
|
||||
if (job->stretch)
|
||||
{
|
||||
const float wscale = 1.f/job->x_stretch;
|
||||
const float hscale = 1.f/job->y_stretch;
|
||||
for ( u32 dy = 0; dy < h; ++dy )
|
||||
{
|
||||
const u32 src_y = (u32)(dy*hscale);
|
||||
src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y );
|
||||
|
||||
for ( u32 dx = 0; dx < w; ++dx )
|
||||
{
|
||||
const u32 src_x = (u32)(dx*wscale);
|
||||
dst[dx] = PixelBlend32( dst[dx], src[src_x] );
|
||||
}
|
||||
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( u32 dy = 0; dy != h; ++dy )
|
||||
{
|
||||
for ( u32 dx = 0; dx != w; ++dx )
|
||||
{
|
||||
dst[dx] = PixelBlend32( dst[dx], src[dx] );
|
||||
}
|
||||
src = (u32*) ( (u8*) (src) + job->srcPitch );
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_TextureBlendColor_16_to_16( const SBlitJob * job )
|
||||
{
|
||||
u16 *src = (u16*) job->src;
|
||||
u16 *dst = (u16*) job->dst;
|
||||
|
||||
u16 blend = video::A8R8G8B8toA1R5G5B5 ( job->argb );
|
||||
for ( s32 dy = 0; dy != job->height; ++dy )
|
||||
{
|
||||
for ( s32 dx = 0; dx != job->width; ++dx )
|
||||
{
|
||||
if ( 0 == (src[dx] & 0x8000) )
|
||||
continue;
|
||||
|
||||
dst[dx] = PixelMul16_2( src[dx], blend );
|
||||
}
|
||||
src = (u16*) ( (u8*) (src) + job->srcPitch );
|
||||
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_TextureBlendColor_32_to_32( const SBlitJob * job )
|
||||
{
|
||||
u32 *src = (u32*) job->src;
|
||||
u32 *dst = (u32*) job->dst;
|
||||
|
||||
for ( s32 dy = 0; dy != job->height; ++dy )
|
||||
{
|
||||
for ( s32 dx = 0; dx != job->width; ++dx )
|
||||
{
|
||||
dst[dx] = PixelBlend32( dst[dx], PixelMul32_2( src[dx], job->argb ) );
|
||||
}
|
||||
src = (u32*) ( (u8*) (src) + job->srcPitch );
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_Color_16_to_16( const SBlitJob * job )
|
||||
{
|
||||
const u16 c = video::A8R8G8B8toA1R5G5B5(job->argb);
|
||||
u16 *dst = (u16*) job->dst;
|
||||
|
||||
for ( s32 dy = 0; dy != job->height; ++dy )
|
||||
{
|
||||
memset16(dst, c, job->srcPitch);
|
||||
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_Color_32_to_32( const SBlitJob * job )
|
||||
{
|
||||
u32 *dst = (u32*) job->dst;
|
||||
|
||||
for ( s32 dy = 0; dy != job->height; ++dy )
|
||||
{
|
||||
memset32( dst, job->argb, job->srcPitch );
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job )
|
||||
{
|
||||
u16 *dst = (u16*) job->dst;
|
||||
|
||||
const u16 alpha = extractAlpha( job->argb ) >> 3;
|
||||
if ( 0 == alpha )
|
||||
return;
|
||||
const u32 src = video::A8R8G8B8toA1R5G5B5( job->argb );
|
||||
|
||||
for ( s32 dy = 0; dy != job->height; ++dy )
|
||||
{
|
||||
for ( s32 dx = 0; dx != job->width; ++dx )
|
||||
{
|
||||
dst[dx] = 0x8000 | PixelBlend16( dst[dx], src, alpha );
|
||||
}
|
||||
dst = (u16*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
static void executeBlit_ColorAlpha_32_to_32( const SBlitJob * job )
|
||||
{
|
||||
u32 *dst = (u32*) job->dst;
|
||||
|
||||
const u32 alpha = extractAlpha( job->argb );
|
||||
const u32 src = job->argb;
|
||||
|
||||
for ( s32 dy = 0; dy != job->height; ++dy )
|
||||
{
|
||||
for ( s32 dx = 0; dx != job->width; ++dx )
|
||||
{
|
||||
dst[dx] = (job->argb & 0xFF000000 ) | PixelBlend32( dst[dx], src, alpha );
|
||||
}
|
||||
dst = (u32*) ( (u8*) (dst) + job->dstPitch );
|
||||
}
|
||||
}
|
||||
|
||||
// Blitter Operation
|
||||
enum eBlitter
|
||||
{
|
||||
BLITTER_INVALID = 0,
|
||||
BLITTER_COLOR,
|
||||
BLITTER_COLOR_ALPHA,
|
||||
BLITTER_TEXTURE,
|
||||
BLITTER_TEXTURE_ALPHA_BLEND,
|
||||
BLITTER_TEXTURE_ALPHA_COLOR_BLEND
|
||||
};
|
||||
|
||||
typedef void (*tExecuteBlit) ( const SBlitJob * job );
|
||||
|
||||
|
||||
/*!
|
||||
*/
|
||||
struct blitterTable
|
||||
{
|
||||
eBlitter operation;
|
||||
s32 destFormat;
|
||||
s32 sourceFormat;
|
||||
tExecuteBlit func;
|
||||
};
|
||||
|
||||
static const blitterTable blitTable[] =
|
||||
{
|
||||
{ BLITTER_TEXTURE, -2, -2, executeBlit_TextureCopy_x_to_x },
|
||||
{ BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_16 },
|
||||
{ BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_16 },
|
||||
{ BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_32 },
|
||||
{ BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_32 },
|
||||
{ BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_24 },
|
||||
{ BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_24 },
|
||||
{ BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlend_16_to_16 },
|
||||
{ BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlend_32_to_32 },
|
||||
{ BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlendColor_16_to_16 },
|
||||
{ BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlendColor_32_to_32 },
|
||||
{ BLITTER_COLOR, video::ECF_A1R5G5B5, -1, executeBlit_Color_16_to_16 },
|
||||
{ BLITTER_COLOR, video::ECF_A8R8G8B8, -1, executeBlit_Color_32_to_32 },
|
||||
{ BLITTER_COLOR_ALPHA, video::ECF_A1R5G5B5, -1, executeBlit_ColorAlpha_16_to_16 },
|
||||
{ BLITTER_COLOR_ALPHA, video::ECF_A8R8G8B8, -1, executeBlit_ColorAlpha_32_to_32 },
|
||||
{ BLITTER_INVALID, -1, -1, 0 }
|
||||
};
|
||||
|
||||
|
||||
static inline tExecuteBlit getBlitter2( eBlitter operation,const video::IImage * dest,const video::IImage * source )
|
||||
{
|
||||
video::ECOLOR_FORMAT sourceFormat = (video::ECOLOR_FORMAT) ( source ? source->getColorFormat() : -1 );
|
||||
video::ECOLOR_FORMAT destFormat = (video::ECOLOR_FORMAT) ( dest ? dest->getColorFormat() : -1 );
|
||||
|
||||
const blitterTable * b = blitTable;
|
||||
|
||||
while ( b->operation != BLITTER_INVALID )
|
||||
{
|
||||
if ( b->operation == operation )
|
||||
{
|
||||
if (( b->destFormat == -1 || b->destFormat == destFormat ) &&
|
||||
( b->sourceFormat == -1 || b->sourceFormat == sourceFormat ) )
|
||||
return b->func;
|
||||
else
|
||||
if ( b->destFormat == -2 && ( sourceFormat == destFormat ) )
|
||||
return b->func;
|
||||
}
|
||||
b += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// bounce clipping to texture
|
||||
inline void setClip ( AbsRectangle &out, const core::rect<s32> *clip,
|
||||
const video::IImage * tex, s32 passnative )
|
||||
{
|
||||
if ( clip && 0 == tex && passnative )
|
||||
{
|
||||
out.x0 = clip->UpperLeftCorner.X;
|
||||
out.x1 = clip->LowerRightCorner.X;
|
||||
out.y0 = clip->UpperLeftCorner.Y;
|
||||
out.y1 = clip->LowerRightCorner.Y;
|
||||
return;
|
||||
}
|
||||
|
||||
const s32 w = tex ? tex->getDimension().Width : 0;
|
||||
const s32 h = tex ? tex->getDimension().Height : 0;
|
||||
if ( clip )
|
||||
{
|
||||
out.x0 = core::s32_clamp ( clip->UpperLeftCorner.X, 0, w );
|
||||
out.x1 = core::s32_clamp ( clip->LowerRightCorner.X, out.x0, w );
|
||||
out.y0 = core::s32_clamp ( clip->UpperLeftCorner.Y, 0, h );
|
||||
out.y1 = core::s32_clamp ( clip->LowerRightCorner.Y, out.y0, h );
|
||||
}
|
||||
else
|
||||
{
|
||||
out.x0 = 0;
|
||||
out.y0 = 0;
|
||||
out.x1 = w;
|
||||
out.y1 = h;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
a generic 2D Blitter
|
||||
*/
|
||||
static s32 Blit(eBlitter operation,
|
||||
video::IImage * dest,
|
||||
const core::rect<s32> *destClipping,
|
||||
const core::position2d<s32> *destPos,
|
||||
video::IImage * const source,
|
||||
const core::rect<s32> *sourceClipping,
|
||||
u32 argb)
|
||||
{
|
||||
tExecuteBlit blitter = getBlitter2( operation, dest, source );
|
||||
if ( 0 == blitter )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Clipping
|
||||
AbsRectangle sourceClip;
|
||||
AbsRectangle destClip;
|
||||
AbsRectangle v;
|
||||
|
||||
SBlitJob job;
|
||||
|
||||
setClip ( sourceClip, sourceClipping, source, 1 );
|
||||
setClip ( destClip, destClipping, dest, 0 );
|
||||
|
||||
v.x0 = destPos ? destPos->X : 0;
|
||||
v.y0 = destPos ? destPos->Y : 0;
|
||||
v.x1 = v.x0 + ( sourceClip.x1 - sourceClip.x0 );
|
||||
v.y1 = v.y0 + ( sourceClip.y1 - sourceClip.y0 );
|
||||
|
||||
if ( !intersect( job.Dest, destClip, v ) )
|
||||
return 0;
|
||||
|
||||
job.width = job.Dest.x1 - job.Dest.x0;
|
||||
job.height = job.Dest.y1 - job.Dest.y0;
|
||||
|
||||
job.Source.x0 = sourceClip.x0 + ( job.Dest.x0 - v.x0 );
|
||||
job.Source.x1 = job.Source.x0 + job.width;
|
||||
job.Source.y0 = sourceClip.y0 + ( job.Dest.y0 - v.y0 );
|
||||
job.Source.y1 = job.Source.y0 + job.height;
|
||||
|
||||
job.argb = argb;
|
||||
|
||||
if ( source )
|
||||
{
|
||||
job.srcPitch = source->getPitch();
|
||||
job.srcPixelMul = source->getBytesPerPixel();
|
||||
job.src = (void*) ( (u8*) source->lock() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// use srcPitch for color operation on dest
|
||||
job.srcPitch = job.width * dest->getBytesPerPixel();
|
||||
}
|
||||
|
||||
job.dstPitch = dest->getPitch();
|
||||
job.dstPixelMul = dest->getBytesPerPixel();
|
||||
job.dst = (void*) ( (u8*) dest->lock() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) );
|
||||
|
||||
blitter( &job );
|
||||
|
||||
if ( source )
|
||||
source->unlock();
|
||||
|
||||
if ( dest )
|
||||
dest->unlock();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
|
||||
|
||||
#include "CBoneSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CBoneSceneNode::CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
u32 boneIndex, const c8* boneName)
|
||||
: IBoneSceneNode(parent, mgr, id), BoneIndex(boneIndex),
|
||||
AnimationMode(EBAM_AUTOMATIC), SkinningSpace(EBSS_LOCAL)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBoneSceneNode");
|
||||
#endif
|
||||
setName(boneName);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the index of the bone
|
||||
u32 CBoneSceneNode::getBoneIndex() const
|
||||
{
|
||||
return BoneIndex;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the animation mode of the bone. Returns true if successful.
|
||||
bool CBoneSceneNode::setAnimationMode(E_BONE_ANIMATION_MODE mode)
|
||||
{
|
||||
AnimationMode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the current animation mode of the bone
|
||||
E_BONE_ANIMATION_MODE CBoneSceneNode::getAnimationMode() const
|
||||
{
|
||||
return AnimationMode;
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CBoneSceneNode::getBoundingBox() const
|
||||
{
|
||||
return Box;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//! Returns the relative transformation of the scene node.
|
||||
core::matrix4 CBoneSceneNode::getRelativeTransformation() const
|
||||
{
|
||||
return core::matrix4(); // RelativeTransformation;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void CBoneSceneNode::OnAnimate(u32 timeMs)
|
||||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
// animate this node with all animators
|
||||
|
||||
ISceneNodeAnimatorList::Iterator ait = Animators.begin();
|
||||
for (; ait != Animators.end(); ++ait)
|
||||
(*ait)->animateNode(this, timeMs);
|
||||
|
||||
// update absolute position
|
||||
//updateAbsolutePosition();
|
||||
|
||||
// perform the post render process on all children
|
||||
for (unsigned i = 0; i < Children.size(); ++i)
|
||||
Children[i]->OnAnimate(timeMs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node)
|
||||
{
|
||||
Node->updateAbsolutePosition();
|
||||
|
||||
for (unsigned i = 0; i < Node->getChildren().size(); ++i)
|
||||
{
|
||||
helper_updateAbsolutePositionOfAllChildren( Node->getChildren()[i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::updateAbsolutePositionOfAllChildren()
|
||||
{
|
||||
helper_updateAbsolutePositionOfAllChildren( this );
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
IBoneSceneNode::serializeAttributes(out, options);
|
||||
out->addInt("BoneIndex", BoneIndex);
|
||||
out->addEnum("AnimationMode", AnimationMode, BoneAnimationModeNames);
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
BoneIndex = in->getAttributeAsInt("BoneIndex");
|
||||
AnimationMode = (E_BONE_ANIMATION_MODE)in->getAttributeAsEnumeration("AnimationMode", BoneAnimationModeNames);
|
||||
// for legacy files (before 1.5)
|
||||
const core::stringc boneName = in->getAttributeAsString("BoneName");
|
||||
setName(boneName);
|
||||
IBoneSceneNode::deserializeAttributes(in, options);
|
||||
// TODO: add/replace bone in parent with bone from mesh
|
||||
}
|
||||
|
||||
|
||||
} // namespace scene
|
||||
} // namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_BONE_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_BONE_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
// Used with SkinnedMesh and IAnimatedMeshSceneNode, for boned meshes
|
||||
|
||||
#include "IBoneSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CBoneSceneNode : public IBoneSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr,
|
||||
s32 id=-1, u32 boneIndex=0, const c8* boneName=0);
|
||||
|
||||
//! Returns the index of the bone
|
||||
virtual u32 getBoneIndex() const;
|
||||
|
||||
//! Sets the animation mode of the bone. Returns true if successful.
|
||||
virtual bool setAnimationMode(E_BONE_ANIMATION_MODE mode);
|
||||
|
||||
//! Gets the current animation mode of the bone
|
||||
virtual E_BONE_ANIMATION_MODE getAnimationMode() const;
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
/*
|
||||
//! Returns the relative transformation of the scene node.
|
||||
//virtual core::matrix4 getRelativeTransformation() const;
|
||||
*/
|
||||
|
||||
virtual void OnAnimate(u32 timeMs);
|
||||
|
||||
virtual void updateAbsolutePosition()
|
||||
{
|
||||
if (SkinningSpace == EBSS_GLOBAL) return;
|
||||
IBoneSceneNode::updateAbsolutePosition();
|
||||
}
|
||||
|
||||
virtual void updateAbsolutePositionOfAllChildren();
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! How the relative transformation of the bone is used
|
||||
virtual void setSkinningSpace( E_BONE_SKINNING_SPACE space )
|
||||
{
|
||||
SkinningSpace=space;
|
||||
}
|
||||
|
||||
virtual E_BONE_SKINNING_SPACE getSkinningSpace() const
|
||||
{
|
||||
return SkinningSpace;
|
||||
}
|
||||
|
||||
private:
|
||||
void helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node);
|
||||
|
||||
u32 BoneIndex;
|
||||
|
||||
core::aabbox3d<f32> Box;
|
||||
|
||||
E_BONE_ANIMATION_MODE AnimationMode;
|
||||
E_BONE_SKINNING_SPACE SkinningSpace;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,385 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CCameraSceneNode.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position, const core::vector3df& lookat)
|
||||
: ICameraSceneNode(parent, mgr, id, position),
|
||||
Target(lookat), UpVector(0.0f, 1.0f, 0.0f), ZNear(1.0f), ZFar(3000.0f),
|
||||
InputReceiverEnabled(true), TargetAndRotationAreBound(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCameraSceneNode");
|
||||
#endif
|
||||
|
||||
// set default projection
|
||||
Fovy = core::PI / 2.5f; // Field of view, in radians.
|
||||
|
||||
const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0;
|
||||
if (d)
|
||||
Aspect = (f32)d->getCurrentRenderTargetSize().Width /
|
||||
(f32)d->getCurrentRenderTargetSize().Height;
|
||||
else
|
||||
Aspect = 4.0f / 3.0f; // Aspect ratio.
|
||||
|
||||
recalculateProjectionMatrix();
|
||||
recalculateViewArea();
|
||||
}
|
||||
|
||||
|
||||
//! Disables or enables the camera to get key or mouse inputs.
|
||||
void CCameraSceneNode::setInputReceiverEnabled(bool enabled)
|
||||
{
|
||||
InputReceiverEnabled = enabled;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the input receiver of the camera is currently enabled.
|
||||
bool CCameraSceneNode::isInputReceiverEnabled() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return InputReceiverEnabled;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the projection matrix of the camera.
|
||||
/** The core::matrix4 class has some methods
|
||||
to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH
|
||||
\param projection: The new projection matrix of the camera. */
|
||||
void CCameraSceneNode::setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal)
|
||||
{
|
||||
IsOrthogonal = isOrthogonal;
|
||||
ViewArea.getTransform ( video::ETS_PROJECTION ) = projection;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the current projection matrix of the camera
|
||||
//! \return Returns the current projection matrix of the camera.
|
||||
const core::matrix4& CCameraSceneNode::getProjectionMatrix() const
|
||||
{
|
||||
return ViewArea.getTransform ( video::ETS_PROJECTION );
|
||||
}
|
||||
|
||||
|
||||
//! Gets the current view matrix of the camera
|
||||
//! \return Returns the current view matrix of the camera.
|
||||
const core::matrix4& CCameraSceneNode::getViewMatrix() const
|
||||
{
|
||||
return ViewArea.getTransform ( video::ETS_VIEW );
|
||||
}
|
||||
|
||||
|
||||
//! Sets a custom view matrix affector. The matrix passed here, will be
|
||||
//! multiplied with the view matrix when it gets updated.
|
||||
//! This allows for custom camera setups like, for example, a reflection camera.
|
||||
/** \param affector: The affector matrix. */
|
||||
void CCameraSceneNode::setViewMatrixAffector(const core::matrix4& affector)
|
||||
{
|
||||
Affector = affector;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the custom view matrix affector.
|
||||
const core::matrix4& CCameraSceneNode::getViewMatrixAffector() const
|
||||
{
|
||||
return Affector;
|
||||
}
|
||||
|
||||
|
||||
//! It is possible to send mouse and key events to the camera. Most cameras
|
||||
//! may ignore this input, but camera scene nodes which are created for
|
||||
//! example with scene::ISceneManager::addMayaCameraSceneNode or
|
||||
//! scene::ISceneManager::addFPSCameraSceneNode, may want to get this input
|
||||
//! for changing their position, look at target or whatever.
|
||||
bool CCameraSceneNode::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (!InputReceiverEnabled)
|
||||
return false;
|
||||
|
||||
// send events to event receiving animators
|
||||
|
||||
ISceneNodeAnimatorList::Iterator ait = Animators.begin();
|
||||
|
||||
for (; ait != Animators.end(); ++ait)
|
||||
if ((*ait)->isEventReceiverEnabled() && (*ait)->OnEvent(event))
|
||||
return true;
|
||||
|
||||
// if nobody processed the event, return false
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//! sets the look at target of the camera
|
||||
//! \param pos: Look at target of the camera.
|
||||
void CCameraSceneNode::setTarget(const core::vector3df& pos)
|
||||
{
|
||||
Target = pos;
|
||||
|
||||
if(TargetAndRotationAreBound)
|
||||
{
|
||||
const core::vector3df toTarget = Target - getAbsolutePosition();
|
||||
ISceneNode::setRotation(toTarget.getHorizontalAngle());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Sets the rotation of the node.
|
||||
/** This only modifies the relative rotation of the node.
|
||||
If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
|
||||
then calling this will also change the camera's target to match the rotation.
|
||||
\param rotation New rotation of the node in degrees. */
|
||||
void CCameraSceneNode::setRotation(const core::vector3df& rotation)
|
||||
{
|
||||
if(TargetAndRotationAreBound)
|
||||
Target = getAbsolutePosition() + rotation.rotationToDirection();
|
||||
|
||||
ISceneNode::setRotation(rotation);
|
||||
}
|
||||
|
||||
|
||||
//! Gets the current look at target of the camera
|
||||
//! \return Returns the current look at target of the camera
|
||||
const core::vector3df& CCameraSceneNode::getTarget() const
|
||||
{
|
||||
return Target;
|
||||
}
|
||||
|
||||
|
||||
//! sets the up vector of the camera
|
||||
//! \param pos: New upvector of the camera.
|
||||
void CCameraSceneNode::setUpVector(const core::vector3df& pos)
|
||||
{
|
||||
UpVector = pos;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the up vector of the camera.
|
||||
//! \return Returns the up vector of the camera.
|
||||
const core::vector3df& CCameraSceneNode::getUpVector() const
|
||||
{
|
||||
return UpVector;
|
||||
}
|
||||
|
||||
|
||||
f32 CCameraSceneNode::getNearValue() const
|
||||
{
|
||||
return ZNear;
|
||||
}
|
||||
|
||||
|
||||
f32 CCameraSceneNode::getFarValue() const
|
||||
{
|
||||
return ZFar;
|
||||
}
|
||||
|
||||
|
||||
f32 CCameraSceneNode::getAspectRatio() const
|
||||
{
|
||||
return Aspect;
|
||||
}
|
||||
|
||||
|
||||
f32 CCameraSceneNode::getFOV() const
|
||||
{
|
||||
return Fovy;
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::setNearValue(f32 f)
|
||||
{
|
||||
ZNear = f;
|
||||
recalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::setFarValue(f32 f)
|
||||
{
|
||||
ZFar = f;
|
||||
recalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::setAspectRatio(f32 f)
|
||||
{
|
||||
Aspect = f;
|
||||
recalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::setFOV(f32 f)
|
||||
{
|
||||
Fovy = f;
|
||||
recalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::recalculateProjectionMatrix()
|
||||
{
|
||||
ViewArea.getTransform ( video::ETS_PROJECTION ).buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar);
|
||||
}
|
||||
|
||||
|
||||
//! prerender
|
||||
void CCameraSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if ( SceneManager->getActiveCamera () == this )
|
||||
SceneManager->registerNodeForRendering(this, ESNRP_CAMERA);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void CCameraSceneNode::render()
|
||||
{
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
core::vector3df tgtv = Target - pos;
|
||||
tgtv.normalize();
|
||||
|
||||
// if upvector and vector to the target are the same, we have a
|
||||
// problem. so solve this problem:
|
||||
core::vector3df up = UpVector;
|
||||
up.normalize();
|
||||
|
||||
f32 dp = tgtv.dotProduct(up);
|
||||
|
||||
if ( core::equals(core::abs_<f32>(dp), 1.f) )
|
||||
{
|
||||
up.X += 0.5f;
|
||||
}
|
||||
|
||||
ViewArea.getTransform(video::ETS_VIEW).buildCameraLookAtMatrixLH(pos, Target, up);
|
||||
ViewArea.getTransform(video::ETS_VIEW) *= Affector;
|
||||
recalculateViewArea();
|
||||
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
if ( driver)
|
||||
{
|
||||
driver->setTransform(video::ETS_PROJECTION, ViewArea.getTransform ( video::ETS_PROJECTION) );
|
||||
driver->setTransform(video::ETS_VIEW, ViewArea.getTransform ( video::ETS_VIEW) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CCameraSceneNode::getBoundingBox() const
|
||||
{
|
||||
return ViewArea.getBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
//! returns the view frustum. needed sometimes by bsp or lod render nodes.
|
||||
const SViewFrustum* CCameraSceneNode::getViewFrustum() const
|
||||
{
|
||||
return &ViewArea;
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::recalculateViewArea()
|
||||
{
|
||||
ViewArea.cameraPosition = getAbsolutePosition();
|
||||
|
||||
core::matrix4 m(core::matrix4::EM4CONST_NOTHING);
|
||||
m.setbyproduct_nocheck(ViewArea.getTransform(video::ETS_PROJECTION),
|
||||
ViewArea.getTransform(video::ETS_VIEW));
|
||||
ViewArea.setFrom(m);
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
void CCameraSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
ICameraSceneNode::serializeAttributes(out, options);
|
||||
|
||||
out->addVector3d("Target", Target);
|
||||
out->addVector3d("UpVector", UpVector);
|
||||
out->addFloat("Fovy", Fovy);
|
||||
out->addFloat("Aspect", Aspect);
|
||||
out->addFloat("ZNear", ZNear);
|
||||
out->addFloat("ZFar", ZFar);
|
||||
out->addBool("Binding", TargetAndRotationAreBound);
|
||||
out->addBool("ReceiveInput", InputReceiverEnabled);
|
||||
}
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
ICameraSceneNode::deserializeAttributes(in, options);
|
||||
|
||||
Target = in->getAttributeAsVector3d("Target");
|
||||
UpVector = in->getAttributeAsVector3d("UpVector");
|
||||
Fovy = in->getAttributeAsFloat("Fovy");
|
||||
Aspect = in->getAttributeAsFloat("Aspect");
|
||||
ZNear = in->getAttributeAsFloat("ZNear");
|
||||
ZFar = in->getAttributeAsFloat("ZFar");
|
||||
TargetAndRotationAreBound = in->getAttributeAsBool("Binding");
|
||||
if ( in->findAttribute("ReceiveInput") )
|
||||
InputReceiverEnabled = in->getAttributeAsBool("InputReceiverEnabled");
|
||||
|
||||
recalculateProjectionMatrix();
|
||||
recalculateViewArea();
|
||||
}
|
||||
|
||||
|
||||
//! Set the binding between the camera's rotation adn target.
|
||||
void CCameraSceneNode::bindTargetAndRotation(bool bound)
|
||||
{
|
||||
TargetAndRotationAreBound = bound;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the binding between the camera's rotation and target.
|
||||
bool CCameraSceneNode::getTargetAndRotationBinding(void) const
|
||||
{
|
||||
return TargetAndRotationAreBound;
|
||||
}
|
||||
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CCameraSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
ICameraSceneNode::clone(newParent, newManager);
|
||||
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CCameraSceneNode* nb = new CCameraSceneNode(newParent,
|
||||
newManager, ID, RelativeTranslation, Target);
|
||||
|
||||
nb->ISceneNode::cloneMembers(this, newManager);
|
||||
nb->ICameraSceneNode::cloneMembers(this);
|
||||
|
||||
nb->Target = Target;
|
||||
nb->UpVector = UpVector;
|
||||
nb->Fovy = Fovy;
|
||||
nb->Aspect = Aspect;
|
||||
nb->ZNear = ZNear;
|
||||
nb->ZFar = ZFar;
|
||||
nb->ViewArea = ViewArea;
|
||||
nb->Affector = Affector;
|
||||
nb->InputReceiverEnabled = InputReceiverEnabled;
|
||||
nb->TargetAndRotationAreBound = TargetAndRotationAreBound;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_CAMERA_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_CAMERA_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "SViewFrustum.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CCameraSceneNode : public ICameraSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position = core::vector3df(0,0,0),
|
||||
const core::vector3df& lookat = core::vector3df(0,0,100));
|
||||
|
||||
//! Sets the projection matrix of the camera.
|
||||
/** The core::matrix4 class has some methods
|
||||
to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH.
|
||||
Note that the matrix will only stay as set by this method until one of
|
||||
the following Methods are called: setNearValue, setFarValue, setAspectRatio, setFOV.
|
||||
\param projection The new projection matrix of the camera.
|
||||
\param isOrthogonal Set this to true if the matrix is an orthogonal one (e.g.
|
||||
from matrix4::buildProjectionMatrixOrthoLH(). */
|
||||
virtual void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal = false);
|
||||
|
||||
//! Gets the current projection matrix of the camera
|
||||
//! \return Returns the current projection matrix of the camera.
|
||||
virtual const core::matrix4& getProjectionMatrix() const;
|
||||
|
||||
//! Gets the current view matrix of the camera
|
||||
//! \return Returns the current view matrix of the camera.
|
||||
virtual const core::matrix4& getViewMatrix() const;
|
||||
|
||||
//! Sets a custom view matrix affector.
|
||||
/** \param affector: The affector matrix. */
|
||||
virtual void setViewMatrixAffector(const core::matrix4& affector);
|
||||
|
||||
//! Gets the custom view matrix affector.
|
||||
virtual const core::matrix4& getViewMatrixAffector() const;
|
||||
|
||||
//! It is possible to send mouse and key events to the camera. Most cameras
|
||||
//! may ignore this input, but camera scene nodes which are created for
|
||||
//! example with scene::ISceneManager::addMayaCameraSceneNode or
|
||||
//! scene::ISceneManager::addMeshViewerCameraSceneNode, may want to get this input
|
||||
//! for changing their position, look at target or whatever.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! Sets the look at target of the camera
|
||||
/** If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
|
||||
then calling this will also change the camera's scene node rotation to match the target.
|
||||
\param pos: Look at target of the camera. */
|
||||
virtual void setTarget(const core::vector3df& pos);
|
||||
|
||||
//! Sets the rotation of the node.
|
||||
/** This only modifies the relative rotation of the node.
|
||||
If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
|
||||
then calling this will also change the camera's target to match the rotation.
|
||||
\param rotation New rotation of the node in degrees. */
|
||||
virtual void setRotation(const core::vector3df& rotation);
|
||||
|
||||
//! Gets the current look at target of the camera
|
||||
/** \return The current look at target of the camera */
|
||||
virtual const core::vector3df& getTarget() const;
|
||||
|
||||
//! Sets the up vector of the camera.
|
||||
//! \param pos: New upvector of the camera.
|
||||
virtual void setUpVector(const core::vector3df& pos);
|
||||
|
||||
//! Gets the up vector of the camera.
|
||||
//! \return Returns the up vector of the camera.
|
||||
virtual const core::vector3df& getUpVector() const;
|
||||
|
||||
//! Gets distance from the camera to the near plane.
|
||||
//! \return Value of the near plane of the camera.
|
||||
virtual f32 getNearValue() const;
|
||||
|
||||
//! Gets the distance from the camera to the far plane.
|
||||
//! \return Value of the far plane of the camera.
|
||||
virtual f32 getFarValue() const;
|
||||
|
||||
//! Get the aspect ratio of the camera.
|
||||
//! \return The aspect ratio of the camera.
|
||||
virtual f32 getAspectRatio() const;
|
||||
|
||||
//! Gets the field of view of the camera.
|
||||
//! \return Field of view of the camera
|
||||
virtual f32 getFOV() const;
|
||||
|
||||
//! Sets the value of the near clipping plane. (default: 1.0f)
|
||||
virtual void setNearValue(f32 zn);
|
||||
|
||||
//! Sets the value of the far clipping plane (default: 2000.0f)
|
||||
virtual void setFarValue(f32 zf);
|
||||
|
||||
//! Sets the aspect ratio (default: 4.0f / 3.0f)
|
||||
virtual void setAspectRatio(f32 aspect);
|
||||
|
||||
//! Sets the field of view (Default: PI / 3.5f)
|
||||
virtual void setFOV(f32 fovy);
|
||||
|
||||
//! PreRender event
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! Render
|
||||
virtual void render();
|
||||
|
||||
//! Returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! Returns the view area. Sometimes needed by bsp or lod render nodes.
|
||||
virtual const SViewFrustum* getViewFrustum() const;
|
||||
|
||||
//! Disables or enables the camera to get key or mouse inputs.
|
||||
//! If this is set to true, the camera will respond to key inputs
|
||||
//! otherwise not.
|
||||
virtual void setInputReceiverEnabled(bool enabled);
|
||||
|
||||
//! Returns if the input receiver of the camera is currently enabled.
|
||||
virtual bool isInputReceiverEnabled() const;
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_CAMERA; }
|
||||
|
||||
//! Binds the camera scene node's rotation to its target position and vice vera, or unbinds them.
|
||||
virtual void bindTargetAndRotation(bool bound);
|
||||
|
||||
//! Queries if the camera scene node's rotation and its target position are bound together.
|
||||
virtual bool getTargetAndRotationBinding(void) const;
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
protected:
|
||||
|
||||
void recalculateProjectionMatrix();
|
||||
void recalculateViewArea();
|
||||
|
||||
core::vector3df Target;
|
||||
core::vector3df UpVector;
|
||||
|
||||
f32 Fovy; // Field of view, in radians.
|
||||
f32 Aspect; // Aspect ratio.
|
||||
f32 ZNear; // value of the near view-plane.
|
||||
f32 ZFar; // Z-value of the far view-plane.
|
||||
|
||||
SViewFrustum ViewArea;
|
||||
core::matrix4 Affector;
|
||||
|
||||
bool InputReceiverEnabled;
|
||||
bool TargetAndRotationAreBound;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,759 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CColorConverter.h"
|
||||
#include "SColor.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! converts a monochrome bitmap to A1R5G5B5 data
|
||||
void CColorConverter::convert1BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
s32 shift = 7;
|
||||
if (flip)
|
||||
out -= width;
|
||||
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
out[x] = *in>>shift & 0x01 ? (s16)0xffff : (s16)0x8000;
|
||||
|
||||
if ((--shift)<0) // 8 pixel done
|
||||
{
|
||||
shift=7;
|
||||
++in;
|
||||
}
|
||||
}
|
||||
|
||||
if (shift != 7) // width did not fill last byte
|
||||
++in;
|
||||
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! converts a 4 bit palettized image to A1R5G5B5
|
||||
void CColorConverter::convert4BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out || !palette)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width*height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
s32 shift = 4;
|
||||
if (flip)
|
||||
out -= width;
|
||||
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
out[x] = X8R8G8B8toA1R5G5B5(palette[(u8)((*in >> shift) & 0xf)]);
|
||||
|
||||
if (shift==0)
|
||||
{
|
||||
shift = 4;
|
||||
++in;
|
||||
}
|
||||
else
|
||||
shift = 0;
|
||||
}
|
||||
|
||||
if (shift == 0) // odd width
|
||||
++in;
|
||||
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! converts a 8 bit palettized image into A1R5G5B5
|
||||
void CColorConverter::convert8BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out || !palette)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= width; // one line back
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
out[x] = X8R8G8B8toA1R5G5B5(palette[(u8)(*in)]);
|
||||
++in;
|
||||
}
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
//! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
|
||||
void CColorConverter::convert8BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out )
|
||||
return;
|
||||
|
||||
const s32 lineWidth = 3 * width;
|
||||
if (flip)
|
||||
out += lineWidth * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= lineWidth; // one line back
|
||||
for (s32 x=0; x< lineWidth; x += 3)
|
||||
{
|
||||
if ( palette )
|
||||
{
|
||||
#ifdef __BIG_ENDIAN__
|
||||
out[x+0] = palette[ (in[0] << 2 ) + 0];
|
||||
out[x+1] = palette[ (in[0] << 2 ) + 1];
|
||||
out[x+2] = palette[ (in[0] << 2 ) + 2];
|
||||
#else
|
||||
out[x+0] = palette[ (in[0] << 2 ) + 2];
|
||||
out[x+1] = palette[ (in[0] << 2 ) + 1];
|
||||
out[x+2] = palette[ (in[0] << 2 ) + 0];
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
out[x+0] = in[0];
|
||||
out[x+1] = in[0];
|
||||
out[x+2] = in[0];
|
||||
}
|
||||
++in;
|
||||
}
|
||||
if (!flip)
|
||||
out += lineWidth;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
//! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
|
||||
void CColorConverter::convert8BitTo32Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out )
|
||||
return;
|
||||
|
||||
const u32 lineWidth = 4 * width;
|
||||
if (flip)
|
||||
out += lineWidth * height;
|
||||
|
||||
u32 x;
|
||||
u32 c;
|
||||
for (u32 y=0; y < (u32) height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= lineWidth; // one line back
|
||||
|
||||
if ( palette )
|
||||
{
|
||||
for (x=0; x < (u32) width; x += 1)
|
||||
{
|
||||
c = in[x];
|
||||
((u32*)out)[x] = ((u32*)palette)[ c ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x=0; x < (u32) width; x += 1)
|
||||
{
|
||||
c = in[x];
|
||||
#ifdef __BIG_ENDIAN__
|
||||
((u32*)out)[x] = c << 24 | c << 16 | c << 8 | 0x000000FF;
|
||||
#else
|
||||
((u32*)out)[x] = 0xFF000000 | c << 16 | c << 8 | c;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!flip)
|
||||
out += lineWidth;
|
||||
in += width + linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! converts 16bit data to 16bit data
|
||||
void CColorConverter::convert16BitTo16Bit(const s16* in, s16* out, s32 width, s32 height, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= width;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
for (s32 x=0; x<width; ++x)
|
||||
out[x]=os::Byteswap::byteswap(in[x]);
|
||||
#else
|
||||
memcpy(out, in, width*sizeof(s16));
|
||||
#endif
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! copies R8G8B8 24bit data to 24bit data
|
||||
void CColorConverter::convert24BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, s32 linepad, bool flip, bool bgr)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
const s32 lineWidth = 3 * width;
|
||||
if (flip)
|
||||
out += lineWidth * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= lineWidth;
|
||||
if (bgr)
|
||||
{
|
||||
for (s32 x=0; x<lineWidth; x+=3)
|
||||
{
|
||||
out[x+0] = in[x+2];
|
||||
out[x+1] = in[x+1];
|
||||
out[x+2] = in[x+0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(out,in,lineWidth);
|
||||
}
|
||||
if (!flip)
|
||||
out += lineWidth;
|
||||
in += lineWidth;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Resizes the surface to a new size and converts it at the same time
|
||||
//! to an A8R8G8B8 format, returning the pointer to the new buffer.
|
||||
void CColorConverter::convert16bitToA8R8G8B8andResize(const s16* in, s32* out, s32 newWidth, s32 newHeight, s32 currentWidth, s32 currentHeight)
|
||||
{
|
||||
if (!newWidth || !newHeight)
|
||||
return;
|
||||
|
||||
// note: this is very very slow. (i didn't want to write a fast version.
|
||||
// but hopefully, nobody wants to convert surfaces every frame.
|
||||
|
||||
f32 sourceXStep = (f32)currentWidth / (f32)newWidth;
|
||||
f32 sourceYStep = (f32)currentHeight / (f32)newHeight;
|
||||
f32 sy;
|
||||
s32 t;
|
||||
|
||||
for (s32 x=0; x<newWidth; ++x)
|
||||
{
|
||||
sy = 0.0f;
|
||||
|
||||
for (s32 y=0; y<newHeight; ++y)
|
||||
{
|
||||
t = in[(s32)(((s32)sy)*currentWidth + x*sourceXStep)];
|
||||
t = (((t >> 15)&0x1)<<31) | (((t >> 10)&0x1F)<<19) |
|
||||
(((t >> 5)&0x1F)<<11) | (t&0x1F)<<3;
|
||||
out[(s32)(y*newWidth + x)] = t;
|
||||
|
||||
sy+=sourceYStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! copies X8R8G8B8 32 bit data
|
||||
void CColorConverter::convert32BitTo32Bit(const s32* in, s32* out, s32 width, s32 height, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= width;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
for (s32 x=0; x<width; ++x)
|
||||
out[x]=os::Byteswap::byteswap(in[x]);
|
||||
#else
|
||||
memcpy(out, in, width*sizeof(s32));
|
||||
#endif
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[2] = (*sB & 0x7c00) >> 7;
|
||||
dB[1] = (*sB & 0x03e0) >> 2;
|
||||
dB[0] = (*sB & 0x1f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toB8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[0] = (*sB & 0x7c00) >> 7;
|
||||
dB[1] = (*sB & 0x03e0) >> 2;
|
||||
dB[2] = (*sB & 0x1f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toR5G5B5A1(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
const u16* sB = (const u16*)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB = (*sB<<1)|(*sB>>15);
|
||||
++sB; ++dB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = A1R5G5B5toA8R8G8B8(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 2);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = A1R5G5B5toR5G6B5(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
// sB[3] is alpha
|
||||
dB[0] = sB[2];
|
||||
dB[1] = sB[1];
|
||||
dB[2] = sB[0];
|
||||
|
||||
sB += 4;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
// sB[3] is alpha
|
||||
dB[0] = sB[0];
|
||||
dB[1] = sB[1];
|
||||
dB[2] = sB[2];
|
||||
|
||||
sB += 4;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 4);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u32* sB = (u32*)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = A8R8G8B8toA1R5G5B5(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8 * sB = (u8 *)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
s32 r = sB[2] >> 3;
|
||||
s32 g = sB[1] >> 2;
|
||||
s32 b = sB[0] >> 3;
|
||||
|
||||
dB[0] = (r << 11) | (g << 5) | (b);
|
||||
|
||||
sB += 4;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toR3G3B2(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
u8 r = sB[2] & 0xe0;
|
||||
u8 g = (sB[1] & 0xe0) >> 3;
|
||||
u8 b = (sB[0] & 0xc0) >> 6;
|
||||
|
||||
dB[0] = (r | g | b);
|
||||
|
||||
sB += 4;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 3);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8* )sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB = 0xff000000 | (sB[0]<<16) | (sB[1]<<8) | sB[2];
|
||||
|
||||
sB += 3;
|
||||
++dB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8 * sB = (u8 *)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
s32 r = sB[0] >> 3;
|
||||
s32 g = sB[1] >> 3;
|
||||
s32 b = sB[2] >> 3;
|
||||
|
||||
dB[0] = (0x8000) | (r << 10) | (g << 5) | (b);
|
||||
|
||||
sB += 3;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8* )sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB = 0xff000000 | (sB[2]<<16) | (sB[1]<<8) | sB[0];
|
||||
|
||||
sB += 3;
|
||||
++dB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toR8G8B8A8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
const u32* sB = (const u32*)sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB++ = (*sB<<8) | (*sB>>24);
|
||||
++sB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toA8B8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
const u32* sB = (const u32*)sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB++ = (*sB&0xff00ff00)|((*sB&0x00ff0000)>>16)|((*sB&0x000000ff)<<16);
|
||||
++sB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[0] = sB[3];
|
||||
dB[1] = sB[2];
|
||||
dB[2] = sB[1];
|
||||
dB[3] = sB[0];
|
||||
|
||||
sB += 4;
|
||||
dB += 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[2] = sB[0];
|
||||
dB[1] = sB[1];
|
||||
dB[0] = sB[2];
|
||||
|
||||
sB += 3;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8 * sB = (u8 *)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
s32 r = sB[0] >> 3;
|
||||
s32 g = sB[1] >> 2;
|
||||
s32 b = sB[2] >> 3;
|
||||
|
||||
dB[0] = (r << 11) | (g << 5) | (b);
|
||||
|
||||
sB += 3;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 2);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[0] = (*sB & 0xf800) >> 8;
|
||||
dB[1] = (*sB & 0x07e0) >> 3;
|
||||
dB[2] = (*sB & 0x001f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toB8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[2] = (*sB & 0xf800) >> 8;
|
||||
dB[1] = (*sB & 0x07e0) >> 3;
|
||||
dB[0] = (*sB & 0x001f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = R5G6B5toA8R8G8B8(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = R5G6B5toA1R5G5B5(*sB++);
|
||||
}
|
||||
|
||||
|
||||
void CColorConverter::convert_viaFormat(const void* sP, ECOLOR_FORMAT sF, s32 sN,
|
||||
void* dP, ECOLOR_FORMAT dF)
|
||||
{
|
||||
switch (sF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_A1R5G5B5toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_A1R5G5B5toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_A1R5G5B5toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_A1R5G5B5toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
#ifndef _DEBUG
|
||||
default:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_R5G6B5toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_R5G6B5toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_R5G6B5toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_R5G6B5toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
#ifndef _DEBUG
|
||||
default:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_A8R8G8B8toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_A8R8G8B8toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_A8R8G8B8toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_A8R8G8B8toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
#ifndef _DEBUG
|
||||
default:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_R8G8B8toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_R8G8B8toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_R8G8B8toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_R8G8B8toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
#ifndef _DEBUG
|
||||
default:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_COLOR_CONVERTER_H_INCLUDED__
|
||||
#define __C_COLOR_CONVERTER_H_INCLUDED__
|
||||
|
||||
#include "irrTypes.h"
|
||||
#include "IImage.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CColorConverter
|
||||
{
|
||||
public:
|
||||
|
||||
//! converts a monochrome bitmap to A1R5G5B5
|
||||
static void convert1BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, s32 linepad=0, bool flip=false);
|
||||
|
||||
//! converts a 4 bit palettized image to A1R5G5B5
|
||||
static void convert4BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad=0, bool flip=false);
|
||||
|
||||
//! converts a 8 bit palettized image to A1R5G5B5
|
||||
static void convert8BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad=0, bool flip=false);
|
||||
|
||||
//! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
|
||||
static void convert8BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad = 0, bool flip=false);
|
||||
|
||||
//! converts a 8 bit palettized or non palettized image (A8) into A8R8G8B8
|
||||
static void convert8BitTo32Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad = 0, bool flip=false);
|
||||
|
||||
//! converts R8G8B8 16 bit data to A1R5G5B5 data
|
||||
static void convert16BitTo16Bit(const s16* in, s16* out, s32 width, s32 height, s32 linepad=0, bool flip=false);
|
||||
|
||||
//! copies R8G8B8 24 bit data to 24 data, and flips and
|
||||
//! mirrors the image during the process.
|
||||
static void convert24BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, s32 linepad=0, bool flip=false, bool bgr=false);
|
||||
|
||||
//! Resizes the surface to a new size and converts it at the same time
|
||||
//! to an A8R8G8B8 format, returning the pointer to the new buffer.
|
||||
static void convert16bitToA8R8G8B8andResize(const s16* in, s32* out, s32 newWidth, s32 newHeight, s32 currentWidth, s32 currentHeight);
|
||||
|
||||
//! copies X8R8G8B8 32 bit data, and flips and
|
||||
//! mirrors the image during the process.
|
||||
static void convert32BitTo32Bit(const s32* in, s32* out, s32 width, s32 height, s32 linepad, bool flip=false);
|
||||
|
||||
|
||||
//! functions for converting one image format to another efficiently
|
||||
//! and hopefully correctly.
|
||||
//!
|
||||
//! \param sP pointer to source pixel data
|
||||
//! \param sN number of source pixels to copy
|
||||
//! \param dP pointer to destination data buffer. must be big enough
|
||||
//! to hold sN pixels in the output format.
|
||||
static void convert_A1R5G5B5toR8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A1R5G5B5toB8G8R8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A1R5G5B5toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A1R5G5B5toA1R5G5B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A1R5G5B5toR5G5B5A1(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A1R5G5B5toR5G6B5(const void* sP, s32 sN, void* dP);
|
||||
|
||||
static void convert_A8R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A8R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A8R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A8R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A8R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP);
|
||||
|
||||
static void convert_A8R8G8B8toR3G3B2(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A8R8G8B8toR8G8B8A8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A8R8G8B8toA8B8G8R8(const void* sP, s32 sN, void* dP);
|
||||
|
||||
static void convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R5G6B5toB8G8R8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R5G6B5toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R5G6B5toA1R5G5B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_viaFormat(const void* sP, ECOLOR_FORMAT sF, s32 sN,
|
||||
void* dP, ECOLOR_FORMAT dF);
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,684 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2016-2017 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_EGL_)
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
#include "stk_android_native_app_glue.h"
|
||||
#endif
|
||||
|
||||
#include "CContextEGL.h"
|
||||
#include "os.h"
|
||||
|
||||
using namespace irr;
|
||||
|
||||
ContextManagerEGL::ContextManagerEGL()
|
||||
{
|
||||
m_egl_window = 0;
|
||||
m_egl_display = EGL_NO_DISPLAY;
|
||||
m_egl_surface = EGL_NO_SURFACE;
|
||||
m_egl_context = EGL_NO_CONTEXT;
|
||||
m_egl_config = 0;
|
||||
m_egl_version = 0;
|
||||
m_is_legacy_device = false;
|
||||
m_initialized = false;
|
||||
eglGetPlatformDisplay = NULL;
|
||||
|
||||
memset(&m_creation_params, 0, sizeof(ContextEGLParams));
|
||||
}
|
||||
|
||||
|
||||
ContextManagerEGL::~ContextManagerEGL()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
bool ContextManagerEGL::init(const ContextEGLParams& params)
|
||||
{
|
||||
if (m_initialized)
|
||||
return false;
|
||||
|
||||
m_creation_params = params;
|
||||
m_egl_window = m_creation_params.window;
|
||||
|
||||
bool success = initExtensions();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
os::Printer::log("Error: Could not initialize EGL extensions.\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
success = initDisplay();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
os::Printer::log("Error: Could not initialize EGL display.\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool has_minimum_requirements = false;
|
||||
|
||||
if (m_creation_params.opengl_api == CEGL_API_OPENGL)
|
||||
{
|
||||
if (hasEGLExtension("EGL_KHR_create_context") || m_egl_version >= 150)
|
||||
{
|
||||
has_minimum_requirements = true;
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
}
|
||||
}
|
||||
else if (m_creation_params.opengl_api == CEGL_API_OPENGL_ES)
|
||||
{
|
||||
if (m_egl_version >= 130)
|
||||
{
|
||||
has_minimum_requirements = true;
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_minimum_requirements)
|
||||
{
|
||||
os::Printer::log("Error: EGL version is too old.\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
success = chooseConfig();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
os::Printer::log("Error: Couldn't get EGL config.\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
success = createSurface();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
os::Printer::log("Error: Couldn't create EGL surface.\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
success = createContext();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
os::Printer::log("Error: Couldn't create OpenGL context.\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
success = eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface,
|
||||
m_egl_context);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
checkEGLError();
|
||||
os::Printer::log("Error: Couldn't make context current for EGL display.\n");
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
eglSwapInterval(m_egl_display, m_creation_params.swap_interval);
|
||||
|
||||
m_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ContextManagerEGL::initExtensions()
|
||||
{
|
||||
if (hasEGLExtension("EGL_KHR_platform_base"))
|
||||
{
|
||||
eglGetPlatformDisplay = (eglGetPlatformDisplay_t)
|
||||
eglGetProcAddress("eglGetPlatformDisplay");
|
||||
}
|
||||
else if (hasEGLExtension("EGL_EXT_platform_base"))
|
||||
{
|
||||
eglGetPlatformDisplay = (eglGetPlatformDisplay_t)
|
||||
eglGetProcAddress("eglGetPlatformDisplayEXT");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ContextManagerEGL::initDisplay()
|
||||
{
|
||||
EGLNativeDisplayType display = m_creation_params.display;
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
display = EGL_DEFAULT_DISPLAY;
|
||||
#endif
|
||||
|
||||
EGLenum platform = 0;
|
||||
|
||||
switch (m_creation_params.platform)
|
||||
{
|
||||
case CEGL_PLATFORM_ANDROID:
|
||||
platform = EGL_PLATFORM_ANDROID;
|
||||
break;
|
||||
case CEGL_PLATFORM_GBM:
|
||||
platform = EGL_PLATFORM_GBM;
|
||||
break;
|
||||
case CEGL_PLATFORM_WAYLAND:
|
||||
platform = EGL_PLATFORM_WAYLAND;
|
||||
break;
|
||||
case CEGL_PLATFORM_X11:
|
||||
platform = EGL_PLATFORM_X11;
|
||||
break;
|
||||
case CEGL_PLATFORM_DEFAULT:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_creation_params.platform != CEGL_PLATFORM_DEFAULT &&
|
||||
eglGetPlatformDisplay != NULL)
|
||||
{
|
||||
m_egl_display = eglGetPlatformDisplay(platform, (void*)display, NULL);
|
||||
}
|
||||
|
||||
if (m_egl_display == EGL_NO_DISPLAY)
|
||||
{
|
||||
m_egl_display = eglGetDisplay(display);
|
||||
}
|
||||
|
||||
if (m_egl_display == EGL_NO_DISPLAY && display != EGL_DEFAULT_DISPLAY)
|
||||
{
|
||||
m_egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
if (m_egl_display == EGL_NO_DISPLAY)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int egl_version_major = 0;
|
||||
int egl_version_minor = 0;
|
||||
|
||||
bool success = eglInitialize(m_egl_display, &egl_version_major,
|
||||
&egl_version_minor);
|
||||
|
||||
if (success)
|
||||
{
|
||||
m_egl_version = 100 * egl_version_major + 10 * egl_version_minor;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool ContextManagerEGL::chooseConfig()
|
||||
{
|
||||
std::vector<EGLint> config_attribs;
|
||||
config_attribs.push_back(EGL_RED_SIZE);
|
||||
config_attribs.push_back(8);
|
||||
config_attribs.push_back(EGL_GREEN_SIZE);
|
||||
config_attribs.push_back(8);
|
||||
config_attribs.push_back(EGL_BLUE_SIZE);
|
||||
config_attribs.push_back(8);
|
||||
config_attribs.push_back(EGL_ALPHA_SIZE);
|
||||
config_attribs.push_back(m_creation_params.with_alpha_channel ? 8 : 0);
|
||||
config_attribs.push_back(EGL_DEPTH_SIZE);
|
||||
config_attribs.push_back(16);
|
||||
// config_attribs.push_back(EGL_BUFFER_SIZE);
|
||||
// config_attribs.push_back(24);
|
||||
// config_attribs.push_back(EGL_STENCIL_SIZE);
|
||||
// config_attribs.push_back(stencil_buffer);
|
||||
// config_attribs.push_back(EGL_SAMPLE_BUFFERS);
|
||||
// config_attribs.push_back(antialias ? 1 : 0);
|
||||
// config_attribs.push_back(EGL_SAMPLES);
|
||||
// config_attribs.push_back(antialias);
|
||||
|
||||
if (m_creation_params.opengl_api == CEGL_API_OPENGL)
|
||||
{
|
||||
config_attribs.push_back(EGL_RENDERABLE_TYPE);
|
||||
config_attribs.push_back(EGL_OPENGL_BIT);
|
||||
}
|
||||
else if (m_creation_params.opengl_api == CEGL_API_OPENGL_ES)
|
||||
{
|
||||
config_attribs.push_back(EGL_RENDERABLE_TYPE);
|
||||
config_attribs.push_back(EGL_OPENGL_ES2_BIT);
|
||||
}
|
||||
|
||||
if (m_creation_params.surface_type == CEGL_SURFACE_WINDOW)
|
||||
{
|
||||
config_attribs.push_back(EGL_SURFACE_TYPE);
|
||||
config_attribs.push_back(EGL_WINDOW_BIT);
|
||||
}
|
||||
else if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER)
|
||||
{
|
||||
config_attribs.push_back(EGL_SURFACE_TYPE);
|
||||
config_attribs.push_back(EGL_PBUFFER_BIT);
|
||||
}
|
||||
|
||||
config_attribs.push_back(EGL_NONE);
|
||||
config_attribs.push_back(0);
|
||||
|
||||
EGLint num_configs = 0;
|
||||
|
||||
bool success = eglChooseConfig(m_egl_display, &config_attribs[0],
|
||||
&m_egl_config, 1, &num_configs);
|
||||
|
||||
if (!success || m_egl_config == NULL || num_configs < 1)
|
||||
{
|
||||
config_attribs[1] = 5; //EGL_RED_SIZE
|
||||
config_attribs[3] = 6; //EGL_GREEN_SIZE
|
||||
config_attribs[5] = 5; //EGL_BLUE_SIZE
|
||||
config_attribs[7] = 0; //EGL_ALPHA_SIZE
|
||||
config_attribs[9] = 1; //EGL_DEPTH_SIZE
|
||||
|
||||
success = eglChooseConfig(m_egl_display, &config_attribs[0],
|
||||
&m_egl_config, 1, &num_configs);
|
||||
}
|
||||
|
||||
if (!success || m_egl_config == NULL || num_configs < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
EGLint format = 0;
|
||||
eglGetConfigAttrib(m_egl_display, m_egl_config, EGL_NATIVE_VISUAL_ID,
|
||||
&format);
|
||||
ANativeWindow_setBuffersGeometry(m_egl_window, 0, 0, format);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ContextManagerEGL::createSurface()
|
||||
{
|
||||
unsigned int colorspace_attr_pos = 0;
|
||||
unsigned int largest_pbuffer_attr_pos = 0;
|
||||
|
||||
std::vector<EGLint> attribs;
|
||||
|
||||
if (m_creation_params.opengl_api == CEGL_API_OPENGL &&
|
||||
m_creation_params.handle_srgb == true)
|
||||
{
|
||||
if (hasEGLExtension("EGL_KHR_gl_colorspace") || m_egl_version >= 150)
|
||||
{
|
||||
attribs.push_back(EGL_GL_COLORSPACE);
|
||||
attribs.push_back(EGL_GL_COLORSPACE_SRGB);
|
||||
colorspace_attr_pos = attribs.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER)
|
||||
{
|
||||
attribs.push_back(EGL_WIDTH);
|
||||
attribs.push_back(m_creation_params.pbuffer_width);
|
||||
attribs.push_back(EGL_HEIGHT);
|
||||
attribs.push_back(m_creation_params.pbuffer_height);
|
||||
attribs.push_back(EGL_LARGEST_PBUFFER);
|
||||
attribs.push_back(EGL_FALSE);
|
||||
largest_pbuffer_attr_pos = attribs.size() - 1;
|
||||
}
|
||||
|
||||
attribs.push_back(EGL_NONE);
|
||||
attribs.push_back(0);
|
||||
|
||||
if (m_egl_surface == EGL_NO_SURFACE)
|
||||
{
|
||||
if (m_creation_params.surface_type == CEGL_SURFACE_WINDOW)
|
||||
{
|
||||
m_egl_surface = eglCreateWindowSurface(m_egl_display, m_egl_config,
|
||||
m_egl_window, &attribs[0]);
|
||||
}
|
||||
else if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER)
|
||||
{
|
||||
m_egl_surface = eglCreatePbufferSurface(m_egl_display, m_egl_config,
|
||||
&attribs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_egl_surface == EGL_NO_SURFACE && colorspace_attr_pos > 0)
|
||||
{
|
||||
attribs[colorspace_attr_pos] = EGL_GL_COLORSPACE_LINEAR;
|
||||
|
||||
if (m_creation_params.surface_type == CEGL_SURFACE_WINDOW)
|
||||
{
|
||||
m_egl_surface = eglCreateWindowSurface(m_egl_display, m_egl_config,
|
||||
m_egl_window, &attribs[0]);
|
||||
}
|
||||
else if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER)
|
||||
{
|
||||
m_egl_surface = eglCreatePbufferSurface(m_egl_display, m_egl_config,
|
||||
&attribs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_egl_surface == EGL_NO_SURFACE && largest_pbuffer_attr_pos > 0)
|
||||
{
|
||||
attribs[largest_pbuffer_attr_pos] = EGL_TRUE;
|
||||
|
||||
if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER)
|
||||
{
|
||||
m_egl_surface = eglCreatePbufferSurface(m_egl_display, m_egl_config,
|
||||
&attribs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return m_egl_surface != EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
|
||||
bool ContextManagerEGL::createContext()
|
||||
{
|
||||
m_is_legacy_device = false;
|
||||
|
||||
if (m_creation_params.opengl_api == CEGL_API_OPENGL_ES)
|
||||
{
|
||||
if (!m_creation_params.force_legacy_device)
|
||||
{
|
||||
if (m_egl_context == EGL_NO_CONTEXT)
|
||||
{
|
||||
std::vector<EGLint> context_attribs;
|
||||
context_attribs.push_back(EGL_CONTEXT_CLIENT_VERSION);
|
||||
context_attribs.push_back(3);
|
||||
context_attribs.push_back(EGL_NONE);
|
||||
context_attribs.push_back(0);
|
||||
|
||||
m_egl_context = eglCreateContext(m_egl_display,
|
||||
m_egl_config,
|
||||
EGL_NO_CONTEXT,
|
||||
&context_attribs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_egl_context == EGL_NO_CONTEXT)
|
||||
{
|
||||
m_is_legacy_device = true;
|
||||
|
||||
std::vector<EGLint> context_attribs;
|
||||
context_attribs.push_back(EGL_CONTEXT_CLIENT_VERSION);
|
||||
context_attribs.push_back(2);
|
||||
context_attribs.push_back(EGL_NONE);
|
||||
context_attribs.push_back(0);
|
||||
|
||||
m_egl_context = eglCreateContext(m_egl_display,
|
||||
m_egl_config,
|
||||
EGL_NO_CONTEXT,
|
||||
&context_attribs[0]);
|
||||
}
|
||||
}
|
||||
else if (m_creation_params.opengl_api == CEGL_API_OPENGL)
|
||||
{
|
||||
if (!m_creation_params.force_legacy_device)
|
||||
{
|
||||
if (m_egl_context == EGL_NO_CONTEXT)
|
||||
{
|
||||
std::vector<EGLint> context_attribs;
|
||||
context_attribs.push_back(EGL_CONTEXT_MAJOR_VERSION);
|
||||
context_attribs.push_back(4);
|
||||
context_attribs.push_back(EGL_CONTEXT_MINOR_VERSION);
|
||||
context_attribs.push_back(3);
|
||||
context_attribs.push_back(EGL_NONE);
|
||||
context_attribs.push_back(0);
|
||||
|
||||
m_egl_context = eglCreateContext(m_egl_display,
|
||||
m_egl_config,
|
||||
EGL_NO_CONTEXT,
|
||||
&context_attribs[0]);
|
||||
}
|
||||
|
||||
if (m_egl_context == EGL_NO_CONTEXT)
|
||||
{
|
||||
std::vector<EGLint> context_attribs;
|
||||
context_attribs.push_back(EGL_CONTEXT_MAJOR_VERSION);
|
||||
context_attribs.push_back(3);
|
||||
context_attribs.push_back(EGL_CONTEXT_MINOR_VERSION);
|
||||
context_attribs.push_back(3);
|
||||
context_attribs.push_back(EGL_NONE);
|
||||
context_attribs.push_back(0);
|
||||
|
||||
m_egl_context = eglCreateContext(m_egl_display,
|
||||
m_egl_config,
|
||||
EGL_NO_CONTEXT,
|
||||
&context_attribs[0]);
|
||||
}
|
||||
|
||||
if (m_egl_context == EGL_NO_CONTEXT)
|
||||
{
|
||||
std::vector<EGLint> context_attribs;
|
||||
context_attribs.push_back(EGL_CONTEXT_MAJOR_VERSION);
|
||||
context_attribs.push_back(3);
|
||||
context_attribs.push_back(EGL_CONTEXT_MINOR_VERSION);
|
||||
context_attribs.push_back(1);
|
||||
context_attribs.push_back(EGL_NONE);
|
||||
context_attribs.push_back(0);
|
||||
|
||||
m_egl_context = eglCreateContext(m_egl_display,
|
||||
m_egl_config,
|
||||
EGL_NO_CONTEXT,
|
||||
&context_attribs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_egl_context == EGL_NO_CONTEXT)
|
||||
{
|
||||
m_is_legacy_device = true;
|
||||
|
||||
std::vector<EGLint> context_attribs;
|
||||
context_attribs.push_back(EGL_CONTEXT_MAJOR_VERSION);
|
||||
context_attribs.push_back(2);
|
||||
context_attribs.push_back(EGL_CONTEXT_MINOR_VERSION);
|
||||
context_attribs.push_back(1);
|
||||
context_attribs.push_back(EGL_NONE);
|
||||
context_attribs.push_back(0);
|
||||
|
||||
m_egl_context = eglCreateContext(m_egl_display,
|
||||
m_egl_config,
|
||||
EGL_NO_CONTEXT,
|
||||
&context_attribs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return m_egl_context != EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
|
||||
void ContextManagerEGL::close()
|
||||
{
|
||||
if (m_egl_display != EGL_NO_DISPLAY)
|
||||
{
|
||||
eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
if (m_egl_context != EGL_NO_CONTEXT)
|
||||
{
|
||||
eglDestroyContext(m_egl_display, m_egl_context);
|
||||
m_egl_context = EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
if (m_egl_surface != EGL_NO_SURFACE)
|
||||
{
|
||||
eglDestroySurface(m_egl_display, m_egl_surface);
|
||||
m_egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
if (m_egl_display != EGL_NO_DISPLAY)
|
||||
{
|
||||
eglTerminate(m_egl_display);
|
||||
m_egl_display = EGL_NO_DISPLAY;
|
||||
}
|
||||
|
||||
eglReleaseThread();
|
||||
}
|
||||
|
||||
|
||||
bool ContextManagerEGL::swapBuffers()
|
||||
{
|
||||
bool success = eglSwapBuffers(m_egl_display, m_egl_surface);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!success)
|
||||
{
|
||||
eglGetError();
|
||||
}
|
||||
#endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool ContextManagerEGL::makeCurrent()
|
||||
{
|
||||
bool success = eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface,
|
||||
m_egl_context);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
void ContextManagerEGL::reloadEGLSurface(void* window)
|
||||
{
|
||||
if (!m_initialized)
|
||||
return;
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
m_egl_window = (ANativeWindow*)window;
|
||||
|
||||
if (!m_egl_window)
|
||||
{
|
||||
os::Printer::log("Error: Invalid EGL window.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
|
||||
eglDestroySurface(m_egl_display, m_egl_surface);
|
||||
m_egl_surface = EGL_NO_SURFACE;
|
||||
|
||||
bool success = createSurface();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
os::Printer::log("Error: Could not create EGL surface.");
|
||||
}
|
||||
|
||||
success = eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface,
|
||||
m_egl_context);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
checkEGLError();
|
||||
os::Printer::log("Error: Couldn't make context current for EGL display.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ContextManagerEGL::getSurfaceDimensions(int* width, int* height)
|
||||
{
|
||||
if (!eglQuerySurface(m_egl_display, m_egl_surface, EGL_WIDTH, width))
|
||||
return false;
|
||||
|
||||
if (!eglQuerySurface(m_egl_display, m_egl_surface, EGL_HEIGHT, height))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ContextManagerEGL::hasEGLExtension(const char* extension)
|
||||
{
|
||||
const char* extensions = eglQueryString(m_egl_display, EGL_EXTENSIONS);
|
||||
|
||||
if (extensions && strstr(extensions, extension) != NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ContextManagerEGL::checkEGLError()
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
switch (eglGetError())
|
||||
{
|
||||
case EGL_SUCCESS:
|
||||
result = false;
|
||||
break;
|
||||
case EGL_NOT_INITIALIZED:
|
||||
os::Printer::log("Error: EGL_NOT_INITIALIZED\n");
|
||||
break;
|
||||
case EGL_BAD_ACCESS:
|
||||
os::Printer::log("Error: EGL_BAD_ACCESS\n");
|
||||
break;
|
||||
case EGL_BAD_ALLOC:
|
||||
os::Printer::log("Error: EGL_BAD_ALLOC\n");
|
||||
break;
|
||||
case EGL_BAD_ATTRIBUTE:
|
||||
os::Printer::log("Error: EGL_BAD_ATTRIBUTE\n");
|
||||
break;
|
||||
case EGL_BAD_CONTEXT:
|
||||
os::Printer::log("Error: EGL_BAD_CONTEXT\n");
|
||||
break;
|
||||
case EGL_BAD_CONFIG:
|
||||
os::Printer::log("Error: EGL_BAD_CONFIG\n");
|
||||
break;
|
||||
case EGL_BAD_CURRENT_SURFACE:
|
||||
os::Printer::log("Error: EGL_BAD_CURRENT_SURFACE\n");
|
||||
break;
|
||||
case EGL_BAD_DISPLAY:
|
||||
os::Printer::log("Error: EGL_BAD_DISPLAY\n");
|
||||
break;
|
||||
case EGL_BAD_SURFACE:
|
||||
os::Printer::log("Error: EGL_BAD_SURFACE\n");
|
||||
break;
|
||||
case EGL_BAD_MATCH:
|
||||
os::Printer::log("Error: EGL_BAD_MATCH\n");
|
||||
break;
|
||||
case EGL_BAD_PARAMETER:
|
||||
os::Printer::log("Error: EGL_BAD_PARAMETER\n");
|
||||
break;
|
||||
case EGL_BAD_NATIVE_PIXMAP:
|
||||
os::Printer::log("Error: EGL_BAD_NATIVE_PIXMAP\n");
|
||||
break;
|
||||
case EGL_BAD_NATIVE_WINDOW:
|
||||
os::Printer::log("Error: EGL_BAD_NATIVE_WINDOW\n");
|
||||
break;
|
||||
case EGL_CONTEXT_LOST:
|
||||
os::Printer::log("Error: EGL_CONTEXT_LOST\n");
|
||||
break;
|
||||
default:
|
||||
os::Printer::log("Error: Unknown EGL error.\n");
|
||||
break;
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,133 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2016-2017 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef CONTEXT_EGL_HPP
|
||||
#define CONTEXT_EGL_HPP
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_EGL_)
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#ifndef EGL_CONTEXT_MAJOR_VERSION
|
||||
#define EGL_CONTEXT_MAJOR_VERSION 0x3098
|
||||
#endif
|
||||
#ifndef EGL_CONTEXT_MINOR_VERSION
|
||||
#define EGL_CONTEXT_MINOR_VERSION 0x30FB
|
||||
#endif
|
||||
#ifndef EGL_GL_COLORSPACE
|
||||
#define EGL_GL_COLORSPACE 0x309D
|
||||
#endif
|
||||
#ifndef EGL_GL_COLORSPACE_SRGB
|
||||
#define EGL_GL_COLORSPACE_SRGB 0x3089
|
||||
#endif
|
||||
#ifndef EGL_GL_COLORSPACE_LINEAR
|
||||
#define EGL_GL_COLORSPACE_LINEAR 0x308A
|
||||
#endif
|
||||
#ifndef EGL_PLATFORM_ANDROID
|
||||
#define EGL_PLATFORM_ANDROID 0x3141
|
||||
#endif
|
||||
#ifndef EGL_PLATFORM_GBM
|
||||
#define EGL_PLATFORM_GBM 0x31D7
|
||||
#endif
|
||||
#ifndef EGL_PLATFORM_WAYLAND
|
||||
#define EGL_PLATFORM_WAYLAND 0x31D8
|
||||
#endif
|
||||
#ifndef EGL_PLATFORM_X11
|
||||
#define EGL_PLATFORM_X11 0x31D5
|
||||
#endif
|
||||
|
||||
enum ContextEGLOpenGLAPI
|
||||
{
|
||||
CEGL_API_OPENGL,
|
||||
CEGL_API_OPENGL_ES
|
||||
};
|
||||
|
||||
enum ContextEGLSurfaceType
|
||||
{
|
||||
CEGL_SURFACE_WINDOW,
|
||||
CEGL_SURFACE_PBUFFER
|
||||
};
|
||||
|
||||
enum ContextEGLPlatform
|
||||
{
|
||||
CEGL_PLATFORM_ANDROID,
|
||||
CEGL_PLATFORM_GBM,
|
||||
CEGL_PLATFORM_WAYLAND,
|
||||
CEGL_PLATFORM_X11,
|
||||
CEGL_PLATFORM_DEFAULT
|
||||
};
|
||||
|
||||
struct ContextEGLParams
|
||||
{
|
||||
ContextEGLOpenGLAPI opengl_api;
|
||||
ContextEGLSurfaceType surface_type;
|
||||
ContextEGLPlatform platform;
|
||||
EGLNativeWindowType window;
|
||||
EGLNativeDisplayType display;
|
||||
bool force_legacy_device;
|
||||
bool handle_srgb;
|
||||
bool with_alpha_channel;
|
||||
int swap_interval;
|
||||
int pbuffer_width;
|
||||
int pbuffer_height;
|
||||
};
|
||||
|
||||
|
||||
class ContextManagerEGL
|
||||
{
|
||||
private:
|
||||
EGLNativeWindowType m_egl_window;
|
||||
EGLDisplay m_egl_display;
|
||||
EGLSurface m_egl_surface;
|
||||
EGLContext m_egl_context;
|
||||
EGLConfig m_egl_config;
|
||||
|
||||
ContextEGLParams m_creation_params;
|
||||
bool m_is_legacy_device;
|
||||
bool m_initialized;
|
||||
int m_egl_version;
|
||||
|
||||
typedef EGLDisplay (*eglGetPlatformDisplay_t) (EGLenum, void*, const EGLint*);
|
||||
eglGetPlatformDisplay_t eglGetPlatformDisplay;
|
||||
|
||||
bool initExtensions();
|
||||
bool initDisplay();
|
||||
bool chooseConfig();
|
||||
bool createSurface();
|
||||
bool createContext();
|
||||
bool hasEGLExtension(const char* extension);
|
||||
bool checkEGLError();
|
||||
|
||||
public:
|
||||
ContextManagerEGL();
|
||||
~ContextManagerEGL();
|
||||
|
||||
bool init(const ContextEGLParams& params);
|
||||
void close();
|
||||
|
||||
void reloadEGLSurface(void* window);
|
||||
bool swapBuffers();
|
||||
bool makeCurrent();
|
||||
bool isLegacyDevice() {return m_is_legacy_device;}
|
||||
bool getSurfaceDimensions(int* width, int* height);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,201 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CCubeSceneNode.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "S3DVertex.h"
|
||||
#include "SMeshBuffer.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
/*
|
||||
011 111
|
||||
/6,8------/5 y
|
||||
/ | / | ^ z
|
||||
/ | / | | /
|
||||
010 3,9-------2 | |/
|
||||
| 7- - -10,4 101 *---->x
|
||||
| / | /
|
||||
|/ | /
|
||||
0------11,1/
|
||||
000 100
|
||||
*/
|
||||
|
||||
//! constructor
|
||||
CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr,
|
||||
s32 id, const core::vector3df& position,
|
||||
const core::vector3df& rotation, const core::vector3df& scale)
|
||||
: IMeshSceneNode(parent, mgr, id, position, rotation, scale),
|
||||
Mesh(0), Size(size)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCubeSceneNode");
|
||||
#endif
|
||||
|
||||
setSize();
|
||||
}
|
||||
|
||||
|
||||
CCubeSceneNode::~CCubeSceneNode()
|
||||
{
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
}
|
||||
|
||||
|
||||
void CCubeSceneNode::setSize()
|
||||
{
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
Mesh = SceneManager->getGeometryCreator()->createCubeMesh(core::vector3df(Size));
|
||||
}
|
||||
|
||||
|
||||
//! renders the node.
|
||||
void CCubeSceneNode::render()
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
|
||||
// for debug purposes only:
|
||||
video::SMaterial mat = Mesh->getMeshBuffer(0)->getMaterial();
|
||||
|
||||
// overwrite half transparency
|
||||
if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY)
|
||||
mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
|
||||
driver->setMaterial(mat);
|
||||
driver->drawMeshBuffer(Mesh->getMeshBuffer(0));
|
||||
|
||||
// for debug purposes only:
|
||||
if (DebugDataVisible)
|
||||
{
|
||||
video::SMaterial m;
|
||||
m.Lighting = false;
|
||||
m.AntiAliasing=0;
|
||||
driver->setMaterial(m);
|
||||
|
||||
if (DebugDataVisible & scene::EDS_BBOX)
|
||||
{
|
||||
driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), video::SColor(255,255,255,255));
|
||||
}
|
||||
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS)
|
||||
{
|
||||
driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(),
|
||||
video::SColor(255,190,128,128));
|
||||
}
|
||||
if (DebugDataVisible & scene::EDS_NORMALS)
|
||||
{
|
||||
// draw normals
|
||||
const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH);
|
||||
const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR);
|
||||
const u32 count = Mesh->getMeshBufferCount();
|
||||
|
||||
for (u32 i=0; i != count; ++i)
|
||||
{
|
||||
driver->drawMeshBufferNormals(Mesh->getMeshBuffer(i), debugNormalLength, debugNormalColor);
|
||||
}
|
||||
}
|
||||
|
||||
// show mesh
|
||||
if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY)
|
||||
{
|
||||
m.Wireframe = true;
|
||||
driver->setMaterial(m);
|
||||
|
||||
driver->drawMeshBuffer(Mesh->getMeshBuffer(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CCubeSceneNode::getBoundingBox() const
|
||||
{
|
||||
return Mesh->getMeshBuffer(0)->getBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
//! Removes a child from this scene node.
|
||||
//! Implemented here, to be able to remove the shadow properly, if there is one,
|
||||
//! or to remove attached childs.
|
||||
bool CCubeSceneNode::removeChild(ISceneNode* child)
|
||||
{
|
||||
return ISceneNode::removeChild(child);
|
||||
}
|
||||
|
||||
|
||||
void CCubeSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! returns the material based on the zero based index i.
|
||||
video::SMaterial& CCubeSceneNode::getMaterial(u32 i)
|
||||
{
|
||||
return Mesh->getMeshBuffer(0)->getMaterial();
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
u32 CCubeSceneNode::getMaterialCount() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
void CCubeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
ISceneNode::serializeAttributes(out, options);
|
||||
|
||||
out->addFloat("Size", Size);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
void CCubeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
f32 newSize = in->getAttributeAsFloat("Size");
|
||||
newSize = core::max_(newSize, 0.0001f);
|
||||
if (newSize != Size)
|
||||
{
|
||||
Size = newSize;
|
||||
setSize();
|
||||
}
|
||||
|
||||
ISceneNode::deserializeAttributes(in, options);
|
||||
}
|
||||
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CCubeSceneNode* nb = new CCubeSceneNode(Size, newParent,
|
||||
newManager, ID, RelativeTranslation);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->getMaterial(0) = getMaterial(0);
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_CUBE_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_CUBE_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IMeshSceneNode.h"
|
||||
#include "SMesh.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class CCubeSceneNode : public IMeshSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position = core::vector3df(0,0,0),
|
||||
const core::vector3df& rotation = core::vector3df(0,0,0),
|
||||
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
|
||||
virtual ~CCubeSceneNode();
|
||||
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! renders the node.
|
||||
virtual void render();
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! returns the material based on the zero based index i. To get the amount
|
||||
//! of materials used by this scene node, use getMaterialCount().
|
||||
//! This function is needed for inserting the node into the scene hirachy on a
|
||||
//! optimal position for minimizing renderstate changes, but can also be used
|
||||
//! to directly modify the material of a scene node.
|
||||
virtual video::SMaterial& getMaterial(u32 i);
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
virtual u32 getMaterialCount() const;
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; }
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
//! Sets a new mesh to display
|
||||
virtual void setMesh(IMesh* mesh) {}
|
||||
|
||||
//! Returns the current mesh
|
||||
virtual IMesh* getMesh(void) { return Mesh; }
|
||||
|
||||
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
|
||||
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes
|
||||
referencing this mesh to change too. */
|
||||
virtual void setReadOnlyMaterials(bool readonly) {}
|
||||
|
||||
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
|
||||
virtual bool isReadOnlyMaterials() const { return false; }
|
||||
|
||||
//! Removes a child from this scene node.
|
||||
//! Implemented here, to be able to remove the shadow properly, if there is one,
|
||||
//! or to remove attached childs.
|
||||
virtual bool removeChild(ISceneNode* child);
|
||||
|
||||
private:
|
||||
void setSize();
|
||||
|
||||
IMesh* Mesh;
|
||||
f32 Size;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,499 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
#define __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#ifdef _IRR_WINDOWS_
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "CNullDriver.h"
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_CG_
|
||||
#include "Cg/cg.h"
|
||||
#include "Cg/cgD3D9.h"
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
struct SDepthSurface : public IReferenceCounted
|
||||
{
|
||||
SDepthSurface() : Surface(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("SDepthSurface");
|
||||
#endif
|
||||
}
|
||||
virtual ~SDepthSurface()
|
||||
{
|
||||
if (Surface)
|
||||
Surface->Release();
|
||||
}
|
||||
|
||||
IDirect3DSurface9* Surface;
|
||||
core::dimension2du Size;
|
||||
};
|
||||
|
||||
class CD3D9Driver : public CNullDriver, IMaterialRendererServices
|
||||
{
|
||||
public:
|
||||
|
||||
friend class CD3D9Texture;
|
||||
|
||||
//! constructor
|
||||
CD3D9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io);
|
||||
|
||||
//! destructor
|
||||
virtual ~CD3D9Driver();
|
||||
|
||||
//! applications must call this method before performing any rendering. returns false if failed.
|
||||
virtual bool beginScene(bool backBuffer=true, bool zBuffer=true,
|
||||
SColor color=SColor(255,0,0,0),
|
||||
const SExposedVideoData& videoData=SExposedVideoData(),
|
||||
core::rect<s32>* sourceRect=0);
|
||||
|
||||
//! applications must call this method after performing any rendering. returns false if failed.
|
||||
virtual bool endScene();
|
||||
|
||||
//! queries the features of the driver, returns true if feature is available
|
||||
virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const;
|
||||
|
||||
//! sets transformation
|
||||
virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat);
|
||||
|
||||
//! sets a material
|
||||
virtual void setMaterial(const SMaterial& material);
|
||||
|
||||
//! sets a render target
|
||||
virtual bool setRenderTarget(video::ITexture* texture,
|
||||
bool clearBackBuffer=true, bool clearZBuffer=true,
|
||||
SColor color=video::SColor(0,0,0,0));
|
||||
|
||||
//! Sets multiple render targets
|
||||
virtual bool setRenderTarget(const core::array<video::IRenderTarget>& texture,
|
||||
bool clearBackBuffer=true, bool clearZBuffer=true,
|
||||
SColor color=video::SColor(0,0,0,0));
|
||||
|
||||
//! sets a viewport
|
||||
virtual void setViewPort(const core::rect<s32>& area);
|
||||
|
||||
//! gets the area of the current viewport
|
||||
virtual const core::rect<s32>& getViewPort() const;
|
||||
|
||||
struct SHWBufferLink_d3d9 : public SHWBufferLink
|
||||
{
|
||||
SHWBufferLink_d3d9(const scene::IMeshBuffer *_MeshBuffer):
|
||||
SHWBufferLink(_MeshBuffer),
|
||||
vertexBuffer(0), indexBuffer(0),
|
||||
vertexBufferSize(0), indexBufferSize(0) {}
|
||||
|
||||
IDirect3DVertexBuffer9* vertexBuffer;
|
||||
IDirect3DIndexBuffer9* indexBuffer;
|
||||
|
||||
u32 vertexBufferSize;
|
||||
u32 indexBufferSize;
|
||||
};
|
||||
|
||||
bool updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer);
|
||||
bool updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer);
|
||||
|
||||
//! updates hardware buffer if needed
|
||||
virtual bool updateHardwareBuffer(SHWBufferLink *HWBuffer);
|
||||
|
||||
//! Create hardware buffer from mesh
|
||||
virtual SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer* mb);
|
||||
|
||||
//! Delete hardware buffer (only some drivers can)
|
||||
virtual void deleteHardwareBuffer(SHWBufferLink *HWBuffer);
|
||||
|
||||
//! Draw hardware buffer
|
||||
virtual void drawHardwareBuffer(SHWBufferLink *HWBuffer);
|
||||
|
||||
//! Create occlusion query.
|
||||
/** Use node for identification and mesh for occlusion test. */
|
||||
virtual void addOcclusionQuery(scene::ISceneNode* node,
|
||||
const scene::IMesh* mesh=0);
|
||||
|
||||
//! Remove occlusion query.
|
||||
virtual void removeOcclusionQuery(scene::ISceneNode* node);
|
||||
|
||||
//! Run occlusion query. Draws mesh stored in query.
|
||||
/** If the mesh shall not be rendered visible, use
|
||||
overrideMaterial to disable the color and depth buffer. */
|
||||
virtual void runOcclusionQuery(scene::ISceneNode* node, bool visible=false);
|
||||
|
||||
//! Update occlusion query. Retrieves results from GPU.
|
||||
/** If the query shall not block, set the flag to false.
|
||||
Update might not occur in this case, though */
|
||||
virtual void updateOcclusionQuery(scene::ISceneNode* node, bool block=true);
|
||||
|
||||
//! Return query result.
|
||||
/** Return value is the number of visible pixels/fragments.
|
||||
The value is a safe approximation, i.e. can be larger then the
|
||||
actual value of pixels. */
|
||||
virtual u32 getOcclusionQueryResult(scene::ISceneNode* node) const;
|
||||
|
||||
//! draws a vertex primitive list
|
||||
virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount,
|
||||
const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType);
|
||||
|
||||
//! draws a vertex primitive list in 2d
|
||||
virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount,
|
||||
const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType);
|
||||
|
||||
//! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted.
|
||||
virtual void draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false);
|
||||
|
||||
//! Draws a part of the texture into the rectangle.
|
||||
virtual void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false);
|
||||
|
||||
//! Draws a set of 2d images, using a color and the alpha channel of the texture.
|
||||
virtual void draw2DImageBatch(const video::ITexture* texture,
|
||||
const core::array<core::position2d<s32> >& positions,
|
||||
const core::array<core::rect<s32> >& sourceRects,
|
||||
const core::rect<s32>* clipRect=0,
|
||||
SColor color=SColor(255,255,255,255),
|
||||
bool useAlphaChannelOfTexture=false);
|
||||
|
||||
//!Draws an 2d rectangle with a gradient.
|
||||
virtual void draw2DRectangle(const core::rect<s32>& pos,
|
||||
SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
|
||||
const core::rect<s32>* clip);
|
||||
|
||||
//! Draws a 2d line.
|
||||
virtual void draw2DLine(const core::position2d<s32>& start,
|
||||
const core::position2d<s32>& end,
|
||||
SColor color=SColor(255,255,255,255));
|
||||
|
||||
//! Draws a pixel.
|
||||
virtual void drawPixel(u32 x, u32 y, const SColor & color);
|
||||
|
||||
//! Draws a 3d line.
|
||||
virtual void draw3DLine(const core::vector3df& start,
|
||||
const core::vector3df& end, SColor color = SColor(255,255,255,255));
|
||||
|
||||
//! initialises the Direct3D API
|
||||
bool initDriver(HWND hwnd, bool pureSoftware);
|
||||
|
||||
//! \return Returns the name of the video driver. Example: In case of the DIRECT3D8
|
||||
//! driver, it would return "Direct3D8.1".
|
||||
virtual const wchar_t* getName() const;
|
||||
|
||||
//! deletes all dynamic lights there are
|
||||
virtual void deleteAllDynamicLights();
|
||||
|
||||
//! adds a dynamic light, returning an index to the light
|
||||
//! \param light: the light data to use to create the light
|
||||
//! \return An index to the light, or -1 if an error occurs
|
||||
virtual s32 addDynamicLight(const SLight& light);
|
||||
|
||||
//! Turns a dynamic light on or off
|
||||
//! \param lightIndex: the index returned by addDynamicLight
|
||||
//! \param turnOn: true to turn the light on, false to turn it off
|
||||
virtual void turnLightOn(s32 lightIndex, bool turnOn);
|
||||
|
||||
//! returns the maximal amount of dynamic lights the device can handle
|
||||
virtual u32 getMaximalDynamicLightAmount() const;
|
||||
|
||||
//! Sets the dynamic ambient light color. The default color is
|
||||
//! (0,0,0,0) which means it is dark.
|
||||
//! \param color: New color of the ambient light.
|
||||
virtual void setAmbientLight(const SColorf& color);
|
||||
|
||||
//! Draws a shadow volume into the stencil buffer.
|
||||
virtual void drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail=true, u32 debugDataVisible=0);
|
||||
|
||||
//! Fills the stencil shadow with color.
|
||||
virtual void drawStencilShadow(bool clearStencilBuffer=false,
|
||||
video::SColor leftUpEdge = video::SColor(0,0,0,0),
|
||||
video::SColor rightUpEdge = video::SColor(0,0,0,0),
|
||||
video::SColor leftDownEdge = video::SColor(0,0,0,0),
|
||||
video::SColor rightDownEdge = video::SColor(0,0,0,0));
|
||||
|
||||
//! Returns the maximum amount of primitives (mostly vertices) which
|
||||
//! the device is able to render with one drawIndexedTriangleList
|
||||
//! call.
|
||||
virtual u32 getMaximalPrimitiveCount() const;
|
||||
|
||||
//! Enables or disables a texture creation flag.
|
||||
virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled);
|
||||
|
||||
//! Sets the fog mode.
|
||||
virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start,
|
||||
f32 end, f32 density, bool pixelFog, bool rangeFog);
|
||||
|
||||
//! Only used by the internal engine. Used to notify the driver that
|
||||
//! the window was resized.
|
||||
virtual void OnResize(const core::dimension2d<u32>& size);
|
||||
|
||||
//! Can be called by an IMaterialRenderer to make its work easier.
|
||||
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates);
|
||||
|
||||
//! Returns type of video driver
|
||||
virtual E_DRIVER_TYPE getDriverType() const;
|
||||
|
||||
//! Returns the transformation set by setTransform
|
||||
virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const;
|
||||
|
||||
//! Sets a vertex shader constant.
|
||||
virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
|
||||
|
||||
//! Sets a pixel shader constant.
|
||||
virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
|
||||
|
||||
//! Sets a constant for the vertex shader based on a name.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count);
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count);
|
||||
|
||||
//! Sets a constant for the pixel shader based on a name.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count);
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count);
|
||||
|
||||
//! Returns a pointer to the IVideoDriver interface. (Implementation for
|
||||
//! IMaterialRendererServices)
|
||||
virtual IVideoDriver* getVideoDriver();
|
||||
|
||||
//! Creates a render target texture.
|
||||
virtual ITexture* addRenderTargetTexture(const core::dimension2d<u32>& size,
|
||||
const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN, const bool useStencil = false);
|
||||
|
||||
//! Clears the ZBuffer.
|
||||
virtual void clearZBuffer();
|
||||
|
||||
//! Returns an image created from the last rendered frame.
|
||||
virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER);
|
||||
|
||||
//! Set/unset a clipping plane.
|
||||
virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false);
|
||||
|
||||
//! Enable/disable a clipping plane.
|
||||
virtual void enableClipPlane(u32 index, bool enable);
|
||||
|
||||
//! Returns the graphics card vendor name.
|
||||
virtual core::stringc getVendorInfo() {return VendorName;}
|
||||
|
||||
//! Enable the 2d override material
|
||||
virtual void enableMaterial2D(bool enable=true);
|
||||
|
||||
//! Check if the driver was recently reset.
|
||||
virtual bool checkDriverReset() {return DriverWasReset;}
|
||||
|
||||
// removes the depth struct from the DepthSurface array
|
||||
void removeDepthSurface(SDepthSurface* depth);
|
||||
|
||||
//! Get the current color format of the color buffer
|
||||
/** \return Color format of the color buffer. */
|
||||
virtual ECOLOR_FORMAT getColorFormat() const;
|
||||
|
||||
//! Returns the maximum texture size supported.
|
||||
virtual core::dimension2du getMaxTextureSize() const;
|
||||
|
||||
//! Get the current color format of the color buffer
|
||||
/** \return Color format of the color buffer as D3D color value. */
|
||||
D3DFORMAT getD3DColorFormat() const;
|
||||
|
||||
//! Get D3D color format from Irrlicht color format.
|
||||
D3DFORMAT getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const;
|
||||
|
||||
//! Get Irrlicht color format from D3D color format.
|
||||
ECOLOR_FORMAT getColorFormatFromD3DFormat(D3DFORMAT format) const;
|
||||
|
||||
//! Get Cg context
|
||||
#ifdef _IRR_COMPILE_WITH_CG_
|
||||
const CGcontext& getCgContext();
|
||||
#endif
|
||||
|
||||
virtual void enableScissorTest(const core::rect<s32>& r);
|
||||
virtual void disableScissorTest();
|
||||
|
||||
private:
|
||||
|
||||
//! enumeration for rendering modes such as 2d and 3d for minizing the switching of renderStates.
|
||||
enum E_RENDER_MODE
|
||||
{
|
||||
ERM_NONE = 0, // no render state has been set yet.
|
||||
ERM_2D, // 2d drawing rendermode
|
||||
ERM_3D, // 3d rendering mode
|
||||
ERM_STENCIL_FILL, // stencil fill mode
|
||||
ERM_SHADOW_VOLUME_ZFAIL, // stencil volume draw mode
|
||||
ERM_SHADOW_VOLUME_ZPASS // stencil volume draw mode
|
||||
};
|
||||
|
||||
//! sets right vertex shader
|
||||
void setVertexShader(video::E_VERTEX_TYPE newType);
|
||||
|
||||
//! sets the needed renderstates
|
||||
bool setRenderStates3DMode();
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel);
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStatesStencilFillMode(bool alpha);
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStatesStencilShadowMode(bool zfail, u32 debugDataVisible);
|
||||
|
||||
//! sets the current Texture
|
||||
bool setActiveTexture(u32 stage, const video::ITexture* texture);
|
||||
|
||||
//! resets the device
|
||||
bool reset();
|
||||
|
||||
//! returns a device dependent texture from a software surface (IImage)
|
||||
//! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES
|
||||
virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0);
|
||||
|
||||
//! returns the current size of the screen or rendertarget
|
||||
virtual const core::dimension2d<u32>& getCurrentRenderTargetSize() const;
|
||||
|
||||
//! Check if a proper depth buffer for the RTT is available, otherwise create it.
|
||||
void checkDepthBuffer(ITexture* tex);
|
||||
|
||||
//! Adds a new material renderer to the VideoDriver, using pixel and/or
|
||||
//! vertex shaders to render geometry.
|
||||
s32 addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
E_MATERIAL_TYPE baseMaterial, s32 userData);
|
||||
|
||||
//! Adds a new material renderer to the VideoDriver, based on a high level shading
|
||||
//! language.
|
||||
virtual s32 addHighLevelShaderMaterial(
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const c8* geometryShaderProgram,
|
||||
const c8* geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack* callback = 0,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0,
|
||||
E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT);
|
||||
|
||||
void createMaterialRenderers();
|
||||
|
||||
void draw2D3DVertexPrimitiveList(const void* vertices,
|
||||
u32 vertexCount, const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType, bool is3D);
|
||||
|
||||
D3DTEXTUREADDRESS getTextureWrapMode(const u8 clamp);
|
||||
|
||||
inline D3DCOLORVALUE colorToD3D(const SColor& col)
|
||||
{
|
||||
const f32 f = 1.0f / 255.0f;
|
||||
D3DCOLORVALUE v;
|
||||
v.r = col.getRed() * f;
|
||||
v.g = col.getGreen() * f;
|
||||
v.b = col.getBlue() * f;
|
||||
v.a = col.getAlpha() * f;
|
||||
return v;
|
||||
}
|
||||
|
||||
E_RENDER_MODE CurrentRenderMode;
|
||||
D3DPRESENT_PARAMETERS present;
|
||||
|
||||
SMaterial Material, LastMaterial;
|
||||
bool ResetRenderStates; // bool to make all renderstates be reseted if set.
|
||||
bool Transformation3DChanged;
|
||||
const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES];
|
||||
bool LastTextureMipMapsAvailable[MATERIAL_MAX_TEXTURES];
|
||||
core::matrix4 Matrices[ETS_COUNT]; // matrizes of the 3d mode we need to restore when we switch back from the 2d mode.
|
||||
|
||||
HINSTANCE D3DLibrary;
|
||||
IDirect3D9* pID3D;
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
|
||||
IDirect3DSurface9* PrevRenderTarget;
|
||||
core::dimension2d<u32> CurrentRendertargetSize;
|
||||
|
||||
HWND WindowId;
|
||||
core::rect<s32>* SceneSourceRect;
|
||||
|
||||
D3DCAPS9 Caps;
|
||||
|
||||
SIrrlichtCreationParameters Params;
|
||||
|
||||
E_VERTEX_TYPE LastVertexType;
|
||||
|
||||
SColorf AmbientLight;
|
||||
|
||||
core::stringc VendorName;
|
||||
u16 VendorID;
|
||||
|
||||
core::array<SDepthSurface*> DepthBuffers;
|
||||
|
||||
u32 MaxTextureUnits;
|
||||
u32 MaxUserClipPlanes;
|
||||
u32 MaxMRTs;
|
||||
u32 NumSetMRTs;
|
||||
f32 MaxLightDistance;
|
||||
s32 LastSetLight;
|
||||
|
||||
enum E_CACHE_2D_ATTRIBUTES
|
||||
{
|
||||
EC2D_ALPHA = 0x1,
|
||||
EC2D_TEXTURE = 0x2,
|
||||
EC2D_ALPHA_CHANNEL = 0x4
|
||||
};
|
||||
|
||||
ECOLOR_FORMAT ColorFormat;
|
||||
D3DFORMAT D3DColorFormat;
|
||||
bool DeviceLost;
|
||||
bool DriverWasReset;
|
||||
bool OcclusionQuerySupport;
|
||||
bool AlphaToCoverageSupport;
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_CG_
|
||||
CGcontext CgContext;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#endif // __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
|
||||
@@ -0,0 +1,429 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#define _IRR_D3D_NO_SHADER_DEBUGGING 1
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9HLSLMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
#ifndef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
//! Public constructor
|
||||
CD3D9HLSLMaterialRenderer::CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver, s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, callback, baseMaterial, userData),
|
||||
VSConstantsTable(0), PSConstantsTable(0)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9HLSLMaterialRenderer");
|
||||
#endif
|
||||
|
||||
outMaterialTypeNr = -1;
|
||||
|
||||
// now create shaders
|
||||
|
||||
if (vsCompileTarget < 0 || vsCompileTarget > EVST_COUNT)
|
||||
{
|
||||
os::Printer::log("Invalid HLSL vertex shader compilation target", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!createHLSLVertexShader(vertexShaderProgram,
|
||||
vertexShaderEntryPointName, VERTEX_SHADER_TYPE_NAMES[vsCompileTarget]))
|
||||
return;
|
||||
|
||||
if (!createHLSLPixelShader(pixelShaderProgram,
|
||||
pixelShaderEntryPointName, PIXEL_SHADER_TYPE_NAMES[psCompileTarget]))
|
||||
return;
|
||||
|
||||
// register myself as new material
|
||||
outMaterialTypeNr = Driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
//! Destructor
|
||||
CD3D9HLSLMaterialRenderer::~CD3D9HLSLMaterialRenderer()
|
||||
{
|
||||
if (VSConstantsTable)
|
||||
VSConstantsTable->Release();
|
||||
|
||||
if (PSConstantsTable)
|
||||
PSConstantsTable->Release();
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::createHLSLVertexShader(const char* vertexShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName)
|
||||
{
|
||||
if (!vertexShaderProgram)
|
||||
return true;
|
||||
|
||||
LPD3DXBUFFER buffer = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile without debug info
|
||||
HRESULT h = stubD3DXCompileShader(
|
||||
vertexShaderProgram,
|
||||
strlen(vertexShaderProgram),
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
0, // no flags
|
||||
&buffer,
|
||||
&errors,
|
||||
&VSConstantsTable);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_hlsl_file_nr = 0;
|
||||
++irr_dbg_hlsl_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.vsh", irr_dbg_hlsl_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(vertexShaderProgram, strlen(vertexShaderProgram), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
HRESULT h = stubD3DXCompileShaderFromFile(
|
||||
tmp,
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION,
|
||||
&buffer,
|
||||
&errors,
|
||||
&VSConstantsTable);
|
||||
|
||||
#endif
|
||||
|
||||
if (FAILED(h))
|
||||
{
|
||||
os::Printer::log("HLSL vertex shader compilation failed:", ELL_ERROR);
|
||||
if (errors)
|
||||
{
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
errors->Release();
|
||||
if (buffer)
|
||||
buffer->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errors)
|
||||
errors->Release();
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
if (FAILED(pID3DDevice->CreateVertexShader((DWORD*)buffer->GetBufferPointer(),
|
||||
&VertexShader)))
|
||||
{
|
||||
os::Printer::log("Could not create hlsl vertex shader.", ELL_ERROR);
|
||||
buffer->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName)
|
||||
{
|
||||
if (!pixelShaderProgram)
|
||||
return true;
|
||||
|
||||
LPD3DXBUFFER buffer = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
DWORD flags = 0;
|
||||
|
||||
#ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY
|
||||
if (Driver->queryFeature(video::EVDF_VERTEX_SHADER_2_0) || Driver->queryFeature(video::EVDF_VERTEX_SHADER_3_0))
|
||||
// this one's for newer DX SDKs which don't support ps_1_x anymore
|
||||
// instead they'll silently compile 1_x as 2_x when using this flag
|
||||
flags |= D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY;
|
||||
#endif
|
||||
#if defined(_IRR_D3D_USE_LEGACY_HLSL_COMPILER) && defined(D3DXSHADER_USE_LEGACY_D3DX9_31_DLL)
|
||||
#ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY
|
||||
else
|
||||
#endif
|
||||
flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL;
|
||||
#endif
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile without debug info
|
||||
HRESULT h = stubD3DXCompileShader(
|
||||
pixelShaderProgram,
|
||||
strlen(pixelShaderProgram),
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
flags,
|
||||
&buffer,
|
||||
&errors,
|
||||
&PSConstantsTable);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_hlsl_file_nr = 0;
|
||||
++irr_dbg_hlsl_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.psh", irr_dbg_hlsl_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(pixelShaderProgram, strlen(pixelShaderProgram), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
HRESULT h = stubD3DXCompileShaderFromFile(
|
||||
tmp,
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
flags | D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION,
|
||||
&buffer,
|
||||
&errors,
|
||||
&PSConstantsTable);
|
||||
|
||||
#endif
|
||||
|
||||
if (FAILED(h))
|
||||
{
|
||||
os::Printer::log("HLSL pixel shader compilation failed:", ELL_ERROR);
|
||||
if (errors)
|
||||
{
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
errors->Release();
|
||||
if (buffer)
|
||||
buffer->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errors)
|
||||
errors->Release();
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)buffer->GetBufferPointer(),
|
||||
&PixelShader)))
|
||||
{
|
||||
os::Printer::log("Could not create hlsl pixel shader.", ELL_ERROR);
|
||||
buffer->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name,
|
||||
const f32* floats, int count)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (!tbl)
|
||||
return false;
|
||||
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name);
|
||||
if (!hndl)
|
||||
{
|
||||
core::stringc s = "HLSL Variable to set not found: '";
|
||||
s += name;
|
||||
s += "'. Available variables are:";
|
||||
os::Printer::log(s.c_str(), ELL_WARNING);
|
||||
printHLSLVariables(tbl);
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DXCONSTANT_DESC Description;
|
||||
UINT ucount = 1;
|
||||
tbl->GetConstantDesc(hndl, &Description, &ucount);
|
||||
|
||||
if(Description.RegisterSet != D3DXRS_SAMPLER)
|
||||
{
|
||||
HRESULT hr = tbl->SetFloatArray(pID3DDevice, hndl, floats, count);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Error setting float array for HLSL variable", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name,
|
||||
const bool* bools, int count)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (!tbl)
|
||||
return false;
|
||||
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name);
|
||||
if (!hndl)
|
||||
{
|
||||
core::stringc s = "HLSL Variable to set not found: '";
|
||||
s += name;
|
||||
s += "'. Available variables are:";
|
||||
os::Printer::log(s.c_str(), ELL_WARNING);
|
||||
printHLSLVariables(tbl);
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DXCONSTANT_DESC Description;
|
||||
UINT ucount = 1;
|
||||
tbl->GetConstantDesc(hndl, &Description, &ucount);
|
||||
|
||||
if(Description.RegisterSet != D3DXRS_SAMPLER)
|
||||
{
|
||||
HRESULT hr = tbl->SetBoolArray(pID3DDevice, hndl, (BOOL*)bools, count);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Error setting bool array for HLSL variable", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name,
|
||||
const s32* ints, int count)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (!tbl)
|
||||
return false;
|
||||
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name);
|
||||
if (!hndl)
|
||||
{
|
||||
core::stringc s = "HLSL Variable to set not found: '";
|
||||
s += name;
|
||||
s += "'. Available variables are:";
|
||||
os::Printer::log(s.c_str(), ELL_WARNING);
|
||||
printHLSLVariables(tbl);
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DXCONSTANT_DESC Description;
|
||||
UINT ucount = 1;
|
||||
tbl->GetConstantDesc(hndl, &Description, &ucount);
|
||||
|
||||
if(Description.RegisterSet != D3DXRS_SAMPLER)
|
||||
{
|
||||
HRESULT hr = tbl->SetIntArray(pID3DDevice, hndl, ints, count);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Error setting int array for HLSL variable", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (VSConstantsTable)
|
||||
VSConstantsTable->SetDefaults(pID3DDevice);
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9HLSLMaterialRenderer::printHLSLVariables(LPD3DXCONSTANTTABLE table)
|
||||
{
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
// print out constant names
|
||||
D3DXCONSTANTTABLE_DESC tblDesc;
|
||||
HRESULT hr = table->GetDesc(&tblDesc);
|
||||
if (!FAILED(hr))
|
||||
{
|
||||
for (int i=0; i<(int)tblDesc.Constants; ++i)
|
||||
{
|
||||
D3DXCONSTANT_DESC d;
|
||||
UINT n = 1;
|
||||
D3DXHANDLE cHndl = table->GetConstant(NULL, i);
|
||||
if (!FAILED(table->GetConstantDesc(cHndl, &d, &n)))
|
||||
{
|
||||
core::stringc s = " '";
|
||||
s += d.Name;
|
||||
s += "' Registers:[begin:";
|
||||
s += (int)d.RegisterIndex;
|
||||
s += ", count:";
|
||||
s += (int)d.RegisterCount;
|
||||
s += "]";
|
||||
os::Printer::log(s.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_HLSL_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_HLSL_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IGPUProgrammingServices.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class IVideoDriver;
|
||||
class IShaderConstantSetCallBack;
|
||||
class IMaterialRenderer;
|
||||
|
||||
//! Class for using vertex and pixel shaders via HLSL with D3D9
|
||||
class CD3D9HLSLMaterialRenderer : public CD3D9ShaderMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Public constructor
|
||||
CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData);
|
||||
|
||||
//! Destructor
|
||||
~CD3D9HLSLMaterialRenderer();
|
||||
|
||||
//! sets a variable in the shader.
|
||||
//! \param vertexShader: True if this should be set in the vertex shader, false if
|
||||
//! in the pixel shader.
|
||||
//! \param name: Name of the variable
|
||||
//! \param floats: Pointer to array of floats
|
||||
//! \param count: Amount of floats in array.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const f32* floats, int count);
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const bool* bools, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const s32* ints, int count);
|
||||
|
||||
bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
protected:
|
||||
|
||||
bool createHLSLVertexShader(const char* vertexShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName);
|
||||
|
||||
bool createHLSLPixelShader(const char* pixelShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName);
|
||||
|
||||
void printHLSLVariables(LPD3DXCONSTANTTABLE table);
|
||||
|
||||
LPD3DXCONSTANTTABLE VSConstantsTable;
|
||||
LPD3DXCONSTANTTABLE PSConstantsTable;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,615 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "IMaterialRenderer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
D3DMATRIX UnitMatrixD3D9;
|
||||
D3DMATRIX SphereMapMatrixD3D9;
|
||||
inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i,
|
||||
DWORD arg1, DWORD op, DWORD arg2)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_COLOROP, op);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG2, arg2);
|
||||
}
|
||||
inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
|
||||
}
|
||||
|
||||
inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i,
|
||||
DWORD arg1, DWORD op, DWORD arg2)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAOP, op);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG2, arg2);
|
||||
}
|
||||
inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
//! Base class for all internal D3D9 material renderers
|
||||
class CD3D9MaterialRenderer : public IMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CD3D9MaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver)
|
||||
: pID3DDevice(d3ddev), Driver(driver)
|
||||
{
|
||||
}
|
||||
|
||||
//! sets a variable in the shader.
|
||||
//! \param vertexShader: True if this should be set in the vertex shader, false if
|
||||
//! in the pixel shader.
|
||||
//! \param name: Name of the variable
|
||||
//! \param floats: Pointer to array of floats
|
||||
//! \param count: Amount of floats in array.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const f32* floats, int count)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const bool* bools, int count)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const s32* ints, int count)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
video::IVideoDriver* Driver;
|
||||
};
|
||||
|
||||
|
||||
//! Solid material renderer
|
||||
class CD3D9MaterialRenderer_SOLID : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SOLID(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
};
|
||||
|
||||
//! Generic Texture Blend
|
||||
class CD3D9MaterialRenderer_ONETEXTURE_BLEND : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType ||
|
||||
material.MaterialTypeParam != lastMaterial.MaterialTypeParam ||
|
||||
resetAllRenderstates)
|
||||
{
|
||||
|
||||
E_BLEND_FACTOR srcFact,dstFact;
|
||||
E_MODULATE_FUNC modulate;
|
||||
u32 alphaSource;
|
||||
unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam );
|
||||
|
||||
if (srcFact == EBF_SRC_COLOR && dstFact == EBF_ZERO)
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, getD3DBlend ( srcFact ) );
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, getD3DBlend ( dstFact ) );
|
||||
}
|
||||
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, getD3DModulate(modulate), D3DTA_DIFFUSE);
|
||||
|
||||
if ( textureBlendFunc_hasAlpha ( srcFact ) || textureBlendFunc_hasAlpha ( dstFact ) )
|
||||
{
|
||||
if (alphaSource==EAS_VERTEX_COLOR)
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
}
|
||||
else if (alphaSource==EAS_TEXTURE)
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent.
|
||||
/** The scene management needs to know this for being able to sort the
|
||||
materials by opaque and transparent.
|
||||
The return value could be optimized, but we'd need to know the
|
||||
MaterialTypeParam for it. */
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
u32 getD3DBlend ( E_BLEND_FACTOR factor ) const
|
||||
{
|
||||
u32 r = 0;
|
||||
switch ( factor )
|
||||
{
|
||||
case EBF_ZERO: r = D3DBLEND_ZERO; break;
|
||||
case EBF_ONE: r = D3DBLEND_ONE; break;
|
||||
case EBF_DST_COLOR: r = D3DBLEND_DESTCOLOR; break;
|
||||
case EBF_ONE_MINUS_DST_COLOR: r = D3DBLEND_INVDESTCOLOR; break;
|
||||
case EBF_SRC_COLOR: r = D3DBLEND_SRCCOLOR; break;
|
||||
case EBF_ONE_MINUS_SRC_COLOR: r = D3DBLEND_INVSRCCOLOR; break;
|
||||
case EBF_SRC_ALPHA: r = D3DBLEND_SRCALPHA; break;
|
||||
case EBF_ONE_MINUS_SRC_ALPHA: r = D3DBLEND_INVSRCALPHA; break;
|
||||
case EBF_DST_ALPHA: r = D3DBLEND_DESTALPHA; break;
|
||||
case EBF_ONE_MINUS_DST_ALPHA: r = D3DBLEND_INVDESTALPHA; break;
|
||||
case EBF_SRC_ALPHA_SATURATE: r = D3DBLEND_SRCALPHASAT; break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
u32 getD3DModulate ( E_MODULATE_FUNC func ) const
|
||||
{
|
||||
u32 r = D3DTOP_MODULATE;
|
||||
switch ( func )
|
||||
{
|
||||
case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break;
|
||||
case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break;
|
||||
case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
bool transparent;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! Solid 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_SOLID_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent add color material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene management needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent vertex alpha material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent alpha channel material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates
|
||||
|| material.MaterialTypeParam != lastMaterial.MaterialTypeParam )
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAREF, core::floor32(material.MaterialTypeParam * 255.f));
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! Transparent alpha channel material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
|
||||
// 127 is required by EMT_TRANSPARENT_ALPHA_CHANNEL_REF
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAREF, 127);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return false; // this material is not really transparent because it does no blending.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! material renderer for all kinds of lightmaps
|
||||
class CD3D9MaterialRenderer_LIGHTMAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_LIGHTMAP(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
if (material.MaterialType >= EMT_LIGHTMAP_LIGHTING)
|
||||
{
|
||||
// with lighting
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE,
|
||||
(material.MaterialType == EMT_LIGHTMAP_ADD)?
|
||||
D3DTOP_ADD:
|
||||
(material.MaterialType == EMT_LIGHTMAP_M4 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M4)?
|
||||
D3DTOP_MODULATE4X:
|
||||
(material.MaterialType == EMT_LIGHTMAP_M2 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M2)?
|
||||
D3DTOP_MODULATE2X:
|
||||
D3DTOP_MODULATE,
|
||||
D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! material renderer for detail maps
|
||||
class CD3D9MaterialRenderer_DETAIL_MAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_DETAIL_MAP(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_ADDSIGNED, D3DTA_CURRENT);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! sphere map material renderer
|
||||
class CD3D9MaterialRenderer_SPHERE_MAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SPHERE_MAP(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE0, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL );
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0);
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE0, &UnitMatrixD3D9 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! reflection 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_REFLECTION_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE1, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE1, &UnitMatrixD3D9 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! reflection 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 1, D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &UnitMatrixD3D9);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9NormalMapRenderer.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "os.h"
|
||||
#include "SLight.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
// 1.1 Shaders with two lights and vertex based attenuation
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map vertex shader
|
||||
const char D3D9_NORMAL_MAP_VSH[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map vertex shader\n"\
|
||||
"; c0-3: Transposed world matrix \n"\
|
||||
"; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\
|
||||
"; c12: Light01 position \n"\
|
||||
"; c13: x,y,z: Light01 color; .w: 1/LightRadius^2 \n"\
|
||||
"; c14: Light02 position \n"\
|
||||
"; c15: x,y,z: Light02 color; .w: 1/LightRadius^2 \n"\
|
||||
"vs.1.1\n"\
|
||||
"dcl_position v0 ; position \n"\
|
||||
"dcl_normal v1 ; normal \n"\
|
||||
"dcl_color v2 ; color \n"\
|
||||
"dcl_texcoord0 v3 ; texture coord \n"\
|
||||
"dcl_texcoord1 v4 ; tangent \n"\
|
||||
"dcl_texcoord2 v5 ; binormal \n"\
|
||||
"\n"\
|
||||
"def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\
|
||||
"\n"\
|
||||
"m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\
|
||||
"\n"\
|
||||
"m3x3 r5, v4, c0 ; transform tangent U\n"\
|
||||
"m3x3 r7, v1, c0 ; transform normal W\n"\
|
||||
"m3x3 r6, v5, c0 ; transform binormal V\n"\
|
||||
"\n"\
|
||||
"m4x4 r4, v0, c0 ; vertex into world position\n"\
|
||||
"add r2, c12, -r4 ; vtxpos - lightpos1\n"\
|
||||
"add r3, c14, -r4 ; vtxpos - lightpos2\n"\
|
||||
"\n"\
|
||||
"dp3 r8.x, r5, r2 ; transform the light vector 1 with U, V, W\n"\
|
||||
"dp3 r8.y, r6, r2 \n"\
|
||||
"dp3 r8.z, r7, r2 \n"\
|
||||
"dp3 r9.x, r5, r3 ; transform the light vector 2 with U, V, W\n"\
|
||||
"dp3 r9.y, r6, r3 \n"\
|
||||
"dp3 r9.z, r7, r3 \n"\
|
||||
"\n"\
|
||||
"dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\
|
||||
"rsq r8.w, r8.w \n"\
|
||||
"mul r8, r8, r8.w \n"\
|
||||
"dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\
|
||||
"rsq r9.w, r9.w \n"\
|
||||
"mul r9, r9, r9.w \n"\
|
||||
"\n"\
|
||||
"mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\
|
||||
"mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 1 \n"\
|
||||
"dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x^2 + r2.y^2 + r2.z^2 \n"\
|
||||
"mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\
|
||||
"rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 2 \n"\
|
||||
"dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x^2 + r3.y^2 + r3.z^2 \n"\
|
||||
"mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\
|
||||
"rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
"mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\
|
||||
"mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\
|
||||
"mov oD0.a, v2.a ; move out original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader
|
||||
const char D3D9_NORMAL_MAP_PSH_1_1[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
"ps.1.1 \n"\
|
||||
"tex t0 ; sample color map \n"\
|
||||
"tex t1 ; sample normal map\n"\
|
||||
"texcoord t2 ; fetch light vector 1\n"\
|
||||
"texcoord t3 ; fetch light vector 2\n"\
|
||||
"\n"\
|
||||
"dp3_sat r0, t1_bx2, t2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1)\n"\
|
||||
"mul r0, r0, v0 ; luminance1 * light color 1 \n"\
|
||||
"\n"\
|
||||
"dp3_sat r1, t1_bx2, t3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1)\n"\
|
||||
"mad r0, r1, v1, r0 ; (luminance2 * light color 2) + luminance 1 \n"\
|
||||
"\n"\
|
||||
"mul r0.xyz, t0, r0 ; total luminance * base color\n"\
|
||||
"+mov r0.a, v0.a ; write interpolated vertex alpha value \n"\
|
||||
"\n"\
|
||||
"";
|
||||
|
||||
// Higher-quality normal map pixel shader (requires PS 2.0)
|
||||
// uses per-pixel normalization for improved accuracy
|
||||
const char D3D9_NORMAL_MAP_PSH_2_0[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
|
||||
"ps_2_0 \n"\
|
||||
"def c0, 0, 0, 0, 0\n"\
|
||||
"def c1, 1.0, 1.0, 1.0, 1.0\n"\
|
||||
"def c2, 2.0, 2.0, 2.0, 2.0\n"\
|
||||
"def c3, -.5, -.5, -.5, -.5\n"\
|
||||
"dcl t0\n"\
|
||||
"dcl t1\n"\
|
||||
"dcl t2\n"\
|
||||
"dcl t3\n"\
|
||||
"dcl v1\n"\
|
||||
"dcl v0\n"\
|
||||
"dcl_2d s0\n"\
|
||||
"dcl_2d s1\n"\
|
||||
|
||||
"texld r0, t0, s0 ; sample color map into r0 \n"\
|
||||
"texld r4, t0, s1 ; sample normal map into r4\n"\
|
||||
"add r4, r4, c3 ; bias the normal vector\n"\
|
||||
"add r5, t2, c3 ; bias the light 1 vector into r5\n"\
|
||||
"add r6, t3, c3 ; bias the light 2 vector into r6\n"\
|
||||
|
||||
"nrm r1, r4 ; normalize the normal vector into r1\n"\
|
||||
"nrm r2, r5 ; normalize the light1 vector into r2\n"\
|
||||
"nrm r3, r6 ; normalize the light2 vector into r3\n"\
|
||||
|
||||
"dp3 r2, r2, r1 ; let r2 = normal DOT light 1 vector\n"\
|
||||
"max r2, r2, c0 ; clamp result to positive numbers\n"\
|
||||
"mul r2, r2, v0 ; let r2 = luminance1 * light color 1 \n"\
|
||||
|
||||
"dp3 r3, r3, r1 ; let r3 = normal DOT light 2 vector\n"\
|
||||
"max r3, r3, c0 ; clamp result to positive numbers\n"\
|
||||
|
||||
"mad r2, r3, v1, r2 ; let r2 = (luminance2 * light color 2) + (luminance2 * light color 1) \n"\
|
||||
|
||||
"mul r2, r2, r0 ; let r2 = total luminance * base color\n"\
|
||||
"mov r2.w, v0.w ; write interpolated vertex alpha value \n"\
|
||||
|
||||
"mov oC0, r2 ; copy r2 to the output register \n"\
|
||||
|
||||
"\n"\
|
||||
"";
|
||||
|
||||
CD3D9NormalMapRenderer::CD3D9NormalMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9NormalMapRenderer");
|
||||
#endif
|
||||
|
||||
// set this as callback. We could have done this in
|
||||
// the initialization list, but some compilers don't like it.
|
||||
|
||||
CallBack = this;
|
||||
|
||||
// basically, this thing simply compiles the hardcoded shaders
|
||||
// if the hardware is able to do them, otherwise it maps to the
|
||||
// base material
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) ||
|
||||
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
{
|
||||
// this hardware is not able to do shaders. Fall back to
|
||||
// base material.
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if already compiled normal map shaders are there.
|
||||
|
||||
video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID);
|
||||
if (renderer)
|
||||
{
|
||||
// use the already compiled shaders
|
||||
video::CD3D9NormalMapRenderer* nmr = (video::CD3D9NormalMapRenderer*)renderer;
|
||||
VertexShader = nmr->VertexShader;
|
||||
if (VertexShader)
|
||||
VertexShader->AddRef();
|
||||
|
||||
PixelShader = nmr->PixelShader;
|
||||
if (PixelShader)
|
||||
PixelShader->AddRef();
|
||||
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// compile shaders on our own
|
||||
if (driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0))
|
||||
{
|
||||
init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_2_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_1_1);
|
||||
}
|
||||
}
|
||||
// something failed, use base material
|
||||
if (-1==outMaterialTypeNr)
|
||||
driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
CD3D9NormalMapRenderer::~CD3D9NormalMapRenderer()
|
||||
{
|
||||
if (CallBack == this)
|
||||
CallBack = 0;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9NormalMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (vtxtype != video::EVT_TANGENTS)
|
||||
{
|
||||
os::Printer::log("Error: Normal map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
s32 CD3D9NormalMapRenderer::getRenderCapability() const
|
||||
{
|
||||
if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
|
||||
Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants
|
||||
//! for an material renderer should be set.
|
||||
void CD3D9NormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
|
||||
{
|
||||
video::IVideoDriver* driver = services->getVideoDriver();
|
||||
|
||||
// set transposed world matrix
|
||||
services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
|
||||
|
||||
// set transposed worldViewProj matrix
|
||||
core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
|
||||
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||
services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
|
||||
|
||||
// here we've got to fetch the fixed function lights from the
|
||||
// driver and set them as constants
|
||||
|
||||
u32 cnt = driver->getDynamicLightCount();
|
||||
|
||||
for (u32 i=0; i<2; ++i)
|
||||
{
|
||||
SLight light;
|
||||
|
||||
if (i<cnt)
|
||||
light = driver->getDynamicLight(i);
|
||||
else
|
||||
{
|
||||
light.DiffuseColor.set(0,0,0); // make light dark
|
||||
light.Radius = 1.0f;
|
||||
}
|
||||
|
||||
light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
|
||||
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
|
||||
}
|
||||
|
||||
// this is not really necessary in d3d9 (used a def instruction), but to be sure:
|
||||
f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
|
||||
services->setVertexShaderConstant(c95, 95, 1);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Renderer for normal maps
|
||||
class CD3D9NormalMapRenderer :
|
||||
public CD3D9ShaderMaterialRenderer, IShaderConstantSetCallBack
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9NormalMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
|
||||
|
||||
~CD3D9NormalMapRenderer();
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants for an
|
||||
//! material renderer should be set.
|
||||
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData);
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
virtual s32 getRenderCapability() const;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,410 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9ParallaxMapRenderer.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "SLight.h"
|
||||
|
||||
//#define SHADER_EXTERNAL_DEBUG
|
||||
|
||||
#ifdef SHADER_EXTERNAL_DEBUG
|
||||
#include "CReadFile.h"
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
// 1.1/1.4 Shaders with two lights and vertex based attenuation
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map vertex shader
|
||||
const char D3D9_PARALLAX_MAP_VSH[] =
|
||||
";Irrlicht Engine 0.10 D3D9 render path parallax mapping vertex shader\n"\
|
||||
"; c0-3: Transposed world matrix \n"\
|
||||
"; c4: Eye position \n"\
|
||||
"; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\
|
||||
"; c12: Light01 position \n"\
|
||||
"; c13: x,y,z: Light01 color; .w: 1/LightRadius² \n"\
|
||||
"; c14: Light02 position \n"\
|
||||
"; c15: x,y,z: Light02 color; .w: 1/LightRadius² \n"\
|
||||
"vs.1.1\n"\
|
||||
"dcl_position v0 ; position \n"\
|
||||
"dcl_normal v1 ; normal \n"\
|
||||
"dcl_color v2 ; color \n"\
|
||||
"dcl_texcoord0 v3 ; texture coord \n"\
|
||||
"dcl_texcoord1 v4 ; tangent \n"\
|
||||
"dcl_texcoord2 v5 ; binormal \n"\
|
||||
"\n"\
|
||||
"def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\
|
||||
"def c96, -1, 1, 1, 1 ; somewhere I've got a bug. flipping the vectors with this fixes it. \n"\
|
||||
"\n"\
|
||||
"m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\
|
||||
"\n"\
|
||||
"m3x3 r5, v4, c0 ; transform tangent U\n"\
|
||||
"m3x3 r7, v1, c0 ; transform normal W\n"\
|
||||
"m3x3 r6, v5, c0 ; transform binormal V\n"\
|
||||
"\n"\
|
||||
"m4x4 r4, v0, c0 ; vertex into world position\n"\
|
||||
"add r2, c12, -r4 ; vtxpos - light1 pos\n"\
|
||||
"add r3, c14, -r4 ; vtxpos - light2 pos\n"\
|
||||
"add r1, -c4, r4 ; eye - vtxpos \n"\
|
||||
"\n"\
|
||||
"dp3 r8.x, r5, r2 ; transform the light1 vector with U, V, W\n"\
|
||||
"dp3 r8.y, r6, r2 \n"\
|
||||
"dp3 r8.z, r7, r2 \n"\
|
||||
"dp3 r9.x, r5, r3 ; transform the light2 vector with U, V, W\n"\
|
||||
"dp3 r9.y, r6, r3 \n"\
|
||||
"dp3 r9.z, r7, r3 \n"\
|
||||
"dp3 r10.x, r5, r1 ; transform the eye vector with U, V, W\n"\
|
||||
"dp3 r10.y, r6, r1 \n"\
|
||||
"dp3 r10.z, r7, r1 \n"\
|
||||
"\n"\
|
||||
"dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\
|
||||
"rsq r8.w, r8.w \n"\
|
||||
"mul r8, r8, r8.w \n"\
|
||||
";mul r8, r8, c96 \n"\
|
||||
"dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\
|
||||
"rsq r9.w, r9.w \n"\
|
||||
"mul r9, r9, r9.w \n"\
|
||||
";mul r9, r9, c96 \n"\
|
||||
"dp3 r10.w, r10, r10 ; normalize eye vector (r10)\n"\
|
||||
"rsq r10.w, r10.w \n"\
|
||||
"mul r10, r10, r10.w \n"\
|
||||
"mul r10, r10, c96 \n"\
|
||||
"\n"\
|
||||
"\n"\
|
||||
"mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\
|
||||
"mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\
|
||||
"mad oT4.xyz, r10.xyz, c95, c95 ; move eye vector from -1..1 into 0..1 \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 1 \n"\
|
||||
"dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x² + r2.y² + r2.z² \n"\
|
||||
"mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\
|
||||
"rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 2 \n"\
|
||||
"dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x² + r3.y² + r3.z² \n"\
|
||||
"mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\
|
||||
"rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
"mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\
|
||||
"mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\
|
||||
"mov oD0.a, v2.a ; move out original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader version 1.4
|
||||
const char D3D9_PARALLAX_MAP_PSH[] =
|
||||
";Irrlicht Engine 0.10 D3D9 render path parallax mapping pixel shader \n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";t4: eye vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
" \n"\
|
||||
"ps.1.4 \n"\
|
||||
" \n"\
|
||||
";def c6, 0.02f, 0.02f, 0.02f, 0.0f ; scale factor, now set in callback \n"\
|
||||
"def c5, 0.5f, 0.5f, 0.5f, 0.0f ; for specular division \n"\
|
||||
" \n"\
|
||||
"texld r1, t1 ; sample (normal.x, normal.y, normal.z, height) \n"\
|
||||
"texcrd r4.xyz, t4 ; fetch eye vector \n"\
|
||||
"texcrd r0.xyz, t0 ; color map \n"\
|
||||
" \n"\
|
||||
"; original parallax mapping: \n"\
|
||||
";mul r3, r1_bx2.wwww, c6; ; r3 = (height, height, height) * scale \n"\
|
||||
";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"; modified parallax mapping to reduce swimming effect: \n"\
|
||||
"mul r3, r1_bx2.wwww, r1_bx2.zzzz ; (nh,nh,nh,nh) = (h,h,h,h) * (n.z,n.z,n.z,n.z,) \n"\
|
||||
"mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\
|
||||
"mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"phase \n"\
|
||||
" \n"\
|
||||
"texld r0, r2 ; load diffuse texture with new tex coord \n"\
|
||||
"texld r1, r2 ; sample normal map \n"\
|
||||
"texcrd r2.xyz, t2 ; fetch light vector 1 \n"\
|
||||
"texcrd r3.xyz, t3 ; fetch light vector 2 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r5, r1_bx2, r2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\
|
||||
"mul r5, r5, v0 ; luminance1 * light color 1 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r3, r1_bx2, r3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\
|
||||
"mad r3, r3, v1, r5 ; (luminance2 * light color 2) + luminance1 \n"\
|
||||
" \n"\
|
||||
"mul r0.xyz, r0, r3 ; total luminance * base color \n"\
|
||||
"+mov r0.a, v0.a ; write original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader version 2.0
|
||||
const char D3D9_PARALLAX_MAP_PSH_20[] =
|
||||
";Irrlicht Engine D3D9 render path parallax mapping pixel shader \n"\
|
||||
";Input: \n"\
|
||||
" \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";t4: eye vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
" \n"\
|
||||
"ps.2.0 \n"\
|
||||
" \n"\
|
||||
"dcl_2d s0 ; Declare the s0 register to be the sampler for stage 0 \n"\
|
||||
"dcl t0.xy ; Declare t0 to have 2D texture coordinates from stage 0 \n"\
|
||||
"dcl t1.xy ; Declare t0 to have 2D texture coordinates from stage 0 \n"\
|
||||
"dcl_2d s1 ; Declare the s1 register to be the sampler for stage 1 \n"\
|
||||
" \n"\
|
||||
"dcl t2.xyz ; \n"\
|
||||
"dcl t3.xyz ; \n"\
|
||||
"dcl t4.xyz ; \n"\
|
||||
"dcl v0.xyzw; \n"\
|
||||
"dcl v1.xyzw; \n"\
|
||||
" \n"\
|
||||
"def c0, -1.0f, -1.0f, -1.0f, -1.0f ; for _bx2 emulation \n"\
|
||||
"def c1, 2.0f, 2.0f, 2.0f, 2.0f ; for _bx2 emulation \n"\
|
||||
"mov r11, c1; \n"\
|
||||
" \n"\
|
||||
"texld r1, t1, s1 ; sample (normal.x, normal.y, normal.z, height) \n"\
|
||||
"mov r4.xyz, t4 ; fetch eye vector \n"\
|
||||
"mov r0.xy, t0 ; color map \n"\
|
||||
" \n"\
|
||||
"; original parallax mapping: \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r1.xyz, r1, r11, c0; \n"\
|
||||
" \n"\
|
||||
"mul r3, r1.wwww, c6; ; r3 = (height, height, height) * scale \n"\
|
||||
" \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r4.xyz, r4, r11, c0; \n"\
|
||||
" \n"\
|
||||
"mad r2.xy, r3, r4, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"; modified parallax mapping to avoid swimming: \n"\
|
||||
";mul r3, r1_bx2.wwww, r1_bx2.zzzz ; r3 = (h,h,h,h) * (n.z, n.z, n.z, n.z,) \n"\
|
||||
";mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\
|
||||
";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"texld r0, r2, s0 ; load diffuse texture with new tex coord \n"\
|
||||
"texld r1, r2, s1 ; sample normal map \n"\
|
||||
"mov r2.xyz, t2 ; fetch light vector 1 \n"\
|
||||
"mov r3.xyz, t3 ; fetch light vector 2 \n"\
|
||||
" \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r1.xyz, r1, r11, c0; \n"\
|
||||
"mad r2.xyz, r2, r11, c0; \n"\
|
||||
"mad r3.xyz, r3, r11, c0; \n"\
|
||||
" \n"\
|
||||
"dp3_sat r2, r1, r2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\
|
||||
"mul r2, r2, v0 ; luminance1 * light color 1 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r3, r1, r3 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\
|
||||
"mad r3, r3, v1, r2 ; (luminance2 * light color 2) + luminance1 \n"\
|
||||
" \n"\
|
||||
"mul r0.xyz, r0, r3 ; total luminance * base color \n"\
|
||||
"mov r0.a, v0.a ; write original alpha value \n"\
|
||||
"mov oC0, r0; \n"\
|
||||
"\n";
|
||||
|
||||
CD3D9ParallaxMapRenderer::CD3D9ParallaxMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial),
|
||||
CurrentScale(0.0f)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ParallaxMapRenderer");
|
||||
#endif
|
||||
|
||||
// set this as callback. We could have done this in
|
||||
// the initialization list, but some compilers don't like it.
|
||||
|
||||
CallBack = this;
|
||||
|
||||
// basicly, this thing simply compiles these hardcoded shaders if the
|
||||
// hardware is able to do them, otherwise it maps to the base material
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) ||
|
||||
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
{
|
||||
// this hardware is not able to do shaders. Fall back to
|
||||
// base material.
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if already compiled parallax map shaders are there.
|
||||
|
||||
video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_PARALLAX_MAP_SOLID);
|
||||
if (renderer)
|
||||
{
|
||||
// use the already compiled shaders
|
||||
video::CD3D9ParallaxMapRenderer* nmr = (video::CD3D9ParallaxMapRenderer*)renderer;
|
||||
VertexShader = nmr->VertexShader;
|
||||
if (VertexShader)
|
||||
VertexShader->AddRef();
|
||||
|
||||
PixelShader = nmr->PixelShader;
|
||||
if (PixelShader)
|
||||
PixelShader->AddRef();
|
||||
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SHADER_EXTERNAL_DEBUG
|
||||
|
||||
// quickly load shader from external file
|
||||
io::CReadFile* file = new io::CReadFile("parallax.psh");
|
||||
s32 sz = file->getSize();
|
||||
char* s = new char[sz+1];
|
||||
file->read(s, sz);
|
||||
s[sz] = 0;
|
||||
|
||||
init(outMaterialTypeNr, D3D9_PARALLAX_MAP_VSH, s);
|
||||
|
||||
delete [] s;
|
||||
file->drop();
|
||||
|
||||
#else
|
||||
|
||||
// compile shaders on our own
|
||||
init(outMaterialTypeNr, D3D9_PARALLAX_MAP_VSH, D3D9_PARALLAX_MAP_PSH);
|
||||
|
||||
#endif // SHADER_EXTERNAL_DEBUG
|
||||
}
|
||||
// something failed, use base material
|
||||
if (-1==outMaterialTypeNr)
|
||||
driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
CD3D9ParallaxMapRenderer::~CD3D9ParallaxMapRenderer()
|
||||
{
|
||||
if (CallBack == this)
|
||||
CallBack = 0;
|
||||
}
|
||||
|
||||
bool CD3D9ParallaxMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (vtxtype != video::EVT_TANGENTS)
|
||||
{
|
||||
os::Printer::log("Error: Parallax map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ParallaxMapRenderer::OnSetMaterial(const video::SMaterial& material,
|
||||
const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services)
|
||||
{
|
||||
CD3D9ShaderMaterialRenderer::OnSetMaterial(material, lastMaterial,
|
||||
resetAllRenderstates, services);
|
||||
|
||||
CurrentScale = material.MaterialTypeParam;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
s32 CD3D9ParallaxMapRenderer::getRenderCapability() const
|
||||
{
|
||||
if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) &&
|
||||
Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants
|
||||
//! for an material renderer should be set.
|
||||
void CD3D9ParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
|
||||
{
|
||||
video::IVideoDriver* driver = services->getVideoDriver();
|
||||
|
||||
// set transposed world matrix
|
||||
services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
|
||||
|
||||
// set eye position
|
||||
|
||||
// The viewpoint is at (0., 0., 0.) in eye space.
|
||||
// Turning this into a vector [0 0 0 1] and multiply it by
|
||||
// the inverse of the view matrix, the resulting vector is the
|
||||
// object space location of the camera.
|
||||
|
||||
f32 floats[4] = {0,0,0,1};
|
||||
core::matrix4 minv = driver->getTransform(video::ETS_VIEW);
|
||||
minv.makeInverse();
|
||||
minv.multiplyWith1x4Matrix(floats);
|
||||
services->setVertexShaderConstant(floats, 4, 1);
|
||||
|
||||
// set transposed worldViewProj matrix
|
||||
core::matrix4 worldViewProj;
|
||||
worldViewProj = driver->getTransform(video::ETS_PROJECTION);
|
||||
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||
services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
|
||||
|
||||
// here we've got to fetch the fixed function lights from the
|
||||
// driver and set them as constants
|
||||
|
||||
const u32 cnt = driver->getDynamicLightCount();
|
||||
|
||||
for (u32 i=0; i<2; ++i)
|
||||
{
|
||||
SLight light;
|
||||
|
||||
if (i<cnt)
|
||||
light = driver->getDynamicLight(i);
|
||||
else
|
||||
{
|
||||
light.DiffuseColor.set(0,0,0); // make light dark
|
||||
light.Radius = 1.0f;
|
||||
}
|
||||
|
||||
light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
|
||||
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
|
||||
}
|
||||
|
||||
// this is not really necessary in d3d9 (used a def instruction), but to be sure:
|
||||
f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
|
||||
services->setVertexShaderConstant(c95, 95, 1);
|
||||
f32 c96[] = {-1, 1, 1, 1};
|
||||
services->setVertexShaderConstant(c96, 96, 1);
|
||||
|
||||
// set scale factor
|
||||
f32 factor = 0.02f; // default value
|
||||
if (CurrentScale != 0)
|
||||
factor = CurrentScale;
|
||||
|
||||
f32 c6[] = {factor, factor, factor, 0};
|
||||
services->setPixelShaderConstant(c6, 6, 1);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Renderer for normal maps using parallax mapping
|
||||
class CD3D9ParallaxMapRenderer :
|
||||
public CD3D9ShaderMaterialRenderer, IShaderConstantSetCallBack
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9ParallaxMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
|
||||
|
||||
~CD3D9ParallaxMapRenderer();
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants for an
|
||||
//! material renderer should be set.
|
||||
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData);
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
virtual s32 getRenderCapability() const;
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material) { }
|
||||
virtual void OnSetMaterial(const video::SMaterial& material,
|
||||
const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services);
|
||||
|
||||
private:
|
||||
|
||||
f32 CurrentScale;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,541 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#define _IRR_D3D_NO_SHADER_DEBUGGING 1
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
#ifndef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Public constructor
|
||||
CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData)
|
||||
: pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
|
||||
VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ShaderMaterialRenderer");
|
||||
#endif
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->grab();
|
||||
|
||||
if (CallBack)
|
||||
CallBack->grab();
|
||||
|
||||
init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram);
|
||||
}
|
||||
|
||||
|
||||
//! constructor only for use by derived classes who want to
|
||||
//! create a fall back material for example.
|
||||
CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial, s32 userData)
|
||||
: pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
|
||||
VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ShaderMaterialRenderer");
|
||||
#endif
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->grab();
|
||||
|
||||
if (CallBack)
|
||||
CallBack->grab();
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::init(s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram, const c8* pixelShaderProgram)
|
||||
{
|
||||
outMaterialTypeNr = -1;
|
||||
|
||||
// create vertex shader
|
||||
if (!createVertexShader(vertexShaderProgram))
|
||||
return;
|
||||
|
||||
// create pixel shader
|
||||
if (!createPixelShader(pixelShaderProgram))
|
||||
return;
|
||||
|
||||
// register myself as new material
|
||||
outMaterialTypeNr = Driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
//! Destructor
|
||||
CD3D9ShaderMaterialRenderer::~CD3D9ShaderMaterialRenderer()
|
||||
{
|
||||
if (CallBack)
|
||||
CallBack->drop();
|
||||
|
||||
if (VertexShader)
|
||||
VertexShader->Release();
|
||||
|
||||
if (PixelShader)
|
||||
PixelShader->Release();
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->drop();
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
// call callback to set shader constants
|
||||
if (CallBack && (VertexShader || PixelShader))
|
||||
CallBack->OnSetConstants(service, UserData);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services)
|
||||
{
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
if (VertexShader)
|
||||
{
|
||||
// save old vertex shader
|
||||
pID3DDevice->GetVertexShader(&OldVertexShader);
|
||||
|
||||
// set new vertex shader
|
||||
if (FAILED(pID3DDevice->SetVertexShader(VertexShader)))
|
||||
os::Printer::log("Could not set vertex shader.", ELL_WARNING);
|
||||
}
|
||||
|
||||
// set new pixel shader
|
||||
if (PixelShader)
|
||||
{
|
||||
if (FAILED(pID3DDevice->SetPixelShader(PixelShader)))
|
||||
os::Printer::log("Could not set pixel shader.", ELL_WARNING);
|
||||
}
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnSetMaterial(material, material, true, services);
|
||||
}
|
||||
|
||||
//let callback know used material
|
||||
if (CallBack)
|
||||
CallBack->OnSetMaterial(material);
|
||||
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::OnUnsetMaterial()
|
||||
{
|
||||
if (VertexShader)
|
||||
pID3DDevice->SetVertexShader(OldVertexShader);
|
||||
|
||||
if (PixelShader)
|
||||
pID3DDevice->SetPixelShader(0);
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnUnsetMaterial();
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
bool CD3D9ShaderMaterialRenderer::isTransparent() const
|
||||
{
|
||||
return BaseMaterial ? BaseMaterial->isTransparent() : false;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::createPixelShader(const c8* pxsh)
|
||||
{
|
||||
if (!pxsh)
|
||||
return true;
|
||||
|
||||
// compile shader
|
||||
|
||||
LPD3DXBUFFER code = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile shader without debug info
|
||||
stubD3DXAssembleShader(pxsh, (UINT)strlen(pxsh), 0, 0, 0, &code, &errors);
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_file_nr = 0;
|
||||
++irr_dbg_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_shader_%d.psh", irr_dbg_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(pxsh, strlen(pxsh), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (errors)
|
||||
{
|
||||
// print out compilation errors.
|
||||
os::Printer::log("Pixel shader compilation failed:", ELL_ERROR);
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
|
||||
if (code)
|
||||
code->Release();
|
||||
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)code->GetBufferPointer(), &PixelShader)))
|
||||
{
|
||||
os::Printer::log("Could not create pixel shader.", ELL_ERROR);
|
||||
code->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
code->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::createVertexShader(const char* vtxsh)
|
||||
{
|
||||
if (!vtxsh)
|
||||
return true;
|
||||
|
||||
// compile shader
|
||||
|
||||
LPD3DXBUFFER code = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile shader without debug info
|
||||
stubD3DXAssembleShader(vtxsh, (UINT)strlen(vtxsh), 0, 0, 0, &code, &errors);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_file_nr = 0;
|
||||
++irr_dbg_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_shader_%d.vsh", irr_dbg_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(vtxsh, strlen(vtxsh), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors);
|
||||
|
||||
#endif
|
||||
|
||||
if (errors)
|
||||
{
|
||||
// print out compilation errors.
|
||||
os::Printer::log("Vertex shader compilation failed:", ELL_ERROR);
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
|
||||
if (code)
|
||||
code->Release();
|
||||
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!code || FAILED(pID3DDevice->CreateVertexShader((DWORD*)code->GetBufferPointer(), &VertexShader)))
|
||||
{
|
||||
os::Printer::log("Could not create vertex shader.", ELL_ERROR);
|
||||
if (code)
|
||||
code->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
code->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader(LPCSTR pSrcData,
|
||||
UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs)
|
||||
{
|
||||
// Because Irrlicht needs to be able to start up even without installed d3d dlls, it
|
||||
// needs to load external d3d dlls manually. examples for the dlls are:
|
||||
// SDK dll name D3DX_SDK_VERSION
|
||||
// Summer 2004: no dll 22
|
||||
// February 2005: d3dx9_24.dll 24
|
||||
// April 2005: d3dx9_25.dll 25
|
||||
// June 2005: d3dx9_26.dll 26
|
||||
// August 2005: d3dx9_27.dll 27
|
||||
// October 2005,
|
||||
// December 2005: d3dx9_28.dll 28
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXAssembleShader(pSrcData, SrcDataLen, pDefines, pInclude,
|
||||
Flags, ppShader, ppErrorMsgs);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXAssembleShader signature
|
||||
typedef HRESULT (WINAPI *AssembleShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude,
|
||||
DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static AssembleShaderFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibraryA(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (AssembleShaderFunction)GetProcAddress(hMod, "D3DXAssembleShader");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXAssembleShader from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, Flags, ppShader, ppErrorMsgs);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXAssembleShaderFromFileA(pSrcFile, pDefines, pInclude, Flags,
|
||||
ppShader, ppErrorMsgs);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXAssembleShaderFromFileA signature
|
||||
typedef HRESULT (WINAPI *AssembleShaderFromFileFunction)(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static AssembleShaderFromFileFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibraryA(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (AssembleShaderFromFileFunction)GetProcAddress(hMod, "D3DXAssembleShaderFromFileA");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXAssembleShaderFromFileA from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcFile, pDefines, pInclude, Flags, ppShader, ppErrorMsgs);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXCompileShader(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXCompileShader
|
||||
typedef HRESULT (WINAPI *D3DXCompileShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static D3DXCompileShaderFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibraryA(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (D3DXCompileShaderFunction)GetProcAddress(hMod, "D3DXCompileShader");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXCompileShader from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXCompileShaderFromFileA(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXCompileShaderFromFileA
|
||||
typedef HRESULT (WINAPI *D3DXCompileShaderFromFileFunction)(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static D3DXCompileShaderFromFileFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibraryA(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (D3DXCompileShaderFromFileFunction)GetProcAddress(hMod, "D3DXCompileShaderFromFileA");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXCompileShaderFromFileA from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_SHADER_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_SHADER_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3dx9shader.h>
|
||||
|
||||
#include "IMaterialRenderer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class IVideoDriver;
|
||||
class IShaderConstantSetCallBack;
|
||||
class IMaterialRenderer;
|
||||
|
||||
//! Class for using vertex and pixel shaders with D3D9
|
||||
class CD3D9ShaderMaterialRenderer : public IMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Public constructor
|
||||
CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData);
|
||||
|
||||
//! Destructor
|
||||
~CD3D9ShaderMaterialRenderer();
|
||||
|
||||
virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services);
|
||||
|
||||
virtual void OnUnsetMaterial();
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
//! Returns if the material is transparent.
|
||||
virtual bool isTransparent() const;
|
||||
|
||||
protected:
|
||||
|
||||
//! constructor only for use by derived classes who want to
|
||||
//! create a fall back material for example.
|
||||
CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData=0);
|
||||
|
||||
void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram);
|
||||
bool createPixelShader(const c8* pxsh);
|
||||
bool createVertexShader(const char* vtxsh);
|
||||
|
||||
HRESULT stubD3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude,
|
||||
DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
HRESULT stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
HRESULT stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
HRESULT stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
video::IVideoDriver* Driver;
|
||||
IShaderConstantSetCallBack* CallBack;
|
||||
IMaterialRenderer* BaseMaterial;
|
||||
|
||||
IDirect3DVertexShader9* VertexShader;
|
||||
IDirect3DVertexShader9* OldVertexShader;
|
||||
IDirect3DPixelShader9* PixelShader;
|
||||
s32 UserData;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,699 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE
|
||||
#include "CD3D9Texture.h"
|
||||
#include "CD3D9Driver.h"
|
||||
#include "os.h"
|
||||
|
||||
#include <d3dx9tex.h>
|
||||
|
||||
#ifndef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
// The D3DXFilterTexture function seems to get linked wrong when
|
||||
// compiling with both D3D8 and 9, causing it not to work in the D3D9 device.
|
||||
// So mipmapgeneration is replaced with my own bad generation in d3d 8 when
|
||||
// compiling with both D3D 8 and 9.
|
||||
// #define _IRR_USE_D3DXFilterTexture_
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
||||
#ifdef _IRR_USE_D3DXFilterTexture_
|
||||
#pragma comment(lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! rendertarget constructor
|
||||
CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size,
|
||||
const io::path& name, const ECOLOR_FORMAT format)
|
||||
: ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0),
|
||||
TextureSize(size), ImageSize(size), Pitch(0), ColorFormat(ECF_UNKNOWN),
|
||||
HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(true)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9Texture");
|
||||
#endif
|
||||
|
||||
Device=driver->getExposedVideoData().D3D9.D3DDev9;
|
||||
if (Device)
|
||||
Device->AddRef();
|
||||
|
||||
createRenderTarget(format);
|
||||
}
|
||||
|
||||
|
||||
//! constructor
|
||||
CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver,
|
||||
u32 flags, const io::path& name, void* mipmapData)
|
||||
: ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0),
|
||||
TextureSize(0,0), ImageSize(0,0), Pitch(0), ColorFormat(ECF_UNKNOWN),
|
||||
HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9Texture");
|
||||
#endif
|
||||
|
||||
HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
|
||||
Device=driver->getExposedVideoData().D3D9.D3DDev9;
|
||||
if (Device)
|
||||
Device->AddRef();
|
||||
|
||||
if (image)
|
||||
{
|
||||
if (createTexture(flags, image))
|
||||
{
|
||||
if (copyTexture(image))
|
||||
{
|
||||
regenerateMipMapLevels(mipmapData);
|
||||
}
|
||||
}
|
||||
else
|
||||
os::Printer::log("Could not create DIRECT3D9 Texture.", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CD3D9Texture::~CD3D9Texture()
|
||||
{
|
||||
if (Texture)
|
||||
Texture->Release();
|
||||
|
||||
if (RTTSurface)
|
||||
RTTSurface->Release();
|
||||
|
||||
// if this texture was the last one using the depth buffer
|
||||
// we can release the surface. We only use the value of the pointer
|
||||
// hence it is safe to use the dropped pointer...
|
||||
if (DepthSurface)
|
||||
{
|
||||
if (DepthSurface->drop())
|
||||
Driver->removeDepthSurface(DepthSurface);
|
||||
}
|
||||
|
||||
if (Device)
|
||||
Device->Release();
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::createRenderTarget(const ECOLOR_FORMAT format)
|
||||
{
|
||||
// are texture size restrictions there ?
|
||||
if(!Driver->queryFeature(EVDF_TEXTURE_NPOT))
|
||||
{
|
||||
if (TextureSize != ImageSize)
|
||||
os::Printer::log("RenderTarget size has to be a power of two", ELL_INFORMATION);
|
||||
}
|
||||
TextureSize = TextureSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
|
||||
|
||||
D3DFORMAT d3dformat = Driver->getD3DColorFormat();
|
||||
|
||||
if(ColorFormat == ECF_UNKNOWN)
|
||||
{
|
||||
// get irrlicht format from backbuffer
|
||||
// (This will get overwritten by the custom format if it is provided, else kept.)
|
||||
ColorFormat = Driver->getColorFormat();
|
||||
setPitch(d3dformat);
|
||||
|
||||
// Use color format if provided.
|
||||
if(format != ECF_UNKNOWN)
|
||||
{
|
||||
ColorFormat = format;
|
||||
d3dformat = Driver->getD3DFormatFromColorFormat(format);
|
||||
setPitch(d3dformat); // This will likely set pitch to 0 for now.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
d3dformat = Driver->getD3DFormatFromColorFormat(ColorFormat);
|
||||
}
|
||||
|
||||
// create texture
|
||||
HRESULT hr;
|
||||
|
||||
hr = Device->CreateTexture(
|
||||
TextureSize.Width,
|
||||
TextureSize.Height,
|
||||
1, // mip map level count, we don't want mipmaps here
|
||||
D3DUSAGE_RENDERTARGET,
|
||||
d3dformat,
|
||||
D3DPOOL_DEFAULT,
|
||||
&Texture,
|
||||
NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (D3DERR_INVALIDCALL == hr)
|
||||
os::Printer::log("Could not create render target texture", "Invalid Call");
|
||||
else
|
||||
if (D3DERR_OUTOFVIDEOMEMORY == hr)
|
||||
os::Printer::log("Could not create render target texture", "Out of Video Memory");
|
||||
else
|
||||
if (E_OUTOFMEMORY == hr)
|
||||
os::Printer::log("Could not create render target texture", "Out of Memory");
|
||||
else
|
||||
os::Printer::log("Could not create render target texture");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9Texture::createMipMaps(u32 level)
|
||||
{
|
||||
if (level==0)
|
||||
return true;
|
||||
|
||||
if (HardwareMipMaps && Texture)
|
||||
{
|
||||
// generate mipmaps in hardware
|
||||
Texture->GenerateMipSubLevels();
|
||||
return true;
|
||||
}
|
||||
|
||||
// manual mipmap generation
|
||||
IDirect3DSurface9* upperSurface = 0;
|
||||
IDirect3DSurface9* lowerSurface = 0;
|
||||
|
||||
// get upper level
|
||||
HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface);
|
||||
if (FAILED(hr) || !upperSurface)
|
||||
{
|
||||
os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get lower level
|
||||
hr = Texture->GetSurfaceLevel(level, &lowerSurface);
|
||||
if (FAILED(hr) || !lowerSurface)
|
||||
{
|
||||
os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING);
|
||||
upperSurface->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DSURFACE_DESC upperDesc, lowerDesc;
|
||||
upperSurface->GetDesc(&upperDesc);
|
||||
lowerSurface->GetDesc(&lowerDesc);
|
||||
|
||||
D3DLOCKED_RECT upperlr;
|
||||
D3DLOCKED_RECT lowerlr;
|
||||
|
||||
// lock upper surface
|
||||
if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0)))
|
||||
{
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
// lock lower surface
|
||||
if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0)))
|
||||
{
|
||||
upperSurface->UnlockRect();
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (upperDesc.Format != lowerDesc.Format)
|
||||
{
|
||||
os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((upperDesc.Format == D3DFMT_A1R5G5B5) || (upperDesc.Format == D3DFMT_R5G6B5))
|
||||
copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
|
||||
lowerDesc.Width, lowerDesc.Height,
|
||||
upperlr.Pitch, lowerlr.Pitch);
|
||||
else
|
||||
if (upperDesc.Format == D3DFMT_A8R8G8B8)
|
||||
copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
|
||||
lowerDesc.Width, lowerDesc.Height,
|
||||
upperlr.Pitch, lowerlr.Pitch);
|
||||
else
|
||||
os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING);
|
||||
}
|
||||
|
||||
bool result=true;
|
||||
// unlock
|
||||
if (FAILED(upperSurface->UnlockRect()))
|
||||
result=false;
|
||||
if (FAILED(lowerSurface->UnlockRect()))
|
||||
result=false;
|
||||
|
||||
// release
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
|
||||
if (!result || (upperDesc.Width <= 3 && upperDesc.Height <= 3))
|
||||
return result; // stop generating levels
|
||||
|
||||
// generate next level
|
||||
return createMipMaps(level+1);
|
||||
}
|
||||
|
||||
|
||||
//! creates the hardware texture
|
||||
bool CD3D9Texture::createTexture(u32 flags, IImage * image)
|
||||
{
|
||||
ImageSize = image->getDimension();
|
||||
|
||||
core::dimension2d<u32> optSize = ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
|
||||
|
||||
D3DFORMAT format = D3DFMT_A1R5G5B5;
|
||||
|
||||
switch(getTextureFormatFromFlags(flags))
|
||||
{
|
||||
case ETCF_ALWAYS_16_BIT:
|
||||
format = D3DFMT_A1R5G5B5; break;
|
||||
case ETCF_ALWAYS_32_BIT:
|
||||
format = D3DFMT_A8R8G8B8; break;
|
||||
case ETCF_OPTIMIZED_FOR_QUALITY:
|
||||
{
|
||||
switch(image->getColorFormat())
|
||||
{
|
||||
case ECF_R8G8B8:
|
||||
case ECF_A8R8G8B8:
|
||||
format = D3DFMT_A8R8G8B8; break;
|
||||
case ECF_A1R5G5B5:
|
||||
case ECF_R5G6B5:
|
||||
format = D3DFMT_A1R5G5B5; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETCF_OPTIMIZED_FOR_SPEED:
|
||||
format = D3DFMT_A1R5G5B5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (Driver->getTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL))
|
||||
{
|
||||
if (format == D3DFMT_A8R8G8B8)
|
||||
format = D3DFMT_R8G8B8;
|
||||
else if (format == D3DFMT_A1R5G5B5)
|
||||
format = D3DFMT_R5G6B5;
|
||||
}
|
||||
|
||||
const bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
|
||||
DWORD usage = 0;
|
||||
|
||||
// This enables hardware mip map generation.
|
||||
if (mipmaps && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
|
||||
{
|
||||
LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9;
|
||||
D3DDISPLAYMODE d3ddm;
|
||||
intf->GetAdapterDisplayMode(Driver->Params.DisplayAdapter, &d3ddm);
|
||||
|
||||
if (D3D_OK==intf->CheckDeviceFormat(Driver->Params.DisplayAdapter,D3DDEVTYPE_HAL,d3ddm.Format,D3DUSAGE_AUTOGENMIPMAP,D3DRTYPE_TEXTURE,format))
|
||||
{
|
||||
usage = D3DUSAGE_AUTOGENMIPMAP;
|
||||
HardwareMipMaps = true;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hr = Device->CreateTexture(optSize.Width, optSize.Height,
|
||||
mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
|
||||
usage, // usage
|
||||
format, D3DPOOL_MANAGED , &Texture, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// try brute force 16 bit
|
||||
HardwareMipMaps = false;
|
||||
if (format == D3DFMT_A8R8G8B8)
|
||||
format = D3DFMT_A1R5G5B5;
|
||||
else if (format == D3DFMT_R8G8B8)
|
||||
format = D3DFMT_R5G6B5;
|
||||
else
|
||||
return false;
|
||||
|
||||
hr = Device->CreateTexture(optSize.Width, optSize.Height,
|
||||
mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
|
||||
0, format, D3DPOOL_MANAGED, &Texture, NULL);
|
||||
}
|
||||
|
||||
ColorFormat = Driver->getColorFormatFromD3DFormat(format);
|
||||
setPitch(format);
|
||||
return (SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
|
||||
//! copies the image to the texture
|
||||
bool CD3D9Texture::copyTexture(IImage * image)
|
||||
{
|
||||
if (Texture && image)
|
||||
{
|
||||
D3DSURFACE_DESC desc;
|
||||
Texture->GetLevelDesc(0, &desc);
|
||||
|
||||
TextureSize.Width = desc.Width;
|
||||
TextureSize.Height = desc.Height;
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
HRESULT hr = Texture->LockRect(0, &rect, 0, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Texture data not copied", "Could not LockRect D3D9 Texture.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
Pitch = rect.Pitch;
|
||||
image->copyToScaling(rect.pBits, TextureSize.Width, TextureSize.Height, ColorFormat, Pitch);
|
||||
|
||||
hr = Texture->UnlockRect(0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Texture data not copied", "Could not UnlockRect D3D9 Texture.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! lock function
|
||||
void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
|
||||
{
|
||||
if (!Texture)
|
||||
return 0;
|
||||
|
||||
MipLevelLocked=mipmapLevel;
|
||||
HRESULT hr;
|
||||
D3DLOCKED_RECT rect;
|
||||
if(!IsRenderTarget)
|
||||
{
|
||||
hr = Texture->LockRect(mipmapLevel, &rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!RTTSurface)
|
||||
{
|
||||
// Make RTT surface large enough for all miplevels (including 0)
|
||||
D3DSURFACE_DESC desc;
|
||||
Texture->GetLevelDesc(0, &desc);
|
||||
hr = Device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &RTTSurface, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Offscreen surface creation failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *surface = 0;
|
||||
hr = Texture->GetSurfaceLevel(mipmapLevel, &surface);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
hr = Device->GetRenderTargetData(surface, RTTSurface);
|
||||
surface->Release();
|
||||
if(FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
hr = RTTSurface->LockRect(&rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return rect.pBits;
|
||||
}
|
||||
|
||||
|
||||
//! unlock function
|
||||
void CD3D9Texture::unlock()
|
||||
{
|
||||
if (!Texture)
|
||||
return;
|
||||
|
||||
if (!IsRenderTarget)
|
||||
Texture->UnlockRect(MipLevelLocked);
|
||||
else if (RTTSurface)
|
||||
RTTSurface->UnlockRect();
|
||||
}
|
||||
|
||||
|
||||
//! Returns original size of the texture.
|
||||
const core::dimension2d<u32>& CD3D9Texture::getOriginalSize() const
|
||||
{
|
||||
return ImageSize;
|
||||
}
|
||||
|
||||
|
||||
//! Returns (=size) of the texture.
|
||||
const core::dimension2d<u32>& CD3D9Texture::getSize() const
|
||||
{
|
||||
return TextureSize;
|
||||
}
|
||||
|
||||
|
||||
//! returns driver type of texture (=the driver, who created the texture)
|
||||
E_DRIVER_TYPE CD3D9Texture::getDriverType() const
|
||||
{
|
||||
return EDT_DIRECT3D9;
|
||||
}
|
||||
|
||||
|
||||
//! returns color format of texture
|
||||
ECOLOR_FORMAT CD3D9Texture::getColorFormat() const
|
||||
{
|
||||
return ColorFormat;
|
||||
}
|
||||
|
||||
|
||||
//! returns pitch of texture (in bytes)
|
||||
u32 CD3D9Texture::getPitch() const
|
||||
{
|
||||
return Pitch;
|
||||
}
|
||||
|
||||
|
||||
//! returns the DIRECT3D9 Texture
|
||||
IDirect3DBaseTexture9* CD3D9Texture::getDX9Texture() const
|
||||
{
|
||||
return Texture;
|
||||
}
|
||||
|
||||
|
||||
//! returns if texture has mipmap levels
|
||||
bool CD3D9Texture::hasMipMaps() const
|
||||
{
|
||||
return HasMipMaps;
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::copy16BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height,
|
||||
s32 pitchsrc, s32 pitchtgt) const
|
||||
{
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
u32 a=0, r=0, g=0, b=0;
|
||||
|
||||
for (s32 dy=0; dy<2; ++dy)
|
||||
{
|
||||
const s32 tgy = (y*2)+dy;
|
||||
for (s32 dx=0; dx<2; ++dx)
|
||||
{
|
||||
const s32 tgx = (x*2)+dx;
|
||||
|
||||
SColor c;
|
||||
if (ColorFormat == ECF_A1R5G5B5)
|
||||
c = A1R5G5B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
|
||||
else
|
||||
c = R5G6B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
|
||||
|
||||
a += c.getAlpha();
|
||||
r += c.getRed();
|
||||
g += c.getGreen();
|
||||
b += c.getBlue();
|
||||
}
|
||||
}
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
u16 c;
|
||||
if (ColorFormat == ECF_A1R5G5B5)
|
||||
c = RGBA16(r,g,b,a);
|
||||
else
|
||||
c = A8R8G8B8toR5G6B5(SColor(a,r,g,b).color);
|
||||
*(u16*)(&tgt[(x*2)+(y*pitchtgt)]) = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height,
|
||||
s32 pitchsrc, s32 pitchtgt) const
|
||||
{
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
u32 a=0, r=0, g=0, b=0;
|
||||
SColor c;
|
||||
|
||||
for (s32 dy=0; dy<2; ++dy)
|
||||
{
|
||||
const s32 tgy = (y*2)+dy;
|
||||
for (s32 dx=0; dx<2; ++dx)
|
||||
{
|
||||
const s32 tgx = (x*2)+dx;
|
||||
|
||||
c = *(u32*)(&src[(tgx*4)+(tgy*pitchsrc)]);
|
||||
|
||||
a += c.getAlpha();
|
||||
r += c.getRed();
|
||||
g += c.getGreen();
|
||||
b += c.getBlue();
|
||||
}
|
||||
}
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
c.set(a, r, g, b);
|
||||
*(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Regenerates the mip map levels of the texture. Useful after locking and
|
||||
//! modifying the texture
|
||||
void CD3D9Texture::regenerateMipMapLevels(void* mipmapData)
|
||||
{
|
||||
if (mipmapData)
|
||||
{
|
||||
core::dimension2du size = TextureSize;
|
||||
u32 level=0;
|
||||
do
|
||||
{
|
||||
if (size.Width>1)
|
||||
size.Width /=2;
|
||||
if (size.Height>1)
|
||||
size.Height /=2;
|
||||
++level;
|
||||
IDirect3DSurface9* mipSurface = 0;
|
||||
HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface);
|
||||
if (FAILED(hr) || !mipSurface)
|
||||
{
|
||||
os::Printer::log("Could not get mipmap level", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
D3DSURFACE_DESC mipDesc;
|
||||
mipSurface->GetDesc(&mipDesc);
|
||||
D3DLOCKED_RECT miplr;
|
||||
|
||||
// lock mipmap surface
|
||||
if (FAILED(mipSurface->LockRect(&miplr, NULL, 0)))
|
||||
{
|
||||
mipSurface->Release();
|
||||
os::Printer::log("Could not lock texture", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width);
|
||||
mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width;
|
||||
// unlock
|
||||
mipSurface->UnlockRect();
|
||||
// release
|
||||
mipSurface->Release();
|
||||
} while (size.Width != 1 || size.Height != 1);
|
||||
}
|
||||
else if (HasMipMaps)
|
||||
{
|
||||
// create mip maps.
|
||||
#ifdef _IRR_USE_D3DXFilterTexture_
|
||||
// The D3DXFilterTexture function seems to get linked wrong when
|
||||
// compiling with both D3D8 and 9, causing it not to work in the D3D9 device.
|
||||
// So mipmapgeneration is replaced with my own bad generation
|
||||
HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT, D3DX_DEFAULT);
|
||||
if (FAILED(hr))
|
||||
#endif
|
||||
createMipMaps();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! returns if it is a render target
|
||||
bool CD3D9Texture::isRenderTarget() const
|
||||
{
|
||||
return IsRenderTarget;
|
||||
}
|
||||
|
||||
|
||||
//! Returns pointer to the render target surface
|
||||
IDirect3DSurface9* CD3D9Texture::getRenderTargetSurface()
|
||||
{
|
||||
if (!IsRenderTarget)
|
||||
return 0;
|
||||
|
||||
IDirect3DSurface9 *pRTTSurface = 0;
|
||||
if (Texture)
|
||||
Texture->GetSurfaceLevel(0, &pRTTSurface);
|
||||
|
||||
if (pRTTSurface)
|
||||
pRTTSurface->Release();
|
||||
|
||||
return pRTTSurface;
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::setPitch(D3DFORMAT d3dformat)
|
||||
{
|
||||
switch(d3dformat)
|
||||
{
|
||||
case D3DFMT_X1R5G5B5:
|
||||
case D3DFMT_A1R5G5B5:
|
||||
Pitch = TextureSize.Width * 2;
|
||||
break;
|
||||
case D3DFMT_A8B8G8R8:
|
||||
case D3DFMT_A8R8G8B8:
|
||||
case D3DFMT_X8R8G8B8:
|
||||
Pitch = TextureSize.Width * 4;
|
||||
break;
|
||||
case D3DFMT_R5G6B5:
|
||||
Pitch = TextureSize.Width * 2;
|
||||
break;
|
||||
case D3DFMT_R8G8B8:
|
||||
Pitch = TextureSize.Width * 3;
|
||||
break;
|
||||
default:
|
||||
Pitch = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
@@ -0,0 +1,132 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DIRECTX9_TEXTURE_H_INCLUDED__
|
||||
#define __C_DIRECTX9_TEXTURE_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "ITexture.h"
|
||||
#include "IImage.h"
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CD3D9Driver;
|
||||
// forward declaration for RTT depth buffer handling
|
||||
struct SDepthSurface;
|
||||
/*!
|
||||
interface for a Video Driver dependent Texture.
|
||||
*/
|
||||
class CD3D9Texture : public ITexture
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CD3D9Texture(IImage* image, CD3D9Driver* driver,
|
||||
u32 flags, const io::path& name, void* mipmapData=0);
|
||||
|
||||
//! rendertarget constructor
|
||||
CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, const io::path& name,
|
||||
const ECOLOR_FORMAT format = ECF_UNKNOWN);
|
||||
|
||||
//! destructor
|
||||
virtual ~CD3D9Texture();
|
||||
|
||||
//! lock function
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0);
|
||||
|
||||
//! unlock function
|
||||
virtual void unlock();
|
||||
|
||||
//! Returns original size of the texture.
|
||||
virtual const core::dimension2d<u32>& getOriginalSize() const;
|
||||
|
||||
//! Returns (=size) of the texture.
|
||||
virtual const core::dimension2d<u32>& getSize() const;
|
||||
|
||||
//! returns driver type of texture (=the driver, who created the texture)
|
||||
virtual E_DRIVER_TYPE getDriverType() const;
|
||||
|
||||
//! returns color format of texture
|
||||
virtual ECOLOR_FORMAT getColorFormat() const;
|
||||
|
||||
//! returns pitch of texture (in bytes)
|
||||
virtual u32 getPitch() const;
|
||||
|
||||
//! returns the DIRECT3D9 Texture
|
||||
IDirect3DBaseTexture9* getDX9Texture() const;
|
||||
|
||||
//! returns if texture has mipmap levels
|
||||
bool hasMipMaps() const;
|
||||
|
||||
//! Regenerates the mip map levels of the texture. Useful after locking and
|
||||
//! modifying the texture
|
||||
virtual void regenerateMipMapLevels(void* mipmapData=0);
|
||||
|
||||
//! returns if it is a render target
|
||||
virtual bool isRenderTarget() const;
|
||||
|
||||
//! Returns pointer to the render target surface
|
||||
IDirect3DSurface9* getRenderTargetSurface();
|
||||
|
||||
u64 getTextureHandler() const { return (u64)Texture; }
|
||||
|
||||
private:
|
||||
friend class CD3D9Driver;
|
||||
|
||||
void createRenderTarget(const ECOLOR_FORMAT format = ECF_UNKNOWN);
|
||||
|
||||
//! creates the hardware texture
|
||||
bool createTexture(u32 flags, IImage * image);
|
||||
|
||||
//! copies the image to the texture
|
||||
bool copyTexture(IImage * image);
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
bool createMipMaps(u32 level=1);
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
void copy16BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
void copy32BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
|
||||
|
||||
//! set Pitch based on the d3d format
|
||||
void setPitch(D3DFORMAT d3dformat);
|
||||
|
||||
IDirect3DDevice9* Device;
|
||||
IDirect3DTexture9* Texture;
|
||||
IDirect3DSurface9* RTTSurface;
|
||||
CD3D9Driver* Driver;
|
||||
SDepthSurface* DepthSurface;
|
||||
core::dimension2d<u32> TextureSize;
|
||||
core::dimension2d<u32> ImageSize;
|
||||
s32 Pitch;
|
||||
u32 MipLevelLocked;
|
||||
ECOLOR_FORMAT ColorFormat;
|
||||
|
||||
bool HasMipMaps;
|
||||
bool HardwareMipMaps;
|
||||
bool IsRenderTarget;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#endif // __C_DIRECTX9_TEXTURE_H_INCLUDED__
|
||||
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CDefaultGUIElementFactory.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUICheckBox.h"
|
||||
#include "IGUIColorSelectDialog.h"
|
||||
#include "IGUIComboBox.h"
|
||||
#include "IGUIContextMenu.h"
|
||||
#include "IGUIEditBox.h"
|
||||
#include "IGUIFileOpenDialog.h"
|
||||
#include "IGUIInOutFader.h"
|
||||
#include "IGUIImage.h"
|
||||
#include "IGUIListBox.h"
|
||||
#include "IGUIMeshViewer.h"
|
||||
#include "IGUIScrollBar.h"
|
||||
#include "IGUISpinBox.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "IGUITabControl.h"
|
||||
#include "IGUITable.h"
|
||||
#include "IGUIToolbar.h"
|
||||
#include "IGUIWindow.h"
|
||||
#include "IGUITreeView.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
CDefaultGUIElementFactory::CDefaultGUIElementFactory(IGUIEnvironment* env)
|
||||
: Environment(env)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDefaultGUIElementFactory");
|
||||
#endif
|
||||
|
||||
// don't grab the gui environment here to prevent cyclic references
|
||||
}
|
||||
|
||||
|
||||
//! adds an element to the env based on its type id
|
||||
IGUIElement* CDefaultGUIElementFactory::addGUIElement(EGUI_ELEMENT_TYPE type, IGUIElement* parent)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case EGUIET_BUTTON:
|
||||
return Environment->addButton(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_CHECK_BOX:
|
||||
return Environment->addCheckBox(false, core::rect<s32>(0,0,100,100), parent);
|
||||
case EGUIET_COLOR_SELECT_DIALOG:
|
||||
return Environment->addColorSelectDialog(0,true,parent);
|
||||
case EGUIET_COMBO_BOX:
|
||||
return Environment->addComboBox(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_CONTEXT_MENU:
|
||||
return Environment->addContextMenu(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_MENU:
|
||||
return Environment->addMenu(parent);
|
||||
case EGUIET_EDIT_BOX:
|
||||
return Environment->addEditBox(0,core::rect<s32>(0,0,100,100),true, parent);
|
||||
case EGUIET_FILE_OPEN_DIALOG:
|
||||
return Environment->addFileOpenDialog(0,true,parent);
|
||||
case EGUIET_IMAGE:
|
||||
return Environment->addImage(0,core::position2di(0,0), true, parent);
|
||||
case EGUIET_IN_OUT_FADER:
|
||||
return Environment->addInOutFader(0,parent);
|
||||
case EGUIET_LIST_BOX:
|
||||
return Environment->addListBox(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_MESH_VIEWER:
|
||||
return Environment->addMeshViewer(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_MODAL_SCREEN:
|
||||
return Environment->addModalScreen(parent);
|
||||
case EGUIET_MESSAGE_BOX:
|
||||
return Environment->addMessageBox(0,0,false,0,parent);
|
||||
case EGUIET_SCROLL_BAR:
|
||||
return Environment->addScrollBar(false,core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_STATIC_TEXT:
|
||||
return Environment->addStaticText(L"",core::rect<s32>(0,0,100,100),false,true,parent);
|
||||
case EGUIET_TAB:
|
||||
return Environment->addTab(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_TAB_CONTROL:
|
||||
return Environment->addTabControl(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_TABLE:
|
||||
return Environment->addTable(core::rect<s32>(0,0,100,100), parent);
|
||||
case EGUIET_TOOL_BAR:
|
||||
return Environment->addToolBar(parent);
|
||||
case EGUIET_WINDOW:
|
||||
return Environment->addWindow(core::rect<s32>(0,0,100,100),false,0,parent);
|
||||
case EGUIET_SPIN_BOX:
|
||||
return Environment->addSpinBox(L"0.0", core::rect<s32>(0,0,100,100), true, parent);
|
||||
case EGUIET_TREE_VIEW:
|
||||
return Environment->addTreeView(core::rect<s32>(0,0,100,100),parent);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! adds an element to the environment based on its type name
|
||||
IGUIElement* CDefaultGUIElementFactory::addGUIElement(const c8* typeName, IGUIElement* parent)
|
||||
{
|
||||
return addGUIElement( getTypeFromName(typeName), parent );
|
||||
}
|
||||
|
||||
|
||||
//! Returns the amount of element types this factory is able to create.
|
||||
s32 CDefaultGUIElementFactory::getCreatableGUIElementTypeCount() const
|
||||
{
|
||||
return EGUIET_COUNT;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type of a createable element type.
|
||||
EGUI_ELEMENT_TYPE CDefaultGUIElementFactory::getCreateableGUIElementType(s32 idx) const
|
||||
{
|
||||
if (idx>=0 && idx<EGUIET_COUNT)
|
||||
return (EGUI_ELEMENT_TYPE)idx;
|
||||
|
||||
return EGUIET_ELEMENT;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type name of a createable element type.
|
||||
const c8* CDefaultGUIElementFactory::getCreateableGUIElementTypeName(s32 idx) const
|
||||
{
|
||||
if (idx>=0 && idx<EGUIET_COUNT)
|
||||
return GUIElementTypeNames[idx];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type name of a createable element type.
|
||||
const c8* CDefaultGUIElementFactory::getCreateableGUIElementTypeName(EGUI_ELEMENT_TYPE type) const
|
||||
{
|
||||
// for this factory, type == index
|
||||
|
||||
if (type>=0 && type<EGUIET_COUNT)
|
||||
return GUIElementTypeNames[type];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EGUI_ELEMENT_TYPE CDefaultGUIElementFactory::getTypeFromName(const c8* name) const
|
||||
{
|
||||
for ( u32 i=0; GUIElementTypeNames[i]; ++i)
|
||||
if (!strcmp(name, GUIElementTypeNames[i]) )
|
||||
return (EGUI_ELEMENT_TYPE)i;
|
||||
|
||||
return EGUIET_ELEMENT;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DEFAULT_GUI_ELEMENT_FACTORY_H_INCLUDED__
|
||||
#define __C_DEFAULT_GUI_ELEMENT_FACTORY_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIElementFactory.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class IGUIElement;
|
||||
class IGUIEnvironment;
|
||||
|
||||
//! This interface makes it possible to dynamically create gui elements.
|
||||
class CDefaultGUIElementFactory : public IGUIElementFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CDefaultGUIElementFactory(IGUIEnvironment* env);
|
||||
|
||||
//! Adds an element to the gui environment based on its type id.
|
||||
/** \param type: Type of the element to add.
|
||||
\param parent: Parent scene node of the new element. A value of 0 adds it to the root.
|
||||
\return Returns pointer to the new element or 0 if unsuccessful. */
|
||||
virtual IGUIElement* addGUIElement(EGUI_ELEMENT_TYPE type, IGUIElement* parent=0);
|
||||
|
||||
//! Adds a GUI element to the GUI Environment based on its type name.
|
||||
/** \param typeName: Type name of the element to add. Taken from the GUIElementTypeNames c8* array.
|
||||
\param parent: Parent scene node of the new element. A value of 0 adds it to the root.
|
||||
\return Returns pointer to the new element or 0 if unsuccessful. */
|
||||
virtual IGUIElement* addGUIElement(const c8* typeName, IGUIElement* parent=0);
|
||||
|
||||
//! Returns the amount of GUI element types this factory is able to create.
|
||||
virtual s32 getCreatableGUIElementTypeCount() const;
|
||||
|
||||
//! Returns the type of a createable GUI element type based on the index.
|
||||
/** \param idx: Index of the element type in this factory. The value must be equal or greater than 0
|
||||
and lower than getCreatableGUIElementTypeCount(). */
|
||||
virtual EGUI_ELEMENT_TYPE getCreateableGUIElementType(s32 idx) const;
|
||||
|
||||
//! Returns the type name of a createable GUI element type based on the index.
|
||||
/** \param idx: Index of the element type in this factory. The value must be equal or greater than 0
|
||||
and lower than getCreatableGUIElementTypeCount(). */
|
||||
virtual const c8* getCreateableGUIElementTypeName(s32 idx) const;
|
||||
|
||||
//! Returns the type name of a createable GUI element based on its type.
|
||||
/** \param type: Type of the GUI element.
|
||||
\return: Returns the name of the type if this factory can create it, otherwise it returns 0. */
|
||||
virtual const c8* getCreateableGUIElementTypeName(EGUI_ELEMENT_TYPE type) const;
|
||||
|
||||
private:
|
||||
|
||||
EGUI_ELEMENT_TYPE getTypeFromName(const c8* name) const;
|
||||
|
||||
IGUIEnvironment* Environment;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_DEFAULT_GUI_ELEMENT_FACTORY_H_INCLUDED__
|
||||
@@ -0,0 +1,162 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CDefaultSceneNodeAnimatorFactory.h"
|
||||
#include "CSceneNodeAnimatorCameraFPS.h"
|
||||
#include "CSceneNodeAnimatorCameraMaya.h"
|
||||
#include "ICursorControl.h"
|
||||
#include "ISceneNodeAnimatorCollisionResponse.h"
|
||||
#include "ISceneManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Names for scene node types
|
||||
const c8* const SceneNodeAnimatorTypeNames[] =
|
||||
{
|
||||
"flyCircle",
|
||||
"flyStraight",
|
||||
"followSpline",
|
||||
"rotation",
|
||||
"texture",
|
||||
"deletion",
|
||||
"collisionResponse",
|
||||
"cameraFPS",
|
||||
"cameraMaya",
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
CDefaultSceneNodeAnimatorFactory::CDefaultSceneNodeAnimatorFactory(ISceneManager* mgr, gui::ICursorControl* crs)
|
||||
: Manager(mgr), CursorControl(crs)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDefaultSceneNodeAnimatorFactory");
|
||||
#endif
|
||||
|
||||
// don't grab the scene manager here to prevent cyclic references
|
||||
if (CursorControl)
|
||||
CursorControl->grab();
|
||||
}
|
||||
|
||||
|
||||
CDefaultSceneNodeAnimatorFactory::~CDefaultSceneNodeAnimatorFactory()
|
||||
{
|
||||
if (CursorControl)
|
||||
CursorControl->drop();
|
||||
}
|
||||
|
||||
|
||||
//! creates a scene node animator based on its type id
|
||||
ISceneNodeAnimator* CDefaultSceneNodeAnimatorFactory::createSceneNodeAnimator(ESCENE_NODE_ANIMATOR_TYPE type, ISceneNode* target)
|
||||
{
|
||||
scene::ISceneNodeAnimator* anim = 0;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ESNAT_FLY_CIRCLE:
|
||||
anim = Manager->createFlyCircleAnimator(core::vector3df(0,0,0), 10);
|
||||
break;
|
||||
case ESNAT_FLY_STRAIGHT:
|
||||
anim = Manager->createFlyStraightAnimator(core::vector3df(0,0,0), core::vector3df(100,100,100), 10000, true );
|
||||
break;
|
||||
case ESNAT_FOLLOW_SPLINE:
|
||||
{
|
||||
core::array<core::vector3df> points;
|
||||
points.push_back(core::vector3df(0,0,0));
|
||||
points.push_back(core::vector3df(10,5,10));
|
||||
anim = Manager->createFollowSplineAnimator(0, points);
|
||||
}
|
||||
break;
|
||||
case ESNAT_ROTATION:
|
||||
anim = Manager->createRotationAnimator(core::vector3df(0.3f,0,0));
|
||||
break;
|
||||
case ESNAT_TEXTURE:
|
||||
{
|
||||
core::array<video::ITexture*> textures;
|
||||
anim = Manager->createTextureAnimator(textures, 250);
|
||||
}
|
||||
break;
|
||||
case ESNAT_DELETION:
|
||||
anim = Manager->createDeleteAnimator(5000);
|
||||
break;
|
||||
case ESNAT_COLLISION_RESPONSE:
|
||||
anim = Manager->createCollisionResponseAnimator(0, target);
|
||||
break;
|
||||
case ESNAT_CAMERA_FPS:
|
||||
anim = new CSceneNodeAnimatorCameraFPS(CursorControl);
|
||||
break;
|
||||
case ESNAT_CAMERA_MAYA:
|
||||
anim = new CSceneNodeAnimatorCameraMaya(CursorControl);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (anim && target)
|
||||
target->addAnimator(anim);
|
||||
|
||||
return anim;
|
||||
}
|
||||
|
||||
|
||||
//! creates a scene node animator based on its type name
|
||||
ISceneNodeAnimator* CDefaultSceneNodeAnimatorFactory::createSceneNodeAnimator(const c8* typeName, ISceneNode* target)
|
||||
{
|
||||
return createSceneNodeAnimator( getTypeFromName(typeName), target );
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of scene node animator types this factory is able to create
|
||||
u32 CDefaultSceneNodeAnimatorFactory::getCreatableSceneNodeAnimatorTypeCount() const
|
||||
{
|
||||
return ESNAT_COUNT;
|
||||
}
|
||||
|
||||
|
||||
//! returns type of a createable scene node animator type
|
||||
ESCENE_NODE_ANIMATOR_TYPE CDefaultSceneNodeAnimatorFactory::getCreateableSceneNodeAnimatorType(u32 idx) const
|
||||
{
|
||||
if (idx<ESNAT_COUNT)
|
||||
return (ESCENE_NODE_ANIMATOR_TYPE)idx;
|
||||
else
|
||||
return ESNAT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
//! returns type name of a createable scene node animator type
|
||||
const c8* CDefaultSceneNodeAnimatorFactory::getCreateableSceneNodeAnimatorTypeName(u32 idx) const
|
||||
{
|
||||
if (idx<ESNAT_COUNT)
|
||||
return SceneNodeAnimatorTypeNames[idx];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! returns type name of a createable scene node animator type
|
||||
const c8* CDefaultSceneNodeAnimatorFactory::getCreateableSceneNodeAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const
|
||||
{
|
||||
// for this factory: index == type
|
||||
|
||||
if (type<ESNAT_COUNT)
|
||||
return SceneNodeAnimatorTypeNames[type];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ESCENE_NODE_ANIMATOR_TYPE CDefaultSceneNodeAnimatorFactory::getTypeFromName(const c8* name) const
|
||||
{
|
||||
for ( u32 i=0; SceneNodeAnimatorTypeNames[i]; ++i)
|
||||
if (!strcmp(name, SceneNodeAnimatorTypeNames[i]) )
|
||||
return (ESCENE_NODE_ANIMATOR_TYPE)i;
|
||||
|
||||
return ESNAT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DEFAULT_SCENE_NODE_ANIMATOR_FACTORY_H_INCLUDED__
|
||||
#define __C_DEFAULT_SCENE_NODE_ANIMATOR_FACTORY_H_INCLUDED__
|
||||
|
||||
#include "ISceneNodeAnimatorFactory.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class ICursorControl;
|
||||
}
|
||||
namespace scene
|
||||
{
|
||||
class ISceneNodeAnimator;
|
||||
class ISceneManager;
|
||||
|
||||
//! Interface making it possible to dynamicly create scene nodes animators
|
||||
class CDefaultSceneNodeAnimatorFactory : public ISceneNodeAnimatorFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CDefaultSceneNodeAnimatorFactory(ISceneManager* mgr, gui::ICursorControl* crs);
|
||||
|
||||
virtual ~CDefaultSceneNodeAnimatorFactory();
|
||||
|
||||
//! creates a scene node animator based on its type id
|
||||
/** \param type: Type of the scene node animator to add.
|
||||
\param target: Target scene node of the new animator.
|
||||
\return Returns pointer to the new scene node animator or null if not successful. You need to
|
||||
drop this pointer after calling this, see IReferenceCounted::drop() for details. */
|
||||
virtual ISceneNodeAnimator* createSceneNodeAnimator(ESCENE_NODE_ANIMATOR_TYPE type, ISceneNode* target);
|
||||
|
||||
//! creates a scene node animator based on its type name
|
||||
/** \param typeName: Type of the scene node animator to add.
|
||||
\param target: Target scene node of the new animator.
|
||||
\return Returns pointer to the new scene node animator or null if not successful. You need to
|
||||
drop this pointer after calling this, see IReferenceCounted::drop() for details. */
|
||||
virtual ISceneNodeAnimator* createSceneNodeAnimator(const char* typeName, ISceneNode* target);
|
||||
|
||||
//! returns amount of scene node animator types this factory is able to create
|
||||
virtual u32 getCreatableSceneNodeAnimatorTypeCount() const;
|
||||
|
||||
//! returns type of a createable scene node animator type
|
||||
/** \param idx: Index of scene node animator type in this factory. Must be a value between 0 and
|
||||
getCreatableSceneNodeTypeCount() */
|
||||
virtual ESCENE_NODE_ANIMATOR_TYPE getCreateableSceneNodeAnimatorType(u32 idx) const;
|
||||
|
||||
//! returns type name of a createable scene node animator type
|
||||
/** \param idx: Index of scene node animator type in this factory. Must be a value between 0 and
|
||||
getCreatableSceneNodeAnimatorTypeCount() */
|
||||
virtual const c8* getCreateableSceneNodeAnimatorTypeName(u32 idx) const;
|
||||
|
||||
//! returns type name of a createable scene node animator type
|
||||
/** \param type: Type of scene node animator.
|
||||
\return: Returns name of scene node animator type if this factory can create the type, otherwise 0. */
|
||||
virtual const c8* getCreateableSceneNodeAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const;
|
||||
|
||||
private:
|
||||
|
||||
ESCENE_NODE_ANIMATOR_TYPE getTypeFromName(const c8* name) const;
|
||||
|
||||
ISceneManager* Manager;
|
||||
gui::ICursorControl* CursorControl;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CDefaultSceneNodeFactory.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ITextSceneNode.h"
|
||||
#include "ITerrainSceneNode.h"
|
||||
#include "IDummyTransformationSceneNode.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "IBillboardSceneNode.h"
|
||||
#include "IAnimatedMeshSceneNode.h"
|
||||
#include "IParticleSystemSceneNode.h"
|
||||
#include "ILightSceneNode.h"
|
||||
#include "IMeshSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
|
||||
CDefaultSceneNodeFactory::CDefaultSceneNodeFactory(ISceneManager* mgr)
|
||||
: Manager(mgr)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDefaultSceneNodeFactory");
|
||||
#endif
|
||||
|
||||
// don't grab the scene manager here to prevent cyclic references
|
||||
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CUBE, "cube"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SPHERE, "sphere"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_TEXT, "text"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_WATER_SURFACE, "waterSurface"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_TERRAIN, "terrain"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_BOX, "skyBox"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_DOME, "skyDome"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SHADOW_VOLUME, "shadowVolume"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octree"));
|
||||
// Legacy support
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octTree"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_MESH, "mesh"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_LIGHT, "light"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_EMPTY, "empty"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_DUMMY_TRANSFORMATION, "dummyTransformation"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA, "camera"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_BILLBOARD, "billBoard"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_ANIMATED_MESH, "animatedMesh"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_PARTICLE_SYSTEM, "particleSystem"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_VOLUME_LIGHT, "volumeLight"));
|
||||
// SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_MD3_SCENE_NODE, "md3"));
|
||||
|
||||
// legacy, for version <= 1.4.x irr files
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_MAYA, "cameraMaya"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_FPS, "cameraFPS"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_Q3SHADER_SCENE_NODE, "quake3Shader"));
|
||||
}
|
||||
|
||||
|
||||
//! adds a scene node to the scene graph based on its type id
|
||||
ISceneNode* CDefaultSceneNodeFactory::addSceneNode(ESCENE_NODE_TYPE type, ISceneNode* parent)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ESNT_CUBE:
|
||||
return Manager->addCubeSceneNode(10, parent);
|
||||
case ESNT_SPHERE:
|
||||
return Manager->addSphereSceneNode(5, 16, parent);
|
||||
case ESNT_TEXT:
|
||||
return Manager->addTextSceneNode(0, L"example");
|
||||
case ESNT_WATER_SURFACE:
|
||||
return Manager->addWaterSurfaceSceneNode(0, 2.0f, 300.0f, 10.0f, parent);
|
||||
case ESNT_TERRAIN:
|
||||
return Manager->addTerrainSceneNode("", parent, -1,
|
||||
core::vector3df(0.0f,0.0f,0.0f),
|
||||
core::vector3df(0.0f,0.0f,0.0f),
|
||||
core::vector3df(1.0f,1.0f,1.0f),
|
||||
video::SColor(255,255,255,255),
|
||||
4, ETPS_17, 0, true);
|
||||
case ESNT_SKY_BOX:
|
||||
return Manager->addSkyBoxSceneNode(0,0,0,0,0,0, parent);
|
||||
case ESNT_SHADOW_VOLUME:
|
||||
return 0;
|
||||
case ESNT_OCTREE:
|
||||
return Manager->addOctreeSceneNode((IMesh*)0, parent, -1, 128, true);
|
||||
case ESNT_MESH:
|
||||
return Manager->addMeshSceneNode(0, parent, -1, core::vector3df(),
|
||||
core::vector3df(), core::vector3df(1,1,1), true);
|
||||
case ESNT_LIGHT:
|
||||
return Manager->addLightSceneNode(parent);
|
||||
case ESNT_EMPTY:
|
||||
return Manager->addEmptySceneNode(parent);
|
||||
case ESNT_DUMMY_TRANSFORMATION:
|
||||
return Manager->addDummyTransformationSceneNode(parent);
|
||||
case ESNT_CAMERA:
|
||||
return Manager->addCameraSceneNode(parent);
|
||||
case ESNT_CAMERA_MAYA:
|
||||
return Manager->addCameraSceneNodeMaya(parent);
|
||||
case ESNT_CAMERA_FPS:
|
||||
return Manager->addCameraSceneNodeFPS(parent);
|
||||
case ESNT_BILLBOARD:
|
||||
return Manager->addBillboardSceneNode(parent);
|
||||
case ESNT_ANIMATED_MESH:
|
||||
return Manager->addAnimatedMeshSceneNode(0, parent, -1, core::vector3df(),
|
||||
core::vector3df(), core::vector3df(1,1,1), true);
|
||||
case ESNT_PARTICLE_SYSTEM:
|
||||
return Manager->addParticleSystemSceneNode(true, parent);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! adds a scene node to the scene graph based on its type name
|
||||
ISceneNode* CDefaultSceneNodeFactory::addSceneNode(const c8* typeName, ISceneNode* parent)
|
||||
{
|
||||
return addSceneNode( getTypeFromName(typeName), parent );
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of scene node types this factory is able to create
|
||||
u32 CDefaultSceneNodeFactory::getCreatableSceneNodeTypeCount() const
|
||||
{
|
||||
return SupportedSceneNodeTypes.size();
|
||||
}
|
||||
|
||||
|
||||
//! returns type of a createable scene node type
|
||||
ESCENE_NODE_TYPE CDefaultSceneNodeFactory::getCreateableSceneNodeType(u32 idx) const
|
||||
{
|
||||
if (idx<SupportedSceneNodeTypes.size())
|
||||
return SupportedSceneNodeTypes[idx].Type;
|
||||
else
|
||||
return ESNT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
//! returns type name of a createable scene node type
|
||||
const c8* CDefaultSceneNodeFactory::getCreateableSceneNodeTypeName(u32 idx) const
|
||||
{
|
||||
if (idx<SupportedSceneNodeTypes.size())
|
||||
return SupportedSceneNodeTypes[idx].TypeName.c_str();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! returns type name of a createable scene node type
|
||||
const c8* CDefaultSceneNodeFactory::getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const
|
||||
{
|
||||
for (u32 i=0; i<SupportedSceneNodeTypes.size(); ++i)
|
||||
if (SupportedSceneNodeTypes[i].Type == type)
|
||||
return SupportedSceneNodeTypes[i].TypeName.c_str();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ESCENE_NODE_TYPE CDefaultSceneNodeFactory::getTypeFromName(const c8* name) const
|
||||
{
|
||||
for (u32 i=0; i<SupportedSceneNodeTypes.size(); ++i)
|
||||
if (SupportedSceneNodeTypes[i].TypeName == name)
|
||||
return SupportedSceneNodeTypes[i].Type;
|
||||
|
||||
return ESNT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DEFAULT_SCENE_NODE_FACTORY_H_INCLUDED__
|
||||
#define __C_DEFAULT_SCENE_NODE_FACTORY_H_INCLUDED__
|
||||
|
||||
#include "ISceneNodeFactory.h"
|
||||
#include "irrArray.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class ISceneNode;
|
||||
class ISceneManager;
|
||||
|
||||
//! Interface making it possible to dynamicly create scene nodes and animators
|
||||
class CDefaultSceneNodeFactory : public ISceneNodeFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CDefaultSceneNodeFactory(ISceneManager* mgr);
|
||||
|
||||
//! adds a scene node to the scene graph based on its type id
|
||||
/** \param type: Type of the scene node to add.
|
||||
\param parent: Parent scene node of the new node, can be null to add the scene node to the root.
|
||||
\return Returns pointer to the new scene node or null if not successful. */
|
||||
virtual ISceneNode* addSceneNode(ESCENE_NODE_TYPE type, ISceneNode* parent=0);
|
||||
|
||||
//! adds a scene node to the scene graph based on its type name
|
||||
/** \param typeName: Type name of the scene node to add.
|
||||
\param parent: Parent scene node of the new node, can be null to add the scene node to the root.
|
||||
\return Returns pointer to the new scene node or null if not successful. */
|
||||
virtual ISceneNode* addSceneNode(const c8* typeName, ISceneNode* parent=0);
|
||||
|
||||
//! returns amount of scene node types this factory is able to create
|
||||
virtual u32 getCreatableSceneNodeTypeCount() const;
|
||||
|
||||
//! returns type name of a createable scene node type by index
|
||||
/** \param idx: Index of scene node type in this factory. Must be a value between 0 and
|
||||
uetCreatableSceneNodeTypeCount() */
|
||||
virtual const c8* getCreateableSceneNodeTypeName(u32 idx) const;
|
||||
|
||||
//! returns type of a createable scene node type
|
||||
/** \param idx: Index of scene node type in this factory. Must be a value between 0 and
|
||||
getCreatableSceneNodeTypeCount() */
|
||||
virtual ESCENE_NODE_TYPE getCreateableSceneNodeType(u32 idx) const;
|
||||
|
||||
//! returns type name of a createable scene node type
|
||||
/** \param idx: Type of scene node.
|
||||
\return: Returns name of scene node type if this factory can create the type, otherwise 0. */
|
||||
virtual const c8* getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const;
|
||||
|
||||
private:
|
||||
|
||||
ESCENE_NODE_TYPE getTypeFromName(const c8* name) const;
|
||||
|
||||
struct SSceneNodeTypePair
|
||||
{
|
||||
SSceneNodeTypePair(ESCENE_NODE_TYPE type, const c8* name)
|
||||
: Type(type), TypeName(name)
|
||||
{}
|
||||
|
||||
ESCENE_NODE_TYPE Type;
|
||||
core::stringc TypeName;
|
||||
};
|
||||
|
||||
core::array<SSceneNodeTypePair> SupportedSceneNodeTypes;
|
||||
|
||||
ISceneManager* Manager;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CDummyTransformationSceneNode.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CDummyTransformationSceneNode::CDummyTransformationSceneNode(
|
||||
ISceneNode* parent, ISceneManager* mgr, s32 id)
|
||||
: IDummyTransformationSceneNode(parent, mgr, id)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDummyTransformationSceneNode");
|
||||
#endif
|
||||
|
||||
setAutomaticCulling(scene::EAC_OFF);
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CDummyTransformationSceneNode::getBoundingBox() const
|
||||
{
|
||||
return Box;
|
||||
}
|
||||
|
||||
|
||||
//! Returns a reference to the current relative transformation matrix.
|
||||
//! This is the matrix, this scene node uses instead of scale, translation
|
||||
//! and rotation.
|
||||
core::matrix4& CDummyTransformationSceneNode::getRelativeTransformationMatrix()
|
||||
{
|
||||
return RelativeTransformationMatrix;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the relative transformation of the scene node.
|
||||
core::matrix4 CDummyTransformationSceneNode::getRelativeTransformation() const
|
||||
{
|
||||
return RelativeTransformationMatrix;
|
||||
}
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CDummyTransformationSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CDummyTransformationSceneNode* nb = new CDummyTransformationSceneNode(newParent,
|
||||
newManager, ID);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->RelativeTransformationMatrix = RelativeTransformationMatrix;
|
||||
nb->Box = Box;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
const core::vector3df& CDummyTransformationSceneNode::getScale() const
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::getScale() does not contain the relative transformation.", ELL_DEBUG);
|
||||
return RelativeScale;
|
||||
}
|
||||
|
||||
void CDummyTransformationSceneNode::setScale(const core::vector3df& scale)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setScale() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeScale = scale;
|
||||
}
|
||||
|
||||
const core::vector3df& CDummyTransformationSceneNode::getRotation() const
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::getRotation() does not contain the relative transformation.", ELL_DEBUG);
|
||||
return RelativeRotation;
|
||||
}
|
||||
|
||||
void CDummyTransformationSceneNode::setRotation(const core::vector3df& rotation)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setRotation() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeRotation = rotation;
|
||||
}
|
||||
|
||||
const core::vector3df& CDummyTransformationSceneNode::getPosition() const
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::getPosition() does not contain the relative transformation.", ELL_DEBUG);
|
||||
return RelativeTranslation;
|
||||
}
|
||||
|
||||
void CDummyTransformationSceneNode::setPosition(const core::vector3df& newpos)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setPosition() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeTranslation = newpos;
|
||||
}
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IDummyTransformationSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CDummyTransformationSceneNode : public IDummyTransformationSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CDummyTransformationSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id);
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! Returns a reference to the current relative transformation matrix.
|
||||
//! This is the matrix, this scene node uses instead of scale, translation
|
||||
//! and rotation.
|
||||
virtual core::matrix4& getRelativeTransformationMatrix();
|
||||
|
||||
//! Returns the relative transformation of the scene node.
|
||||
virtual core::matrix4 getRelativeTransformation() const;
|
||||
|
||||
//! does nothing.
|
||||
virtual void render() {}
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_DUMMY_TRANSFORMATION; }
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// TODO: We can add least add some warnings to find troubles faster until we have
|
||||
// fixed bug id 2318691.
|
||||
virtual const core::vector3df& getScale() const;
|
||||
virtual void setScale(const core::vector3df& scale);
|
||||
virtual const core::vector3df& getRotation() const;
|
||||
virtual void setRotation(const core::vector3df& rotation);
|
||||
virtual const core::vector3df& getPosition() const;
|
||||
virtual void setPosition(const core::vector3df& newpos);
|
||||
|
||||
core::matrix4 RelativeTransformationMatrix;
|
||||
core::aabbox3d<f32> Box;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CEmptySceneNode.h"
|
||||
#include "ISceneManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CEmptySceneNode::CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id)
|
||||
: ISceneNode(parent, mgr, id)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CEmptySceneNode");
|
||||
#endif
|
||||
|
||||
setAutomaticCulling(scene::EAC_OFF);
|
||||
}
|
||||
|
||||
|
||||
//! pre render event
|
||||
void CEmptySceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void CEmptySceneNode::render()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CEmptySceneNode::getBoundingBox() const
|
||||
{
|
||||
return Box;
|
||||
}
|
||||
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CEmptySceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CEmptySceneNode* nb = new CEmptySceneNode(newParent,
|
||||
newManager, ID);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->Box = Box;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_EMPTY_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_EMPTY_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "ISceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CEmptySceneNode : public ISceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id);
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! This method is called just before the rendering process of the whole scene.
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! does nothing.
|
||||
virtual void render();
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_EMPTY; }
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
private:
|
||||
|
||||
core::aabbox3d<f32> Box;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CFPSCounter.h"
|
||||
#include "irrMath.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
CFPSCounter::CFPSCounter()
|
||||
: FPS(60), Primitive(0), StartTime(0), FramesCounted(0),
|
||||
PrimitivesCounted(0), PrimitiveAverage(0), PrimitiveTotal(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! returns current fps
|
||||
s32 CFPSCounter::getFPS() const
|
||||
{
|
||||
return FPS;
|
||||
}
|
||||
|
||||
|
||||
//! returns current primitive count
|
||||
u32 CFPSCounter::getPrimitive() const
|
||||
{
|
||||
return Primitive;
|
||||
}
|
||||
|
||||
|
||||
//! returns average primitive count of last period
|
||||
u32 CFPSCounter::getPrimitiveAverage() const
|
||||
{
|
||||
return PrimitiveAverage;
|
||||
}
|
||||
|
||||
|
||||
//! returns accumulated primitive count since start
|
||||
u32 CFPSCounter::getPrimitiveTotal() const
|
||||
{
|
||||
return PrimitiveTotal;
|
||||
}
|
||||
|
||||
|
||||
//! to be called every frame
|
||||
void CFPSCounter::registerFrame(u32 now, u32 primitivesDrawn)
|
||||
{
|
||||
++FramesCounted;
|
||||
PrimitiveTotal += primitivesDrawn;
|
||||
PrimitivesCounted += primitivesDrawn;
|
||||
Primitive = primitivesDrawn;
|
||||
|
||||
const u32 milliseconds = now - StartTime;
|
||||
|
||||
if (milliseconds >= 1500 )
|
||||
{
|
||||
const f32 invMilli = core::reciprocal ( (f32) milliseconds );
|
||||
|
||||
FPS = core::ceil32 ( ( 1000 * FramesCounted ) * invMilli );
|
||||
PrimitiveAverage = core::ceil32 ( ( 1000 * PrimitivesCounted ) * invMilli );
|
||||
|
||||
FramesCounted = 0;
|
||||
PrimitivesCounted = 0;
|
||||
StartTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_FPSCOUNTER_H_INCLUDED__
|
||||
#define __C_FPSCOUNTER_H_INCLUDED__
|
||||
|
||||
#include "irrTypes.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
class CFPSCounter
|
||||
{
|
||||
public:
|
||||
CFPSCounter();
|
||||
|
||||
//! returns current fps
|
||||
s32 getFPS() const;
|
||||
|
||||
//! returns primitive count
|
||||
u32 getPrimitive() const;
|
||||
|
||||
//! returns average primitive count of last period
|
||||
u32 getPrimitiveAverage() const;
|
||||
|
||||
//! returns accumulated primitive count since start
|
||||
u32 getPrimitiveTotal() const;
|
||||
|
||||
//! to be called every frame
|
||||
void registerFrame(u32 now, u32 primitive);
|
||||
|
||||
private:
|
||||
|
||||
s32 FPS;
|
||||
u32 Primitive;
|
||||
u32 StartTime;
|
||||
|
||||
u32 FramesCounted;
|
||||
u32 PrimitivesCounted;
|
||||
u32 PrimitiveAverage;
|
||||
u32 PrimitiveTotal;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CFileList.h"
|
||||
#include "IrrCompileConfig.h"
|
||||
#include "irrArray.h"
|
||||
#include "coreutil.h"
|
||||
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
static const io::path emptyFileListEntry;
|
||||
|
||||
CFileList::CFileList(const io::path& path, bool ignoreCase, bool ignorePaths)
|
||||
: IgnorePaths(ignorePaths), IgnoreCase(ignoreCase), Path(path)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CFileList");
|
||||
#endif
|
||||
|
||||
Path.replace('\\', '/');
|
||||
}
|
||||
|
||||
CFileList::~CFileList()
|
||||
{
|
||||
Files.clear();
|
||||
}
|
||||
|
||||
u32 CFileList::getFileCount() const
|
||||
{
|
||||
return Files.size();
|
||||
}
|
||||
|
||||
void CFileList::sort()
|
||||
{
|
||||
Files.sort();
|
||||
}
|
||||
|
||||
const io::path& CFileList::getFileName(u32 index) const
|
||||
{
|
||||
if (index >= Files.size())
|
||||
return emptyFileListEntry;
|
||||
|
||||
return Files[index].Name;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the full name of a file in the list, path included, based on an index.
|
||||
const io::path& CFileList::getFullFileName(u32 index) const
|
||||
{
|
||||
if (index >= Files.size())
|
||||
return emptyFileListEntry;
|
||||
|
||||
return Files[index].FullName;
|
||||
}
|
||||
|
||||
//! adds a file or folder
|
||||
u32 CFileList::addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id)
|
||||
{
|
||||
SFileListEntry entry;
|
||||
entry.ID = id ? id : Files.size();
|
||||
entry.Offset = offset;
|
||||
entry.Size = size;
|
||||
entry.Name = fullPath;
|
||||
entry.Name.replace('\\', '/');
|
||||
entry.IsDirectory = isDirectory;
|
||||
|
||||
// remove trailing slash
|
||||
if (entry.Name.lastChar() == '/')
|
||||
{
|
||||
entry.IsDirectory = true;
|
||||
entry.Name[entry.Name.size()-1] = 0;
|
||||
entry.Name.validate();
|
||||
}
|
||||
|
||||
if (IgnoreCase)
|
||||
entry.Name.make_lower();
|
||||
|
||||
entry.FullName = entry.Name;
|
||||
|
||||
core::deletePathFromFilename(entry.Name);
|
||||
|
||||
if (IgnorePaths)
|
||||
entry.FullName = entry.Name;
|
||||
|
||||
//os::Printer::log(Path.c_str(), entry.FullName);
|
||||
|
||||
Files.push_back(entry);
|
||||
|
||||
return Files.size() - 1;
|
||||
}
|
||||
|
||||
//! Returns the ID of a file in the file list, based on an index.
|
||||
u32 CFileList::getID(u32 index) const
|
||||
{
|
||||
return index < Files.size() ? Files[index].ID : 0;
|
||||
}
|
||||
|
||||
bool CFileList::isDirectory(u32 index) const
|
||||
{
|
||||
bool ret = false;
|
||||
if (index < Files.size())
|
||||
ret = Files[index].IsDirectory;
|
||||
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! Returns the size of a file
|
||||
u32 CFileList::getFileSize(u32 index) const
|
||||
{
|
||||
return index < Files.size() ? Files[index].Size : 0;
|
||||
}
|
||||
|
||||
//! Returns the size of a file
|
||||
u32 CFileList::getFileOffset(u32 index) const
|
||||
{
|
||||
return index < Files.size() ? Files[index].Offset : 0;
|
||||
}
|
||||
|
||||
|
||||
//! Searches for a file or folder within the list, returns the index
|
||||
s32 CFileList::findFile(const io::path& filename, bool isDirectory = false) const
|
||||
{
|
||||
SFileListEntry entry;
|
||||
// we only need FullName to be set for the search
|
||||
entry.FullName = filename;
|
||||
entry.IsDirectory = isDirectory;
|
||||
|
||||
// exchange
|
||||
entry.FullName.replace('\\', '/');
|
||||
|
||||
// remove trailing slash
|
||||
if (entry.FullName.lastChar() == '/')
|
||||
{
|
||||
entry.IsDirectory = true;
|
||||
entry.FullName[entry.FullName.size()-1] = 0;
|
||||
entry.FullName.validate();
|
||||
}
|
||||
|
||||
if (IgnoreCase)
|
||||
entry.FullName.make_lower();
|
||||
|
||||
if (IgnorePaths)
|
||||
core::deletePathFromFilename(entry.FullName);
|
||||
|
||||
return Files.binary_search(entry);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the base path of the file list
|
||||
const io::path& CFileList::getPath() const
|
||||
{
|
||||
return Path;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_FILE_LIST_H_INCLUDED__
|
||||
#define __C_FILE_LIST_H_INCLUDED__
|
||||
|
||||
#include "IFileList.h"
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
//! An entry in a list of files, can be a folder or a file.
|
||||
struct SFileListEntry
|
||||
{
|
||||
//! The name of the file
|
||||
/** If this is a file or folder in the virtual filesystem and the archive
|
||||
was created with the ignoreCase flag then the file name will be lower case. */
|
||||
io::path Name;
|
||||
|
||||
//! The name of the file including the path
|
||||
/** If this is a file or folder in the virtual filesystem and the archive was
|
||||
created with the ignoreDirs flag then it will be the same as Name. */
|
||||
io::path FullName;
|
||||
|
||||
//! The size of the file in bytes
|
||||
u32 Size;
|
||||
|
||||
//! The ID of the file in an archive
|
||||
/** This is used to link the FileList entry to extra info held about this
|
||||
file in an archive, which can hold things like data offset and CRC. */
|
||||
u32 ID;
|
||||
|
||||
//! FileOffset inside an archive
|
||||
u32 Offset;
|
||||
|
||||
//! True if this is a folder, false if not.
|
||||
bool IsDirectory;
|
||||
|
||||
//! The == operator is provided so that CFileList can slowly search the list!
|
||||
bool operator ==(const struct SFileListEntry& other) const
|
||||
{
|
||||
if (IsDirectory != other.IsDirectory)
|
||||
return false;
|
||||
|
||||
return FullName.equals_ignore_case(other.FullName);
|
||||
}
|
||||
|
||||
//! The < operator is provided so that CFileList can sort and quickly search the list.
|
||||
bool operator <(const struct SFileListEntry& other) const
|
||||
{
|
||||
if (IsDirectory != other.IsDirectory)
|
||||
return IsDirectory;
|
||||
|
||||
return FullName.lower_ignore_case(other.FullName);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Implementation of a file list
|
||||
class CFileList : public IFileList
|
||||
{
|
||||
public:
|
||||
|
||||
// CFileList methods
|
||||
|
||||
//! Constructor
|
||||
/** \param path The path of this file archive */
|
||||
CFileList(const io::path& path, bool ignoreCase, bool ignorePaths);
|
||||
|
||||
//! Destructor
|
||||
virtual ~CFileList();
|
||||
|
||||
//! Add as a file or folder to the list
|
||||
/** \param fullPath The file name including path, up to the root of the file list.
|
||||
\param isDirectory True if this is a directory rather than a file.
|
||||
\param offset The offset where the file is stored in an archive
|
||||
\param size The size of the file in bytes.
|
||||
\param id The ID of the file in the archive which owns it */
|
||||
virtual u32 addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id=0);
|
||||
|
||||
//! Sorts the file list. You should call this after adding any items to the file list
|
||||
virtual void sort();
|
||||
|
||||
//! Returns the amount of files in the filelist.
|
||||
virtual u32 getFileCount() const;
|
||||
|
||||
//! Gets the name of a file in the list, based on an index.
|
||||
virtual const io::path& getFileName(u32 index) const;
|
||||
|
||||
//! Gets the full name of a file in the list, path included, based on an index.
|
||||
virtual const io::path& getFullFileName(u32 index) const;
|
||||
|
||||
//! Returns the ID of a file in the file list, based on an index.
|
||||
virtual u32 getID(u32 index) const;
|
||||
|
||||
//! Returns true if the file is a directory
|
||||
virtual bool isDirectory(u32 index) const;
|
||||
|
||||
//! Returns the size of a file
|
||||
virtual u32 getFileSize(u32 index) const;
|
||||
|
||||
//! Returns the offest of a file
|
||||
virtual u32 getFileOffset(u32 index) const;
|
||||
|
||||
//! Searches for a file or folder within the list, returns the index
|
||||
virtual s32 findFile(const io::path& filename, bool isFolder) const;
|
||||
|
||||
//! Returns the base path of the file list
|
||||
virtual const io::path& getPath() const;
|
||||
|
||||
protected:
|
||||
|
||||
//! Ignore paths when adding or searching for files
|
||||
bool IgnorePaths;
|
||||
|
||||
//! Ignore case when adding or searching for files
|
||||
bool IgnoreCase;
|
||||
|
||||
//! Path to the file list
|
||||
io::path Path;
|
||||
|
||||
//! List of files
|
||||
core::array<SFileListEntry> Files;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,186 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_FILE_SYSTEM_H_INCLUDED__
|
||||
#define __C_FILE_SYSTEM_H_INCLUDED__
|
||||
|
||||
#include "IFileSystem.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
class CZipReader;
|
||||
class CPakReader;
|
||||
class CMountPointReader;
|
||||
|
||||
/*!
|
||||
FileSystem which uses normal files and one zipfile
|
||||
*/
|
||||
class CFileSystem : public IFileSystem
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CFileSystem();
|
||||
|
||||
//! destructor
|
||||
virtual ~CFileSystem();
|
||||
|
||||
//! opens a file for read access
|
||||
virtual IReadFile* createAndOpenFile(const io::path& filename);
|
||||
|
||||
//! Creates an IReadFile interface for accessing memory like a file.
|
||||
virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped = false);
|
||||
|
||||
//! Creates an IReadFile interface for accessing files inside files
|
||||
virtual IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize);
|
||||
|
||||
//! Creates an IWriteFile interface for accessing memory like a file.
|
||||
virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped=false);
|
||||
|
||||
//! Opens a file for write access.
|
||||
virtual IWriteFile* createAndWriteFile(const io::path& filename, bool append=false);
|
||||
|
||||
//! Adds an archive to the file system.
|
||||
virtual bool addFileArchive(const io::path& filename,
|
||||
bool ignoreCase = true, bool ignorePaths = true,
|
||||
E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN,
|
||||
const core::stringc& password="",
|
||||
IFileArchive** retArchive = 0);
|
||||
|
||||
//! Adds an archive to the file system.
|
||||
virtual bool addFileArchive(IReadFile* file, bool ignoreCase=true,
|
||||
bool ignorePaths=true,
|
||||
E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN,
|
||||
const core::stringc& password="",
|
||||
IFileArchive** retArchive = 0);
|
||||
|
||||
//! Adds an archive to the file system.
|
||||
virtual bool addFileArchive(IFileArchive* archive);
|
||||
|
||||
//! move the hirarchy of the filesystem. moves sourceIndex relative up or down
|
||||
virtual bool moveFileArchive(u32 sourceIndex, s32 relative);
|
||||
|
||||
//! Adds an external archive loader to the engine.
|
||||
virtual void addArchiveLoader(IArchiveLoader* loader);
|
||||
|
||||
//! Returns the total number of archive loaders added.
|
||||
virtual u32 getArchiveLoaderCount() const;
|
||||
|
||||
//! Gets the archive loader by index.
|
||||
virtual IArchiveLoader* getArchiveLoader(u32 index) const;
|
||||
|
||||
//! gets the file archive count
|
||||
virtual u32 getFileArchiveCount() const;
|
||||
|
||||
//! gets an archive
|
||||
virtual IFileArchive* getFileArchive(u32 index);
|
||||
|
||||
virtual void removeAllFileArchives();
|
||||
|
||||
//! removes an archive from the file system.
|
||||
virtual bool removeFileArchive(u32 index);
|
||||
|
||||
//! removes an archive from the file system.
|
||||
virtual bool removeFileArchive(const io::path& filename);
|
||||
|
||||
//! Removes an archive from the file system.
|
||||
virtual bool removeFileArchive(const IFileArchive* archive);
|
||||
|
||||
//! Returns the string of the current working directory
|
||||
virtual const io::path& getWorkingDirectory();
|
||||
|
||||
//! Changes the current Working Directory to the string given.
|
||||
//! The string is operating system dependent. Under Windows it will look
|
||||
//! like this: "drive:\directory\sudirectory\"
|
||||
virtual bool changeWorkingDirectoryTo(const io::path& newDirectory);
|
||||
|
||||
//! Converts a relative path to an absolute (unique) path, resolving symbolic links
|
||||
virtual io::path getAbsolutePath(const io::path& filename) const;
|
||||
|
||||
//! Returns the directory a file is located in.
|
||||
/** \param filename: The file to get the directory from */
|
||||
virtual io::path getFileDir(const io::path& filename) const;
|
||||
|
||||
//! Returns the base part of a filename, i.e. the name without the directory
|
||||
//! part. If no directory is prefixed, the full name is returned.
|
||||
/** \param filename: The file to get the basename from */
|
||||
virtual io::path getFileBasename(const io::path& filename, bool keepExtension=true) const;
|
||||
|
||||
//! flatten a path and file name for example: "/you/me/../." becomes "/you"
|
||||
virtual io::path& flattenFilename( io::path& directory, const io::path& root = "/" ) const;
|
||||
|
||||
//! Get the relative filename, relative to the given directory
|
||||
virtual path getRelativeFilename(const path& filename, const path& directory) const;
|
||||
|
||||
virtual EFileSystemType setFileListSystem(EFileSystemType listType);
|
||||
|
||||
//! Creates a list of files and directories in the current working directory
|
||||
//! and returns it.
|
||||
virtual IFileList* createFileList();
|
||||
|
||||
//! Creates a list of files and directories in specified directory
|
||||
//! and returns it.
|
||||
virtual IFileList* createFileList(const io::path& directory);
|
||||
|
||||
//! Creates an empty filelist
|
||||
virtual IFileList* createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths);
|
||||
|
||||
//! determines if a file exists and would be able to be opened.
|
||||
virtual bool existFile(const io::path& filename) const;
|
||||
|
||||
//! Determines if a file exists and could be opened (thread-safe, ignore file archives), this function returns false for directory
|
||||
virtual bool existFileOnly(const path& filename) const;
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReader* createXMLReader(const io::path& filename);
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReader* createXMLReader(IReadFile* file);
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReaderUTF8* createXMLReaderUTF8(const io::path& filename);
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReaderUTF8* createXMLReaderUTF8(IReadFile* file);
|
||||
|
||||
//! Creates a XML Writer from a file.
|
||||
virtual IXMLWriter* createXMLWriter(const io::path& filename);
|
||||
|
||||
//! Creates a XML Writer from a file.
|
||||
virtual IXMLWriter* createXMLWriter(IWriteFile* file);
|
||||
|
||||
//! Creates a new empty collection of attributes, usable for serialization and more.
|
||||
virtual IAttributes* createEmptyAttributes(video::IVideoDriver* driver);
|
||||
|
||||
virtual std::unique_lock<std::recursive_mutex> acquireFileArchivesMutex() const;
|
||||
|
||||
private:
|
||||
|
||||
// don't expose, needs refactoring
|
||||
bool changeArchivePassword(const path& filename,
|
||||
const core::stringc& password,
|
||||
IFileArchive** archive = 0);
|
||||
|
||||
//! Currently used FileSystemType
|
||||
EFileSystemType FileSystemType;
|
||||
//! WorkingDirectory for Native and Virtual filesystems
|
||||
io::path WorkingDirectory [2];
|
||||
//! currently attached ArchiveLoaders
|
||||
core::array<IArchiveLoader*> ArchiveLoader;
|
||||
//! currently attached Archives
|
||||
core::array<IFileArchive*> FileArchives;
|
||||
|
||||
mutable std::recursive_mutex m_file_archives_mutex;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,539 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIButton.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIButton::CGUIButton(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle, bool noclip)
|
||||
: IGUIButton(environment, parent, id, rectangle),
|
||||
SpriteBank(0), OverrideFont(0), Image(0), PressedImage(0),
|
||||
ClickTime(0), HoverTime(0), FocusTime(0),
|
||||
IsPushButton(false), Pressed(false),
|
||||
UseAlphaChannel(false), DrawBorder(true), ScaleImage(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIButton");
|
||||
#endif
|
||||
setNotClipped(noclip);
|
||||
|
||||
// Initialize the sprites.
|
||||
for (u32 i=0; i<EGBS_COUNT; ++i)
|
||||
ButtonSprites[i].Index = -1;
|
||||
|
||||
// This element can be tabbed.
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIButton::~CGUIButton()
|
||||
{
|
||||
if (OverrideFont)
|
||||
OverrideFont->drop();
|
||||
|
||||
if (Image)
|
||||
Image->drop();
|
||||
|
||||
if (PressedImage)
|
||||
PressedImage->drop();
|
||||
|
||||
if (SpriteBank)
|
||||
SpriteBank->drop();
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the images should be scaled to fit the button
|
||||
void CGUIButton::setScaleImage(bool scaleImage)
|
||||
{
|
||||
ScaleImage = scaleImage;
|
||||
}
|
||||
|
||||
|
||||
//! Returns whether the button scale the used images
|
||||
bool CGUIButton::isScalingImage() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return ScaleImage;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the button should use the skin to draw its border
|
||||
void CGUIButton::setDrawBorder(bool border)
|
||||
{
|
||||
DrawBorder = border;
|
||||
}
|
||||
|
||||
|
||||
void CGUIButton::setSpriteBank(IGUISpriteBank* sprites)
|
||||
{
|
||||
if (sprites)
|
||||
sprites->grab();
|
||||
|
||||
if (SpriteBank)
|
||||
SpriteBank->drop();
|
||||
|
||||
SpriteBank = sprites;
|
||||
}
|
||||
|
||||
|
||||
void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop)
|
||||
{
|
||||
if (SpriteBank)
|
||||
{
|
||||
ButtonSprites[(u32)state].Index = index;
|
||||
ButtonSprites[(u32)state].Color = color;
|
||||
ButtonSprites[(u32)state].Loop = loop;
|
||||
}
|
||||
else
|
||||
{
|
||||
ButtonSprites[(u32)state].Index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIButton::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (!isEnabled())
|
||||
return IGUIElement::OnEvent(event);
|
||||
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (event.KeyInput.PressedDown &&
|
||||
(event.KeyInput.Key == IRR_KEY_RETURN ||
|
||||
event.KeyInput.Key == IRR_KEY_SPACE))
|
||||
{
|
||||
if (!IsPushButton)
|
||||
setPressed(true);
|
||||
else
|
||||
setPressed(!Pressed);
|
||||
|
||||
return true;
|
||||
}
|
||||
if (Pressed && !IsPushButton && event.KeyInput.PressedDown &&
|
||||
event.KeyInput.Key == IRR_KEY_ESCAPE)
|
||||
{
|
||||
setPressed(false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!event.KeyInput.PressedDown && Pressed &&
|
||||
(event.KeyInput.Key == IRR_KEY_RETURN ||
|
||||
event.KeyInput.Key == IRR_KEY_SPACE))
|
||||
{
|
||||
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
|
||||
if (Parent)
|
||||
{
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EET_GUI_EVENT:
|
||||
if (event.GUIEvent.Caller == this)
|
||||
{
|
||||
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
|
||||
{
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
FocusTime = os::Timer::getTime();
|
||||
}
|
||||
else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
|
||||
{
|
||||
FocusTime = os::Timer::getTime();
|
||||
}
|
||||
else if (event.GUIEvent.EventType == EGET_ELEMENT_HOVERED || event.GUIEvent.EventType == EGET_ELEMENT_LEFT)
|
||||
{
|
||||
HoverTime = os::Timer::getTime();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
|
||||
{
|
||||
if (Environment->hasFocus(this) &&
|
||||
!AbsoluteClippingRect.isPointInside(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)))
|
||||
{
|
||||
Environment->removeFocus(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsPushButton)
|
||||
setPressed(true);
|
||||
|
||||
Environment->setFocus(this);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
|
||||
{
|
||||
bool wasPressed = Pressed;
|
||||
|
||||
if ( !AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y ) ) )
|
||||
{
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
else
|
||||
{
|
||||
setPressed(!Pressed);
|
||||
}
|
||||
|
||||
if ((!IsPushButton && wasPressed && Parent) ||
|
||||
(IsPushButton && wasPressed != Pressed))
|
||||
{
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIButton::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
// todo: move sprite up and text down if the pressed state has a sprite
|
||||
const core::position2di spritePos = AbsoluteRect.getCenter();
|
||||
|
||||
if (!Pressed)
|
||||
{
|
||||
if (DrawBorder)
|
||||
skin->draw3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect);
|
||||
|
||||
if (Image)
|
||||
{
|
||||
core::position2d<s32> pos = spritePos;
|
||||
pos.X -= ImageRect.getWidth() / 2;
|
||||
pos.Y -= ImageRect.getHeight() / 2;
|
||||
|
||||
skin->draw2DImage(Image,
|
||||
ScaleImage ? AbsoluteRect :
|
||||
core::recti(pos, ImageRect.getSize()),
|
||||
ImageRect, &AbsoluteClippingRect,
|
||||
0, UseAlphaChannel);
|
||||
//video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
//driver->draw2DImage(Image,
|
||||
// ScaleImage? AbsoluteRect :
|
||||
// core::recti(pos, ImageRect.getSize()),
|
||||
// ImageRect, &AbsoluteClippingRect,
|
||||
// 0, UseAlphaChannel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DrawBorder)
|
||||
skin->draw3DButtonPanePressed(this, AbsoluteRect, &AbsoluteClippingRect);
|
||||
|
||||
if (PressedImage)
|
||||
{
|
||||
core::position2d<s32> pos = spritePos;
|
||||
pos.X -= PressedImageRect.getWidth() / 2;
|
||||
pos.Y -= PressedImageRect.getHeight() / 2;
|
||||
|
||||
if (Image == PressedImage && PressedImageRect == ImageRect)
|
||||
{
|
||||
pos.X += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X);
|
||||
pos.Y += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y);
|
||||
}
|
||||
skin->draw2DImage(PressedImage,
|
||||
ScaleImage? AbsoluteRect :
|
||||
core::recti(pos, PressedImageRect.getSize()),
|
||||
PressedImageRect, &AbsoluteClippingRect,
|
||||
0, UseAlphaChannel);
|
||||
}
|
||||
}
|
||||
|
||||
if (false) //SpriteBank)
|
||||
{
|
||||
// pressed / unpressed animation
|
||||
u32 state = Pressed ? (u32)EGBS_BUTTON_DOWN : (u32)EGBS_BUTTON_UP;
|
||||
if (ButtonSprites[state].Index != -1)
|
||||
{
|
||||
SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos,
|
||||
&AbsoluteClippingRect, ButtonSprites[state].Color, ClickTime, os::Timer::getTime(),
|
||||
ButtonSprites[state].Loop, true);
|
||||
}
|
||||
|
||||
// focused / unfocused animation
|
||||
state = Environment->hasFocus(this) ? (u32)EGBS_BUTTON_FOCUSED : (u32)EGBS_BUTTON_NOT_FOCUSED;
|
||||
if (ButtonSprites[state].Index != -1)
|
||||
{
|
||||
SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos,
|
||||
&AbsoluteClippingRect, ButtonSprites[state].Color, FocusTime, os::Timer::getTime(),
|
||||
ButtonSprites[state].Loop, true);
|
||||
}
|
||||
|
||||
// mouse over / off animation
|
||||
if (isEnabled())
|
||||
{
|
||||
state = Environment->getHovered() == this ? (u32)EGBS_BUTTON_MOUSE_OVER : (u32)EGBS_BUTTON_MOUSE_OFF;
|
||||
if (ButtonSprites[state].Index != -1)
|
||||
{
|
||||
SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos,
|
||||
&AbsoluteClippingRect, ButtonSprites[state].Color, HoverTime, os::Timer::getTime(),
|
||||
ButtonSprites[state].Loop, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Text.size())
|
||||
{
|
||||
IGUIFont* font = getActiveFont();
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
if (Pressed)
|
||||
{
|
||||
rect.UpperLeftCorner.X += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_X);
|
||||
rect.UpperLeftCorner.Y += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y);
|
||||
}
|
||||
|
||||
if (font)
|
||||
font->draw(Text.c_str(), rect,
|
||||
skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
|
||||
true, true, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
|
||||
void CGUIButton::setOverrideFont(IGUIFont* font)
|
||||
{
|
||||
if (OverrideFont == font)
|
||||
return;
|
||||
|
||||
if (OverrideFont)
|
||||
OverrideFont->drop();
|
||||
|
||||
OverrideFont = font;
|
||||
|
||||
if (OverrideFont)
|
||||
OverrideFont->grab();
|
||||
}
|
||||
|
||||
//! Gets the override font (if any)
|
||||
IGUIFont * CGUIButton::getOverrideFont() const
|
||||
{
|
||||
return OverrideFont;
|
||||
}
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
IGUIFont* CGUIButton::getActiveFont() const
|
||||
{
|
||||
if ( OverrideFont )
|
||||
return OverrideFont;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
return skin->getFont(EGDF_BUTTON);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in normal state.
|
||||
void CGUIButton::setImage(video::ITexture* image)
|
||||
{
|
||||
if (image)
|
||||
image->grab();
|
||||
if (Image)
|
||||
Image->drop();
|
||||
|
||||
Image = image;
|
||||
if (image)
|
||||
ImageRect = core::rect<s32>(core::position2d<s32>(0,0), image->getSize());
|
||||
|
||||
if (!PressedImage)
|
||||
setPressedImage(Image);
|
||||
}
|
||||
|
||||
|
||||
//! Sets the image which should be displayed on the button when it is in its normal state.
|
||||
void CGUIButton::setImage(video::ITexture* image, const core::rect<s32>& pos)
|
||||
{
|
||||
setImage(image);
|
||||
ImageRect = pos;
|
||||
}
|
||||
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in pressed state.
|
||||
void CGUIButton::setPressedImage(video::ITexture* image)
|
||||
{
|
||||
if (image)
|
||||
image->grab();
|
||||
|
||||
if (PressedImage)
|
||||
PressedImage->drop();
|
||||
|
||||
PressedImage = image;
|
||||
if (image)
|
||||
PressedImageRect = core::rect<s32>(core::position2d<s32>(0,0), image->getSize());
|
||||
}
|
||||
|
||||
|
||||
//! Sets the image which should be displayed on the button when it is in its pressed state.
|
||||
void CGUIButton::setPressedImage(video::ITexture* image, const core::rect<s32>& pos)
|
||||
{
|
||||
setPressedImage(image);
|
||||
PressedImageRect = pos;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the button should behave like a push button. Which means it
|
||||
//! can be in two states: Normal or Pressed. With a click on the button,
|
||||
//! the user can change the state of the button.
|
||||
void CGUIButton::setIsPushButton(bool isPushButton)
|
||||
{
|
||||
IsPushButton = isPushButton;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the button is currently pressed
|
||||
bool CGUIButton::isPressed() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Pressed;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the pressed state of the button if this is a pushbutton
|
||||
void CGUIButton::setPressed(bool pressed)
|
||||
{
|
||||
if (Pressed != pressed)
|
||||
{
|
||||
ClickTime = os::Timer::getTime();
|
||||
Pressed = pressed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Returns whether the button is a push button
|
||||
bool CGUIButton::isPushButton() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return IsPushButton;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the alpha channel should be used for drawing images on the button (default is false)
|
||||
void CGUIButton::setUseAlphaChannel(bool useAlphaChannel)
|
||||
{
|
||||
UseAlphaChannel = useAlphaChannel;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the alpha channel should be used for drawing images on the button
|
||||
bool CGUIButton::isAlphaChannelUsed() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return UseAlphaChannel;
|
||||
}
|
||||
|
||||
|
||||
bool CGUIButton::isDrawingBorder() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return DrawBorder;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIButton::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIButton::serializeAttributes(out,options);
|
||||
|
||||
out->addBool ("PushButton", IsPushButton );
|
||||
if (IsPushButton)
|
||||
out->addBool("Pressed", Pressed);
|
||||
|
||||
out->addTexture ("Image", Image);
|
||||
out->addRect ("ImageRect", ImageRect);
|
||||
out->addTexture ("PressedImage", PressedImage);
|
||||
out->addRect ("PressedImageRect", PressedImageRect);
|
||||
|
||||
out->addBool ("UseAlphaChannel", isAlphaChannelUsed());
|
||||
out->addBool ("Border", isDrawingBorder());
|
||||
out->addBool ("ScaleImage", isScalingImage());
|
||||
|
||||
// out->addString ("OverrideFont", OverrideFont);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIButton::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIButton::deserializeAttributes(in,options);
|
||||
|
||||
IsPushButton = in->getAttributeAsBool("PushButton");
|
||||
Pressed = IsPushButton ? in->getAttributeAsBool("Pressed") : false;
|
||||
|
||||
core::rect<s32> rec = in->getAttributeAsRect("ImageRect");
|
||||
if (rec.isValid())
|
||||
setImage( in->getAttributeAsTexture("Image"), rec);
|
||||
else
|
||||
setImage( in->getAttributeAsTexture("Image") );
|
||||
|
||||
rec = in->getAttributeAsRect("PressedImageRect");
|
||||
if (rec.isValid())
|
||||
setPressedImage( in->getAttributeAsTexture("PressedImage"), rec);
|
||||
else
|
||||
setPressedImage( in->getAttributeAsTexture("PressedImage") );
|
||||
|
||||
setDrawBorder(in->getAttributeAsBool("Border"));
|
||||
setUseAlphaChannel(in->getAttributeAsBool("UseAlphaChannel"));
|
||||
setScaleImage(in->getAttributeAsBool("ScaleImage"));
|
||||
|
||||
// setOverrideFont(in->getAttributeAsString("OverrideFont"));
|
||||
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_BUTTON_H_INCLUDED__
|
||||
#define __C_GUI_BUTTON_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
#include "SColor.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIButton : public IGUIButton
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIButton(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle, bool noclip=false);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIButton();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
|
||||
virtual void setOverrideFont(IGUIFont* font=0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in normal state.
|
||||
virtual void setImage(video::ITexture* image=0);
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in normal state.
|
||||
virtual void setImage(video::ITexture* image, const core::rect<s32>& pos);
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in pressed state.
|
||||
virtual void setPressedImage(video::ITexture* image=0);
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in pressed state.
|
||||
virtual void setPressedImage(video::ITexture* image, const core::rect<s32>& pos);
|
||||
|
||||
//! Sets the sprite bank used by the button
|
||||
virtual void setSpriteBank(IGUISpriteBank* bank=0);
|
||||
|
||||
//! Sets the animated sprite for a specific button state
|
||||
/** \param index: Number of the sprite within the sprite bank, use -1 for no sprite
|
||||
\param state: State of the button to set the sprite for
|
||||
\param index: The sprite number from the current sprite bank
|
||||
\param color: The color of the sprite
|
||||
*/
|
||||
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
|
||||
video::SColor color=video::SColor(255,255,255,255), bool loop=false);
|
||||
|
||||
//! Sets if the button should behave like a push button. Which means it
|
||||
//! can be in two states: Normal or Pressed. With a click on the button,
|
||||
//! the user can change the state of the button.
|
||||
virtual void setIsPushButton(bool isPushButton=true);
|
||||
|
||||
//! Checks whether the button is a push button
|
||||
virtual bool isPushButton() const;
|
||||
|
||||
//! Sets the pressed state of the button if this is a pushbutton
|
||||
virtual void setPressed(bool pressed=true);
|
||||
|
||||
//! Returns if the button is currently pressed
|
||||
virtual bool isPressed() const;
|
||||
|
||||
//! Sets if the button should use the skin to draw its border
|
||||
virtual void setDrawBorder(bool border=true);
|
||||
|
||||
//! Checks if the button face and border are being drawn
|
||||
virtual bool isDrawingBorder() const;
|
||||
|
||||
//! Sets if the alpha channel should be used for drawing images on the button (default is false)
|
||||
virtual void setUseAlphaChannel(bool useAlphaChannel=true);
|
||||
|
||||
//! Checks if the alpha channel should be used for drawing images on the button
|
||||
virtual bool isAlphaChannelUsed() const;
|
||||
|
||||
//! Sets if the button should scale the button images to fit
|
||||
virtual void setScaleImage(bool scaleImage=true);
|
||||
|
||||
//! Checks whether the button scales the used images
|
||||
virtual bool isScalingImage() const;
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
private:
|
||||
|
||||
struct ButtonSprite
|
||||
{
|
||||
s32 Index;
|
||||
video::SColor Color;
|
||||
bool Loop;
|
||||
};
|
||||
|
||||
ButtonSprite ButtonSprites[EGBS_COUNT];
|
||||
|
||||
IGUISpriteBank* SpriteBank;
|
||||
IGUIFont* OverrideFont;
|
||||
|
||||
video::ITexture* Image;
|
||||
video::ITexture* PressedImage;
|
||||
|
||||
core::rect<s32> ImageRect;
|
||||
core::rect<s32> PressedImageRect;
|
||||
|
||||
u32 ClickTime, HoverTime, FocusTime;
|
||||
|
||||
bool IsPushButton;
|
||||
bool Pressed;
|
||||
bool UseAlphaChannel;
|
||||
bool DrawBorder;
|
||||
bool ScaleImage;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_BUTTON_H_INCLUDED__
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUICheckBox.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUICheckBox::CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
|
||||
: IGUICheckBox(environment, parent, id, rectangle), checkTime(0), Pressed(false), Checked(checked)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUICheckBox");
|
||||
#endif
|
||||
|
||||
// this element can be tabbed into
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUICheckBox::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (event.KeyInput.PressedDown &&
|
||||
(event.KeyInput.Key == IRR_KEY_RETURN ||
|
||||
event.KeyInput.Key == IRR_KEY_SPACE))
|
||||
{
|
||||
Pressed = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (Pressed && event.KeyInput.PressedDown &&
|
||||
event.KeyInput.Key == IRR_KEY_ESCAPE)
|
||||
{
|
||||
Pressed = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!event.KeyInput.PressedDown && Pressed &&
|
||||
(event.KeyInput.Key == IRR_KEY_RETURN ||
|
||||
event.KeyInput.Key == IRR_KEY_SPACE))
|
||||
{
|
||||
Pressed = false;
|
||||
if (Parent)
|
||||
{
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
Checked = !Checked;
|
||||
newEvent.GUIEvent.EventType = EGET_CHECKBOX_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EET_GUI_EVENT:
|
||||
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
|
||||
{
|
||||
if (event.GUIEvent.Caller == this)
|
||||
Pressed = false;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
|
||||
{
|
||||
Pressed = true;
|
||||
checkTime = os::Timer::getTime();
|
||||
Environment->setFocus(this);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
|
||||
{
|
||||
bool wasPressed = Pressed;
|
||||
Environment->removeFocus(this);
|
||||
Pressed = false;
|
||||
|
||||
if (wasPressed && Parent)
|
||||
{
|
||||
if ( !AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y) ) )
|
||||
{
|
||||
Pressed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
Checked = !Checked;
|
||||
newEvent.GUIEvent.EventType = EGET_CHECKBOX_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUICheckBox::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
{
|
||||
const s32 height = skin->getSize(EGDS_CHECK_BOX_WIDTH);
|
||||
|
||||
core::rect<s32> checkRect(AbsoluteRect.UpperLeftCorner.X,
|
||||
((AbsoluteRect.getHeight() - height) / 2) + AbsoluteRect.UpperLeftCorner.Y,
|
||||
0, 0);
|
||||
|
||||
checkRect.LowerRightCorner.X = checkRect.UpperLeftCorner.X + height;
|
||||
checkRect.LowerRightCorner.Y = checkRect.UpperLeftCorner.Y + height;
|
||||
|
||||
EGUI_DEFAULT_COLOR col = EGDC_GRAY_EDITABLE;
|
||||
if ( isEnabled() )
|
||||
col = Pressed ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE;
|
||||
skin->draw3DSunkenPane(this, skin->getColor(col),
|
||||
false, true, checkRect, &AbsoluteClippingRect);
|
||||
|
||||
if (Checked)
|
||||
{
|
||||
skin->drawIcon(this, EGDI_CHECK_BOX_CHECKED, checkRect.getCenter(),
|
||||
checkTime, os::Timer::getTime(), false, &AbsoluteClippingRect);
|
||||
}
|
||||
if (Text.size())
|
||||
{
|
||||
checkRect = AbsoluteRect;
|
||||
checkRect.UpperLeftCorner.X += height + 5;
|
||||
|
||||
IGUIFont* font = skin->getFont();
|
||||
if (font)
|
||||
{
|
||||
font->draw(Text.c_str(), checkRect,
|
||||
skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), false, true, &AbsoluteClippingRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! set if box is checked
|
||||
void CGUICheckBox::setChecked(bool checked)
|
||||
{
|
||||
Checked = checked;
|
||||
}
|
||||
|
||||
|
||||
//! returns if box is checked
|
||||
bool CGUICheckBox::isChecked() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Checked;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUICheckBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUICheckBox::serializeAttributes(out,options);
|
||||
out->addBool("Checked", Checked);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUICheckBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
Checked = in->getAttributeAsBool ("Checked");
|
||||
|
||||
IGUICheckBox::deserializeAttributes(in,options);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_CHECKBOX_H_INCLUDED__
|
||||
#define __C_GUI_CHECKBOX_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUICheckBox.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUICheckBox : public IGUICheckBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);
|
||||
|
||||
//! set if box is checked
|
||||
virtual void setChecked(bool checked);
|
||||
|
||||
//! returns if box is checked
|
||||
virtual bool isChecked() const;
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
private:
|
||||
|
||||
u32 checkTime;
|
||||
bool Pressed;
|
||||
bool Checked;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // __C_GUI_CHECKBOX_H_INCLUDED__
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
@@ -0,0 +1,483 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIColorSelectDialog.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
#include "IFileList.h"
|
||||
#include "os.h"
|
||||
#include "fast_atof.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
const s32 CSD_WIDTH = 350;
|
||||
const s32 CSD_HEIGHT = 300;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct subElementPredefines
|
||||
{
|
||||
const wchar_t *pre;
|
||||
const wchar_t *init;
|
||||
const wchar_t *post;
|
||||
int x, y;
|
||||
int range_down ,range_up;
|
||||
};
|
||||
|
||||
static const subElementPredefines Template [] =
|
||||
{
|
||||
{ L"A:", L"0", 0,50,165, 0, 255 },
|
||||
{ L"R:", L"0", 0,20,205, 0, 255 },
|
||||
{ L"G:", L"0", 0,20,230, 0, 255 },
|
||||
{ L"B:", L"0", 0,20,255, 0, 255 },
|
||||
{ L"H:", L"0", L"°",80,205, 0, 360 },
|
||||
{ L"S:", L"0", L"%",80,230, 0, 100 },
|
||||
{ L"L:", L"0", L"%",80,255, 0, 100 },
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//! constructor
|
||||
CGUIColorSelectDialog::CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id)
|
||||
: IGUIColorSelectDialog(environment, parent, id,
|
||||
core::rect<s32>((parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2,
|
||||
(parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2,
|
||||
(parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2+CSD_WIDTH,
|
||||
(parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2+CSD_HEIGHT)),
|
||||
Dragging(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
IGUIElement::setDebugName("CGUIColorSelectDialog");
|
||||
#endif
|
||||
|
||||
Text = title;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
const s32 buttonw = environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH);
|
||||
const s32 posx = RelativeRect.getWidth() - buttonw - 4;
|
||||
|
||||
CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw),
|
||||
this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close");
|
||||
if (skin && skin->getSpriteBank())
|
||||
{
|
||||
CloseButton->setSpriteBank(skin->getSpriteBank());
|
||||
CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
}
|
||||
CloseButton->setSubElement(true);
|
||||
CloseButton->setTabStop(false);
|
||||
CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
CloseButton->grab();
|
||||
|
||||
OKButton = Environment->addButton(
|
||||
core::rect<s32>(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50),
|
||||
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK");
|
||||
OKButton->setSubElement(true);
|
||||
OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
OKButton->grab();
|
||||
|
||||
CancelButton = Environment->addButton(
|
||||
core::rect<s32>(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75),
|
||||
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel");
|
||||
CancelButton->setSubElement(true);
|
||||
CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
CancelButton->grab();
|
||||
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
ColorRing.Texture = driver->getTexture ( "#colorring" );
|
||||
if ( 0 == ColorRing.Texture )
|
||||
{
|
||||
buildColorRing(core::dimension2d<u32>(128, 128), 1,
|
||||
Environment->getSkin()->getColor(EGDC_3D_SHADOW));
|
||||
}
|
||||
|
||||
core::rect<s32> r(20,20, 0,0);
|
||||
|
||||
ColorRing.Control = Environment->addImage(ColorRing.Texture, r.UpperLeftCorner, true, this);
|
||||
ColorRing.Control->setSubElement(true);
|
||||
ColorRing.Control->grab();
|
||||
|
||||
for ( u32 i = 0; i != sizeof (Template) / sizeof ( subElementPredefines ); ++i )
|
||||
{
|
||||
if ( Template[i].pre )
|
||||
{
|
||||
r.UpperLeftCorner.X = Template[i].x;
|
||||
r.UpperLeftCorner.Y = Template[i].y;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X + 15;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
|
||||
IGUIElement *t = Environment->addStaticText(Template[i].pre, r, false, false, this);
|
||||
t->setSubElement(true);
|
||||
}
|
||||
|
||||
if ( Template[i].post )
|
||||
{
|
||||
r.UpperLeftCorner.X = Template[i].x + 56;
|
||||
r.UpperLeftCorner.Y = Template[i].y;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X + 15;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
|
||||
IGUIElement *t = Environment->addStaticText( Template[i].post, r, false, false, this);
|
||||
t->setSubElement(true);
|
||||
}
|
||||
|
||||
r.UpperLeftCorner.X = Template[i].x + 15;
|
||||
r.UpperLeftCorner.Y = Template[i].y-2;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X + 40;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
|
||||
|
||||
gui::IGUISpinBox* spin = Environment->addSpinBox( Template[i].init, r, true, this);
|
||||
spin->setSubElement(true);
|
||||
spin->setDecimalPlaces(0);
|
||||
spin->setRange((f32)Template[i].range_down, (f32)Template[i].range_up);
|
||||
spin->grab();
|
||||
|
||||
Battery.push_back(spin);
|
||||
}
|
||||
|
||||
bringToFront(CancelButton);
|
||||
bringToFront(OKButton);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIColorSelectDialog::~CGUIColorSelectDialog()
|
||||
{
|
||||
if (CloseButton)
|
||||
CloseButton->drop();
|
||||
|
||||
if (OKButton)
|
||||
OKButton->drop();
|
||||
|
||||
if (CancelButton)
|
||||
CancelButton->drop();
|
||||
|
||||
for (u32 i = 0; i != Battery.size(); ++i)
|
||||
Battery[i]->drop();
|
||||
|
||||
if (ColorRing.Control)
|
||||
ColorRing.Control->drop();
|
||||
}
|
||||
|
||||
|
||||
//! renders a antialiased, colored ring
|
||||
void CGUIColorSelectDialog::buildColorRing( const core::dimension2d<u32> & dim, s32 supersample, const video::SColor& borderColor )
|
||||
{
|
||||
const core::dimension2d<u32> d(dim.Width * supersample, dim.Height * supersample);
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
video::IImage *RawTexture = driver->createImage(video::ECF_A8R8G8B8, d);
|
||||
|
||||
RawTexture->fill ( 0x00808080 );
|
||||
|
||||
const s32 radiusOut = ( d.Width / 2 ) - 4;
|
||||
const s32 fullR2 = radiusOut * radiusOut;
|
||||
|
||||
video::SColorf rgb(0,0,0);
|
||||
video::SColorHSL hsl;
|
||||
hsl.Luminance = 50;
|
||||
hsl.Saturation = 100;
|
||||
|
||||
core::position2d<s32> p;
|
||||
for ( p.Y = -radiusOut; p.Y <= radiusOut; p.Y += 1 )
|
||||
{
|
||||
s32 y2 = p.Y * p.Y;
|
||||
|
||||
for (p.X = -radiusOut; p.X <= radiusOut; p.X += 1)
|
||||
{
|
||||
s32 r2 = y2 + ( p.X * p.X );
|
||||
|
||||
// test point in circle
|
||||
s32 testa = r2 - fullR2;
|
||||
|
||||
if ( testa < 0 )
|
||||
{
|
||||
// dotproduct u ( x,y ) * v ( 1, 0 ) = cosinus(a)
|
||||
|
||||
const f32 r = sqrtf((f32) r2);
|
||||
|
||||
// normalize, dotproduct = xnorm
|
||||
const f32 xn = r == 0.f ? 0.f : -p.X * core::reciprocal(r);
|
||||
|
||||
hsl.Hue = acosf(xn)*core::RADTODEG;
|
||||
if ( p.Y > 0 )
|
||||
hsl.Hue = 360 - hsl.Hue;
|
||||
hsl.Hue -= 90;
|
||||
|
||||
const f32 rTest = r / radiusOut;
|
||||
#if 0
|
||||
if (rTest < 0.33f)
|
||||
{
|
||||
// luminance from 0 to 50
|
||||
hsl.Luminance = 50*(rTest/0.33);
|
||||
hsl.Saturation = 0.f;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
else
|
||||
if ( rTest < 0.66f )
|
||||
{
|
||||
// saturation from 0 to 100
|
||||
hsl.Saturation = 100*(( rTest - 0.33f ) / 0.33f);
|
||||
hsl.Luminance = 50;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// luminance from 50 to 100
|
||||
hsl.Luminance = 100*(0.5f + ( ( rTest - 0.66f ) / .66f ));
|
||||
hsl.Saturation = 100;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
// borders should be slightly transparent
|
||||
if ( rTest >= 0.95f )
|
||||
rgb.a = (1.f-rTest)*20;
|
||||
else
|
||||
rgb.a=1.f;
|
||||
#else
|
||||
if ( rTest > 0.5f )
|
||||
{
|
||||
hsl.Saturation = 100;
|
||||
hsl.Luminance = 50;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
// borders should be slightly transparent
|
||||
if ( rTest < 0.5f )
|
||||
rgb.a = 0;
|
||||
else if ( rTest >= 0.95f )
|
||||
rgb.a = (1.f-rTest)*20;
|
||||
else if ( rTest <= 0.55f )
|
||||
rgb.a = (rTest-0.5f)*20;
|
||||
else
|
||||
rgb.a=1.f;
|
||||
#endif
|
||||
RawTexture->setPixel(4+p.X+radiusOut, 4+p.Y+radiusOut, rgb.toSColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RawTexture->unlock ();
|
||||
|
||||
if ( supersample > 1 )
|
||||
{
|
||||
video::IImage * filter = driver->createImage(video::ECF_A8R8G8B8, dim );
|
||||
RawTexture->copyToScalingBoxFilter(filter);
|
||||
RawTexture->drop();
|
||||
RawTexture = filter;
|
||||
}
|
||||
|
||||
bool generateMipLevels = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
driver->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, false);
|
||||
|
||||
ColorRing.Texture = driver->addTexture ( "#colorring", RawTexture);
|
||||
RawTexture->drop();
|
||||
|
||||
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, generateMipLevels);
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIColorSelectDialog::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_SPINBOX_CHANGED:
|
||||
{
|
||||
for ( u32 i = 0; i!= Battery.size (); ++i )
|
||||
{
|
||||
if ( event.GUIEvent.Caller == Battery[i] )
|
||||
{
|
||||
if (i<4)
|
||||
{
|
||||
video::SColor rgb((u32)Battery[0]->getValue(), (u32)Battery[1]->getValue(),
|
||||
(u32)Battery[2]->getValue(), (u32)Battery[3]->getValue());
|
||||
video::SColorHSL hsl;
|
||||
video::SColorf rgb2(rgb);
|
||||
hsl.fromRGB(rgb2);
|
||||
Battery[4]->setValue(hsl.Hue);
|
||||
Battery[5]->setValue(hsl.Saturation);
|
||||
Battery[6]->setValue(hsl.Luminance);
|
||||
}
|
||||
else
|
||||
{
|
||||
video::SColorHSL hsl(Battery[4]->getValue(), Battery[5]->getValue(),
|
||||
Battery[6]->getValue());
|
||||
video::SColorf rgb2;
|
||||
hsl.toRGB(rgb2);
|
||||
video::SColor rgb = rgb2.toSColor();
|
||||
Battery[1]->setValue((f32)rgb.getRed());
|
||||
Battery[2]->setValue((f32)rgb.getGreen());
|
||||
Battery[3]->setValue((f32)rgb.getBlue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
Dragging = false;
|
||||
break;
|
||||
case EGET_BUTTON_CLICKED:
|
||||
if (event.GUIEvent.Caller == CloseButton ||
|
||||
event.GUIEvent.Caller == CancelButton)
|
||||
{
|
||||
sendCancelEvent();
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.Caller == OKButton)
|
||||
{
|
||||
sendSelectedEvent();
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case EGET_LISTBOX_CHANGED:
|
||||
case EGET_LISTBOX_SELECTED_AGAIN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
Dragging = true;
|
||||
Environment->setFocus(this);
|
||||
return true;
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
Dragging = false;
|
||||
Environment->removeFocus(this);
|
||||
return true;
|
||||
case EMIE_MOUSE_MOVED:
|
||||
if (Dragging)
|
||||
{
|
||||
// gui window should not be dragged outside its parent
|
||||
if (Parent)
|
||||
if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||
|
||||
event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||
|
||||
event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||
|
||||
event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1)
|
||||
|
||||
return true;
|
||||
|
||||
move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIColorSelectDialog::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
core::rect<s32> rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
|
||||
AbsoluteRect, &AbsoluteClippingRect);
|
||||
|
||||
if (Text.size())
|
||||
{
|
||||
rect.UpperLeftCorner.X += 2;
|
||||
rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;
|
||||
|
||||
IGUIFont* font = skin->getFont(EGDF_WINDOW);
|
||||
if (font)
|
||||
font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true,
|
||||
&AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
|
||||
// draw color selector after the window elements
|
||||
core::vector2di pos(ColorRing.Control->getAbsolutePosition().UpperLeftCorner);
|
||||
pos.X += ColorRing.Texture->getOriginalSize().Width/2;
|
||||
pos.Y += ColorRing.Texture->getOriginalSize().Height/2;
|
||||
#if 0
|
||||
const f32 h = Battery[4]->getValue();
|
||||
const f32 s = Battery[5]->getValue();
|
||||
const f32 l = Battery[6]->getValue();
|
||||
const f32 factor = 58.f*(((s==0)&&(l<50))?(l*0.33f/50):(
|
||||
(s<100)?((.33f+(s*0.33f/100))):((0.66f+(l-50)*0.33f/50))));
|
||||
|
||||
#else
|
||||
const f32 factor = 44;
|
||||
#endif
|
||||
pos.X += core::round32(sinf(Battery[4]->getValue()*core::DEGTORAD)*factor);
|
||||
pos.Y -= core::round32(cosf(Battery[4]->getValue()*core::DEGTORAD)*factor);
|
||||
Environment->getVideoDriver()->draw2DPolygon(pos, 4, 0xffffffff, 4);
|
||||
}
|
||||
|
||||
|
||||
video::SColor CGUIColorSelectDialog::getColor()
|
||||
{
|
||||
return video::SColor((u32)Battery[0]->getValue(), (u32)Battery[1]->getValue(),
|
||||
(u32)Battery[2]->getValue(), (u32)Battery[3]->getValue());
|
||||
}
|
||||
|
||||
video::SColorHSL CGUIColorSelectDialog::getColorHSL()
|
||||
{
|
||||
return video::SColorHSL(Battery[4]->getValue(), Battery[5]->getValue(),
|
||||
Battery[6]->getValue());
|
||||
}
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void CGUIColorSelectDialog::sendSelectedEvent()
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_FILE_SELECTED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! sends the event that the file choose process has been canceld
|
||||
void CGUIColorSelectDialog::sendCancelEvent()
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__
|
||||
#define __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIColorSelectDialog.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUISpinBox.h"
|
||||
#include "IGUIImage.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIColorSelectDialog : public IGUIColorSelectDialog
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIColorSelectDialog();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
virtual video::SColor getColor();
|
||||
virtual video::SColorHSL getColorHSL();
|
||||
|
||||
private:
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void sendSelectedEvent();
|
||||
|
||||
//! sends the event that the file choose process has been canceld
|
||||
void sendCancelEvent();
|
||||
|
||||
core::position2d<s32> DragStart;
|
||||
bool Dragging;
|
||||
IGUIButton* CloseButton;
|
||||
IGUIButton* OKButton;
|
||||
IGUIButton* CancelButton;
|
||||
|
||||
core::array<IGUISpinBox*> Battery;
|
||||
|
||||
struct SColorCircle
|
||||
{
|
||||
IGUIImage * Control;
|
||||
video::ITexture * Texture;
|
||||
};
|
||||
SColorCircle ColorRing;
|
||||
|
||||
void buildColorRing( const core::dimension2d<u32> & dim, s32 supersample, const video::SColor& borderColor );
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__
|
||||
@@ -0,0 +1,525 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIComboBox.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "CGUIListBox.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle)
|
||||
: IGUIComboBox(environment, parent, id, rectangle),
|
||||
ListButton(0), SelectedText(0), ListBox(0), LastFocus(0),
|
||||
Selected(-1), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), MaxSelectionRows(5), HasFocus(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIComboBox");
|
||||
#endif
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
s32 width = 15;
|
||||
if (skin)
|
||||
width = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
|
||||
|
||||
core::rect<s32> r;
|
||||
r.UpperLeftCorner.X = rectangle.getWidth() - width - 2;
|
||||
r.LowerRightCorner.X = rectangle.getWidth() - 2;
|
||||
|
||||
r.UpperLeftCorner.Y = 2;
|
||||
r.LowerRightCorner.Y = rectangle.getHeight() - 2;
|
||||
|
||||
ListButton = Environment->addButton(r, this, -1, L"");
|
||||
if (skin && skin->getSpriteBank())
|
||||
{
|
||||
ListButton->setSpriteBank(skin->getSpriteBank());
|
||||
ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
}
|
||||
ListButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
ListButton->setSubElement(true);
|
||||
ListButton->setTabStop(false);
|
||||
|
||||
r.UpperLeftCorner.X = 2;
|
||||
r.UpperLeftCorner.Y = 2;
|
||||
r.LowerRightCorner.X = RelativeRect.getWidth() - (ListButton->getAbsolutePosition().getWidth() + 2);
|
||||
r.LowerRightCorner.Y = RelativeRect.getHeight() - 2;
|
||||
|
||||
SelectedText = Environment->addStaticText(L"", r, false, false, this, -1, false);
|
||||
SelectedText->setSubElement(true);
|
||||
SelectedText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
SelectedText->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_CENTER);
|
||||
if (skin)
|
||||
SelectedText->setOverrideColor(skin->getColor(EGDC_BUTTON_TEXT));
|
||||
SelectedText->enableOverrideColor(true);
|
||||
|
||||
// this element can be tabbed to
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
}
|
||||
|
||||
|
||||
void CGUIComboBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
|
||||
{
|
||||
HAlign = horizontal;
|
||||
VAlign = vertical;
|
||||
SelectedText->setTextAlignment(horizontal, vertical);
|
||||
}
|
||||
|
||||
|
||||
//! Set the maximal number of rows for the selection listbox
|
||||
void CGUIComboBox::setMaxSelectionRows(u32 max)
|
||||
{
|
||||
MaxSelectionRows = max;
|
||||
|
||||
// force recalculation of open listbox
|
||||
if (ListBox)
|
||||
{
|
||||
openCloseMenu();
|
||||
openCloseMenu();
|
||||
}
|
||||
}
|
||||
|
||||
//! Get the maximimal number of rows for the selection listbox
|
||||
u32 CGUIComboBox::getMaxSelectionRows() const
|
||||
{
|
||||
return MaxSelectionRows;
|
||||
}
|
||||
|
||||
|
||||
//! Returns amount of items in box
|
||||
u32 CGUIComboBox::getItemCount() const
|
||||
{
|
||||
return Items.size();
|
||||
}
|
||||
|
||||
|
||||
//! returns string of an item. the idx may be a value from 0 to itemCount-1
|
||||
const wchar_t* CGUIComboBox::getItem(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].Name.c_str();
|
||||
}
|
||||
|
||||
//! returns string of an item. the idx may be a value from 0 to itemCount-1
|
||||
u32 CGUIComboBox::getItemData(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].Data;
|
||||
}
|
||||
|
||||
//! Returns index based on item data
|
||||
s32 CGUIComboBox::getIndexForItemData(u32 data ) const
|
||||
{
|
||||
for ( u32 i = 0; i < Items.size (); ++i )
|
||||
{
|
||||
if ( Items[i].Data == data )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//! Removes an item from the combo box.
|
||||
void CGUIComboBox::removeItem(u32 idx)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
if (Selected == (s32)idx)
|
||||
setSelected(-1);
|
||||
|
||||
Items.erase(idx);
|
||||
}
|
||||
|
||||
|
||||
//! Returns caption of this element.
|
||||
const wchar_t* CGUIComboBox::getText() const
|
||||
{
|
||||
return getItem(Selected);
|
||||
}
|
||||
|
||||
|
||||
//! adds an item and returns the index of it
|
||||
u32 CGUIComboBox::addItem(const wchar_t* text, u32 data)
|
||||
{
|
||||
Items.push_back( SComboData ( text, data ) );
|
||||
|
||||
if (Selected == -1)
|
||||
setSelected(0);
|
||||
|
||||
return Items.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
//! deletes all items in the combo box
|
||||
void CGUIComboBox::clear()
|
||||
{
|
||||
Items.clear();
|
||||
setSelected(-1);
|
||||
}
|
||||
|
||||
|
||||
//! returns id of selected item. returns -1 if no item is selected.
|
||||
s32 CGUIComboBox::getSelected() const
|
||||
{
|
||||
return Selected;
|
||||
}
|
||||
|
||||
|
||||
//! sets the selected item. Set this to -1 if no item should be selected
|
||||
void CGUIComboBox::setSelected(s32 idx)
|
||||
{
|
||||
if (idx < -1 || idx >= (s32)Items.size())
|
||||
return;
|
||||
|
||||
Selected = idx;
|
||||
if (Selected == -1)
|
||||
SelectedText->setText(L"");
|
||||
else
|
||||
SelectedText->setText(Items[Selected].Name.c_str());
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIComboBox::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (ListBox && event.KeyInput.PressedDown &&
|
||||
event.KeyInput.Key == IRR_KEY_ESCAPE)
|
||||
{
|
||||
// hide list box
|
||||
openCloseMenu();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.KeyInput.Key == IRR_KEY_RETURN ||
|
||||
event.KeyInput.Key == IRR_KEY_SPACE)
|
||||
{
|
||||
if (!event.KeyInput.PressedDown)
|
||||
{
|
||||
openCloseMenu();
|
||||
}
|
||||
|
||||
ListButton->setPressed(ListBox == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.KeyInput.PressedDown)
|
||||
{
|
||||
s32 oldSelected = Selected;
|
||||
bool absorb = true;
|
||||
switch (event.KeyInput.Key)
|
||||
{
|
||||
case IRR_KEY_DOWN:
|
||||
setSelected(Selected+1);
|
||||
break;
|
||||
case IRR_KEY_UP:
|
||||
setSelected(Selected-1);
|
||||
break;
|
||||
case IRR_KEY_HOME:
|
||||
case IRR_KEY_PRIOR:
|
||||
setSelected(0);
|
||||
break;
|
||||
case IRR_KEY_END:
|
||||
case IRR_KEY_NEXT:
|
||||
setSelected((s32)Items.size()-1);
|
||||
break;
|
||||
default:
|
||||
absorb = false;
|
||||
}
|
||||
|
||||
if (Selected <0)
|
||||
setSelected(0);
|
||||
|
||||
if (Selected >= (s32)Items.size())
|
||||
setSelected((s32)Items.size() -1);
|
||||
|
||||
if (Selected != oldSelected)
|
||||
{
|
||||
sendSelectionChangedEvent();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (absorb)
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case EET_GUI_EVENT:
|
||||
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
if (ListBox &&
|
||||
(Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller) ) &&
|
||||
event.GUIEvent.Element != this &&
|
||||
!isMyChild(event.GUIEvent.Element) &&
|
||||
!ListBox->isMyChild(event.GUIEvent.Element))
|
||||
{
|
||||
openCloseMenu();
|
||||
}
|
||||
break;
|
||||
case EGET_BUTTON_CLICKED:
|
||||
if (event.GUIEvent.Caller == ListButton)
|
||||
{
|
||||
openCloseMenu();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EGET_LISTBOX_SELECTED_AGAIN:
|
||||
case EGET_LISTBOX_CHANGED:
|
||||
if (event.GUIEvent.Caller == ListBox)
|
||||
{
|
||||
setSelected(ListBox->getSelected());
|
||||
if (Selected <0 || Selected >= (s32)Items.size())
|
||||
setSelected(-1);
|
||||
openCloseMenu();
|
||||
|
||||
sendSelectionChangedEvent();
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
{
|
||||
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
|
||||
|
||||
// send to list box
|
||||
if (ListBox && ListBox->isPointInside(p) && ListBox->OnEvent(event))
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
{
|
||||
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
|
||||
|
||||
// send to list box
|
||||
if (!(ListBox &&
|
||||
ListBox->getAbsolutePosition().isPointInside(p) &&
|
||||
ListBox->OnEvent(event)))
|
||||
{
|
||||
openCloseMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
{
|
||||
s32 oldSelected = Selected;
|
||||
setSelected( Selected + ((event.MouseInput.Wheel < 0) ? 1 : -1));
|
||||
|
||||
if (Selected <0)
|
||||
setSelected(0);
|
||||
|
||||
if (Selected >= (s32)Items.size())
|
||||
setSelected((s32)Items.size() -1);
|
||||
|
||||
if (Selected != oldSelected)
|
||||
{
|
||||
sendSelectionChangedEvent();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
void CGUIComboBox::sendSelectionChangedEvent()
|
||||
{
|
||||
if (Parent)
|
||||
{
|
||||
SEvent event;
|
||||
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_COMBO_BOX_CHANGED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIComboBox::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
IGUIElement *currentFocus = Environment->getFocus();
|
||||
if (currentFocus != LastFocus)
|
||||
{
|
||||
HasFocus = currentFocus == this || isMyChild(currentFocus);
|
||||
LastFocus = currentFocus;
|
||||
}
|
||||
|
||||
// set colors each time as skin-colors can be changed
|
||||
SelectedText->setBackgroundColor(skin->getColor(EGDC_HIGH_LIGHT));
|
||||
if(isEnabled())
|
||||
{
|
||||
SelectedText->setDrawBackground(HasFocus);
|
||||
SelectedText->setOverrideColor(skin->getColor(HasFocus ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT));
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedText->setDrawBackground(false);
|
||||
SelectedText->setOverrideColor(skin->getColor(EGDC_GRAY_TEXT));
|
||||
}
|
||||
ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
|
||||
ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
|
||||
|
||||
|
||||
core::rect<s32> frameRect(AbsoluteRect);
|
||||
|
||||
// draw the border
|
||||
|
||||
skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT),
|
||||
true, true, frameRect, &AbsoluteClippingRect);
|
||||
|
||||
// draw children
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
void CGUIComboBox::openCloseMenu()
|
||||
{
|
||||
if (ListBox)
|
||||
{
|
||||
// close list box
|
||||
Environment->setFocus(this);
|
||||
ListBox->remove();
|
||||
ListBox = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Parent)
|
||||
Parent->bringToFront(this);
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
u32 h = Items.size();
|
||||
|
||||
if (h > getMaxSelectionRows())
|
||||
h = getMaxSelectionRows();
|
||||
if (h == 0)
|
||||
h = 1;
|
||||
|
||||
IGUIFont* font = skin->getFont();
|
||||
if (font)
|
||||
h *= (font->getDimension(L"A").Height + 4);
|
||||
|
||||
// open list box
|
||||
core::rect<s32> r(0, AbsoluteRect.getHeight(),
|
||||
AbsoluteRect.getWidth(), AbsoluteRect.getHeight() + h);
|
||||
|
||||
ListBox = new CGUIListBox(Environment, this, -1, r, false, true, true);
|
||||
ListBox->setSubElement(true);
|
||||
ListBox->setNotClipped(true);
|
||||
ListBox->drop();
|
||||
|
||||
// ensure that list box is always completely visible
|
||||
if (ListBox->getAbsolutePosition().LowerRightCorner.Y > Environment->getRootGUIElement()->getAbsolutePosition().getHeight())
|
||||
ListBox->setRelativePosition( core::rect<s32>(0, -ListBox->getAbsolutePosition().getHeight(), AbsoluteRect.getWidth(), 0) );
|
||||
|
||||
for (s32 i=0; i<(s32)Items.size(); ++i)
|
||||
ListBox->addItem(Items[i].Name.c_str());
|
||||
|
||||
ListBox->setSelected(Selected);
|
||||
|
||||
// set focus
|
||||
Environment->setFocus(ListBox);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIComboBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIComboBox::serializeAttributes(out,options);
|
||||
|
||||
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
|
||||
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
|
||||
out->addInt("MaxSelectionRows", (s32)MaxSelectionRows );
|
||||
|
||||
out->addInt ("Selected", Selected );
|
||||
out->addInt ("ItemCount", Items.size());
|
||||
for (u32 i=0; i < Items.size(); ++i)
|
||||
{
|
||||
core::stringc s = "Item";
|
||||
s += i;
|
||||
s += "Text";
|
||||
out->addString(s.c_str(), Items[i].Name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIComboBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIComboBox::deserializeAttributes(in,options);
|
||||
|
||||
setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
|
||||
(EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
|
||||
setMaxSelectionRows( (u32)(in->getAttributeAsInt("MaxSelectionRows")) );
|
||||
|
||||
// clear the list
|
||||
clear();
|
||||
// get item count
|
||||
u32 c = in->getAttributeAsInt("ItemCount");
|
||||
// add items
|
||||
for (u32 i=0; i < c; ++i)
|
||||
{
|
||||
core::stringc s = "Item";
|
||||
s += i;
|
||||
s += "Text";
|
||||
addItem(in->getAttributeAsStringW(s.c_str()).c_str(), 0);
|
||||
}
|
||||
|
||||
setSelected(in->getAttributeAsInt("Selected"));
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_COMBO_BOX_H_INCLUDED__
|
||||
#define __C_GUI_COMBO_BOX_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIComboBox.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class IGUIButton;
|
||||
class IGUIListBox;
|
||||
|
||||
//! Single line edit box for editing simple text.
|
||||
class CGUIComboBox : public IGUIComboBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle);
|
||||
|
||||
//! Returns amount of items in box
|
||||
virtual u32 getItemCount() const;
|
||||
|
||||
//! returns string of an item. the idx may be a value from 0 to itemCount-1
|
||||
virtual const wchar_t* getItem(u32 idx) const;
|
||||
|
||||
//! Returns item data of an item. the idx may be a value from 0 to itemCount-1
|
||||
virtual u32 getItemData(u32 idx) const;
|
||||
|
||||
//! Returns index based on item data
|
||||
virtual s32 getIndexForItemData( u32 data ) const;
|
||||
|
||||
//! adds an item and returns the index of it
|
||||
virtual u32 addItem(const wchar_t* text, u32 data);
|
||||
|
||||
//! Removes an item from the combo box.
|
||||
virtual void removeItem(u32 id);
|
||||
|
||||
//! deletes all items in the combo box
|
||||
virtual void clear();
|
||||
|
||||
//! returns the text of the currently selected item
|
||||
virtual const wchar_t* getText() const;
|
||||
|
||||
//! returns id of selected item. returns -1 if no item is selected.
|
||||
virtual s32 getSelected() const;
|
||||
|
||||
//! sets the selected item. Set this to -1 if no item should be selected
|
||||
virtual void setSelected(s32 idx);
|
||||
|
||||
//! sets the text alignment of the text part
|
||||
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical);
|
||||
|
||||
//! Set the maximal number of rows for the selection listbox
|
||||
virtual void setMaxSelectionRows(u32 max);
|
||||
|
||||
//! Get the maximimal number of rows for the selection listbox
|
||||
virtual u32 getMaxSelectionRows() const;
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
private:
|
||||
|
||||
void openCloseMenu();
|
||||
void sendSelectionChangedEvent();
|
||||
|
||||
IGUIButton* ListButton;
|
||||
IGUIStaticText* SelectedText;
|
||||
IGUIListBox* ListBox;
|
||||
IGUIElement *LastFocus;
|
||||
|
||||
|
||||
struct SComboData
|
||||
{
|
||||
SComboData ( const wchar_t * text, u32 data )
|
||||
: Name (text), Data ( data ) {}
|
||||
|
||||
core::stringw Name;
|
||||
u32 Data;
|
||||
};
|
||||
core::array< SComboData > Items;
|
||||
|
||||
s32 Selected;
|
||||
EGUI_ALIGNMENT HAlign, VAlign;
|
||||
u32 MaxSelectionRows;
|
||||
bool HasFocus;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_COMBO_BOX_H_INCLUDED__
|
||||
|
||||
@@ -0,0 +1,867 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIContextMenu.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CGUIContextMenu::CGUIContextMenu(IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id,
|
||||
core::rect<s32> rectangle, bool getFocus, bool allowFocus)
|
||||
: IGUIContextMenu(environment, parent, id, rectangle), EventParent(0), LastFont(0),
|
||||
CloseHandling(ECMC_REMOVE), HighLighted(-1), ChangeTime(0), AllowFocus(allowFocus)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIContextMenu");
|
||||
#endif
|
||||
|
||||
Pos = rectangle.UpperLeftCorner;
|
||||
recalculateSize();
|
||||
|
||||
if (getFocus)
|
||||
Environment->setFocus(this);
|
||||
|
||||
setNotClipped(true);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIContextMenu::~CGUIContextMenu()
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->drop();
|
||||
|
||||
if (LastFont)
|
||||
LastFont->drop();
|
||||
}
|
||||
|
||||
//! set behavior when menus are closed
|
||||
void CGUIContextMenu::setCloseHandling(ECONTEXT_MENU_CLOSE onClose)
|
||||
{
|
||||
CloseHandling = onClose;
|
||||
}
|
||||
|
||||
//! get current behavior when the menue will be closed
|
||||
ECONTEXT_MENU_CLOSE CGUIContextMenu::getCloseHandling() const
|
||||
{
|
||||
return CloseHandling;
|
||||
}
|
||||
|
||||
//! Returns amount of menu items
|
||||
u32 CGUIContextMenu::getItemCount() const
|
||||
{
|
||||
return Items.size();
|
||||
}
|
||||
|
||||
|
||||
//! Adds a menu item.
|
||||
u32 CGUIContextMenu::addItem(const wchar_t* text, s32 commandId, bool enabled, bool hasSubMenu, bool checked, bool autoChecking)
|
||||
{
|
||||
return insertItem(Items.size(), text, commandId, enabled, hasSubMenu, checked, autoChecking);
|
||||
}
|
||||
|
||||
//! Insert a menu item at specified position.
|
||||
u32 CGUIContextMenu::insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled,
|
||||
bool hasSubMenu, bool checked, bool autoChecking)
|
||||
{
|
||||
SItem s;
|
||||
s.Enabled = enabled;
|
||||
s.Checked = checked;
|
||||
s.AutoChecking = autoChecking;
|
||||
s.Text = text;
|
||||
s.IsSeparator = (text == 0);
|
||||
s.SubMenu = 0;
|
||||
s.CommandId = commandId;
|
||||
|
||||
if (hasSubMenu)
|
||||
{
|
||||
s.SubMenu = new CGUIContextMenu(Environment, this, commandId,
|
||||
core::rect<s32>(0,0,100,100), false, false);
|
||||
s.SubMenu->setVisible(false);
|
||||
}
|
||||
|
||||
u32 result = idx;
|
||||
if ( idx < Items.size() )
|
||||
{
|
||||
Items.insert(s, idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Items.push_back(s);
|
||||
result = Items.size() - 1;
|
||||
}
|
||||
|
||||
recalculateSize();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 CGUIContextMenu::findItemWithCommandId(s32 commandId, u32 idxStartSearch) const
|
||||
{
|
||||
for ( u32 i=idxStartSearch; i<Items.size(); ++i )
|
||||
{
|
||||
if ( Items[i].CommandId == commandId )
|
||||
{
|
||||
return (s32)i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! Adds a sub menu from an element that already exists.
|
||||
void CGUIContextMenu::setSubMenu(u32 index, CGUIContextMenu* menu)
|
||||
{
|
||||
if (index >= Items.size())
|
||||
return;
|
||||
|
||||
if (menu)
|
||||
menu->grab();
|
||||
if (Items[index].SubMenu)
|
||||
Items[index].SubMenu->drop();
|
||||
|
||||
Items[index].SubMenu = menu;
|
||||
menu->setVisible(false);
|
||||
|
||||
if (Items[index].SubMenu)
|
||||
{
|
||||
menu->AllowFocus = false;
|
||||
if ( Environment->getFocus() == menu )
|
||||
{
|
||||
Environment->setFocus( this );
|
||||
}
|
||||
}
|
||||
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
//! Adds a separator item to the menu
|
||||
void CGUIContextMenu::addSeparator()
|
||||
{
|
||||
addItem(0, -1, true, false, false, false);
|
||||
}
|
||||
|
||||
|
||||
//! Returns text of the menu item.
|
||||
const wchar_t* CGUIContextMenu::getItemText(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].Text.c_str();
|
||||
}
|
||||
|
||||
|
||||
//! Sets text of the menu item.
|
||||
void CGUIContextMenu::setItemText(u32 idx, const wchar_t* text)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].Text = text;
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
//! should the element change the checked status on clicking
|
||||
void CGUIContextMenu::setItemAutoChecking(u32 idx, bool autoChecking)
|
||||
{
|
||||
if ( idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].AutoChecking = autoChecking;
|
||||
}
|
||||
|
||||
//! does the element change the checked status on clicking
|
||||
bool CGUIContextMenu::getItemAutoChecking(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return false;
|
||||
|
||||
return Items[idx].AutoChecking;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if a menu item is enabled
|
||||
bool CGUIContextMenu::isItemEnabled(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return false;
|
||||
}
|
||||
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Items[idx].Enabled;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if a menu item is checked
|
||||
bool CGUIContextMenu::isItemChecked(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return false;
|
||||
}
|
||||
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Items[idx].Checked;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the menu item should be enabled.
|
||||
void CGUIContextMenu::setItemEnabled(u32 idx, bool enabled)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].Enabled = enabled;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the menu item should be checked.
|
||||
void CGUIContextMenu::setItemChecked(u32 idx, bool checked )
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].Checked = checked;
|
||||
}
|
||||
|
||||
|
||||
//! Removes a menu item
|
||||
void CGUIContextMenu::removeItem(u32 idx)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
if (Items[idx].SubMenu)
|
||||
{
|
||||
Items[idx].SubMenu->drop();
|
||||
Items[idx].SubMenu = 0;
|
||||
}
|
||||
|
||||
Items.erase(idx);
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
//! Removes all menu items
|
||||
void CGUIContextMenu::removeAllItems()
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->drop();
|
||||
|
||||
Items.clear();
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIContextMenu::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus)
|
||||
{
|
||||
// set event parent of submenus
|
||||
IGUIElement * p = EventParent ? EventParent : Parent;
|
||||
setEventParent(p);
|
||||
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_ELEMENT_CLOSED;
|
||||
if ( !p->OnEvent(event) )
|
||||
{
|
||||
if ( CloseHandling & ECMC_HIDE )
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
if ( CloseHandling & ECMC_REMOVE )
|
||||
{
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case EGET_ELEMENT_FOCUSED:
|
||||
if (event.GUIEvent.Caller == this && !AllowFocus)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
{
|
||||
// menu might be removed if it loses focus in sendClick, so grab a reference
|
||||
grab();
|
||||
const u32 t = sendClick(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
|
||||
if ((t==0 || t==1) && Environment->hasFocus(this))
|
||||
Environment->removeFocus(this);
|
||||
drop();
|
||||
}
|
||||
return true;
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
return true;
|
||||
case EMIE_MOUSE_MOVED:
|
||||
if (Environment->hasFocus(this))
|
||||
highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! Sets the visible state of this element.
|
||||
void CGUIContextMenu::setVisible(bool visible)
|
||||
{
|
||||
HighLighted = -1;
|
||||
ChangeTime = os::Timer::getTime();
|
||||
for (u32 j=0; j<Items.size(); ++j)
|
||||
if (Items[j].SubMenu)
|
||||
Items[j].SubMenu->setVisible(false);
|
||||
|
||||
IGUIElement::setVisible(visible);
|
||||
}
|
||||
|
||||
|
||||
//! sends a click Returns:
|
||||
//! 0 if click went outside of the element,
|
||||
//! 1 if a valid button was clicked,
|
||||
//! 2 if a nonclickable element was clicked
|
||||
u32 CGUIContextMenu::sendClick(const core::position2d<s32>& p)
|
||||
{
|
||||
u32 t = 0;
|
||||
|
||||
// get number of open submenu
|
||||
s32 openmenu = -1;
|
||||
s32 j;
|
||||
for (j=0; j<(s32)Items.size(); ++j)
|
||||
if (Items[j].SubMenu && Items[j].SubMenu->isVisible())
|
||||
{
|
||||
openmenu = j;
|
||||
break;
|
||||
}
|
||||
|
||||
// delegate click operation to submenu
|
||||
if (openmenu != -1)
|
||||
{
|
||||
t = Items[j].SubMenu->sendClick(p);
|
||||
if (t != 0)
|
||||
return t; // clicked something
|
||||
}
|
||||
|
||||
// check click on myself
|
||||
if (isPointInside(p) &&
|
||||
(u32)HighLighted < Items.size())
|
||||
{
|
||||
if (!Items[HighLighted].Enabled ||
|
||||
Items[HighLighted].IsSeparator ||
|
||||
Items[HighLighted].SubMenu)
|
||||
return 2;
|
||||
|
||||
if ( Items[HighLighted].AutoChecking )
|
||||
{
|
||||
Items[HighLighted].Checked = Items[HighLighted].Checked ? false : true;
|
||||
}
|
||||
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_MENU_ITEM_SELECTED;
|
||||
if (EventParent)
|
||||
EventParent->OnEvent(event);
|
||||
else if (Parent)
|
||||
Parent->OnEvent(event);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! returns true, if an element was highligted
|
||||
bool CGUIContextMenu::highlight(const core::position2d<s32>& p, bool canOpenSubMenu)
|
||||
{
|
||||
if (!isEnabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// get number of open submenu
|
||||
s32 openmenu = -1;
|
||||
s32 i;
|
||||
for (i=0; i<(s32)Items.size(); ++i)
|
||||
if (Items[i].Enabled && Items[i].SubMenu && Items[i].SubMenu->isVisible())
|
||||
{
|
||||
openmenu = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// delegate highlight operation to submenu
|
||||
if (openmenu != -1)
|
||||
{
|
||||
if (Items[openmenu].Enabled && Items[openmenu].SubMenu->highlight(p, canOpenSubMenu))
|
||||
{
|
||||
HighLighted = openmenu;
|
||||
ChangeTime = os::Timer::getTime();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// highlight myself
|
||||
for (i=0; i<(s32)Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].Enabled && getHRect(Items[i], AbsoluteRect).isPointInside(p))
|
||||
{
|
||||
HighLighted = i;
|
||||
ChangeTime = os::Timer::getTime();
|
||||
|
||||
// make submenus visible/invisible
|
||||
for (s32 j=0; j<(s32)Items.size(); ++j)
|
||||
if (Items[j].SubMenu)
|
||||
{
|
||||
if ( j == i && canOpenSubMenu && Items[j].Enabled )
|
||||
Items[j].SubMenu->setVisible(true);
|
||||
else if ( j != i )
|
||||
Items[j].SubMenu->setVisible(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
HighLighted = openmenu;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//! returns the item highlight-area
|
||||
core::rect<s32> CGUIContextMenu::getHRect(const SItem& i, const core::rect<s32>& absolute) const
|
||||
{
|
||||
core::rect<s32> r = absolute;
|
||||
r.UpperLeftCorner.Y += i.PosY;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//! Gets drawing rect of Item
|
||||
core::rect<s32> CGUIContextMenu::getRect(const SItem& i, const core::rect<s32>& absolute) const
|
||||
{
|
||||
core::rect<s32> r = absolute;
|
||||
r.UpperLeftCorner.Y += i.PosY;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height;
|
||||
r.UpperLeftCorner.X += 20;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIContextMenu::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
if (!skin)
|
||||
return;
|
||||
|
||||
IGUIFont* font = skin->getFont(EGDF_MENU);
|
||||
if (font != LastFont)
|
||||
{
|
||||
if (LastFont)
|
||||
LastFont->drop();
|
||||
LastFont = font;
|
||||
if (LastFont)
|
||||
LastFont->grab();
|
||||
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
core::rect<s32>* clip = 0;
|
||||
|
||||
// draw frame
|
||||
skin->draw3DMenuPane(this, AbsoluteRect, clip);
|
||||
|
||||
// loop through all menu items
|
||||
|
||||
rect = AbsoluteRect;
|
||||
|
||||
for (s32 i=0; i<(s32)Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].IsSeparator)
|
||||
{
|
||||
// draw separator
|
||||
rect = AbsoluteRect;
|
||||
rect.UpperLeftCorner.Y += Items[i].PosY + 3;
|
||||
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
|
||||
rect.UpperLeftCorner.X += 5;
|
||||
rect.LowerRightCorner.X -= 5;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), rect, clip);
|
||||
|
||||
rect.LowerRightCorner.Y += 1;
|
||||
rect.UpperLeftCorner.Y += 1;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), rect, clip);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
rect = getRect(Items[i], AbsoluteRect);
|
||||
|
||||
// draw highlighted
|
||||
|
||||
if (i == HighLighted && Items[i].Enabled)
|
||||
{
|
||||
core::rect<s32> r = AbsoluteRect;
|
||||
r.LowerRightCorner.Y = rect.LowerRightCorner.Y;
|
||||
r.UpperLeftCorner.Y = rect.UpperLeftCorner.Y;
|
||||
r.LowerRightCorner.X -= 5;
|
||||
r.UpperLeftCorner.X += 5;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), r, clip);
|
||||
}
|
||||
|
||||
// draw text
|
||||
|
||||
EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT;
|
||||
|
||||
if (i == HighLighted)
|
||||
c = EGDC_HIGH_LIGHT_TEXT;
|
||||
|
||||
if (!Items[i].Enabled)
|
||||
c = EGDC_GRAY_TEXT;
|
||||
|
||||
if (font)
|
||||
font->draw(Items[i].Text.c_str(), rect,
|
||||
skin->getColor(c), false, true, clip);
|
||||
|
||||
|
||||
// draw submenu symbol
|
||||
//IGUISpriteBank* sprites = skin->getSpriteBank();
|
||||
//if (Items[i].SubMenu && sprites)
|
||||
//{
|
||||
// core::rect<s32> r = rect;
|
||||
// r.UpperLeftCorner.X = r.LowerRightCorner.X - 15;
|
||||
//
|
||||
// sprites->draw2DSprite(skin->getIcon(EGDI_CURSOR_RIGHT),
|
||||
// r.getCenter(), clip, skin->getColor(c),
|
||||
// (i == HighLighted) ? ChangeTime : 0,
|
||||
// (i == HighLighted) ? os::Timer::getTime() : 0,
|
||||
// (i == HighLighted), true);
|
||||
//}
|
||||
|
||||
// draw checked symbol
|
||||
//if (Items[i].Checked && sprites)
|
||||
//{
|
||||
// core::rect<s32> r = rect;
|
||||
// r.LowerRightCorner.X = r.UpperLeftCorner.X - 15;
|
||||
// r.UpperLeftCorner.X = r.LowerRightCorner.X + 15;
|
||||
// sprites->draw2DSprite(skin->getIcon(EGDI_CHECK_BOX_CHECKED),
|
||||
// r.getCenter(), clip, skin->getColor(c),
|
||||
// (i == HighLighted) ? ChangeTime : 0,
|
||||
// (i == HighLighted) ? os::Timer::getTime() : 0,
|
||||
// (i == HighLighted), true);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
void CGUIContextMenu::recalculateSize()
|
||||
{
|
||||
IGUIFont* font = Environment->getSkin()->getFont(EGDF_MENU);
|
||||
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
core::rect<s32> rect;
|
||||
rect.UpperLeftCorner = RelativeRect.UpperLeftCorner;
|
||||
u32 width = 100;
|
||||
u32 height = 3;
|
||||
|
||||
u32 i;
|
||||
for (i=0; i<Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].IsSeparator)
|
||||
{
|
||||
Items[i].Dim.Width = 100;
|
||||
Items[i].Dim.Height = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
Items[i].Dim = font->getDimension(Items[i].Text.c_str());
|
||||
Items[i].Dim.Width += 40;
|
||||
|
||||
if (Items[i].Dim.Width > width)
|
||||
width = Items[i].Dim.Width;
|
||||
}
|
||||
|
||||
Items[i].PosY = height;
|
||||
height += Items[i].Dim.Height;
|
||||
}
|
||||
|
||||
height += 5;
|
||||
|
||||
if (height < 10)
|
||||
height = 10;
|
||||
|
||||
rect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + width;
|
||||
rect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + height;
|
||||
|
||||
setRelativePosition(rect);
|
||||
|
||||
// recalculate submenus
|
||||
for (i=0; i<Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].SubMenu)
|
||||
{
|
||||
// move submenu
|
||||
const s32 w = Items[i].SubMenu->getAbsolutePosition().getWidth();
|
||||
const s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight();
|
||||
|
||||
core::rect<s32> subRect(width-5, Items[i].PosY, width+w-5, Items[i].PosY+h);
|
||||
|
||||
// if it would be drawn beyond the right border, then add it to the left side
|
||||
gui::IGUIElement * root = Environment->getRootGUIElement();
|
||||
if ( root )
|
||||
{
|
||||
core::rect<s32> rectRoot( root->getAbsolutePosition() );
|
||||
if ( getAbsolutePosition().UpperLeftCorner.X+subRect.LowerRightCorner.X > rectRoot.LowerRightCorner.X )
|
||||
{
|
||||
subRect.UpperLeftCorner.X = -w;
|
||||
subRect.LowerRightCorner.X = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Items[i].SubMenu->setRelativePosition(subRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Returns the selected item in the menu
|
||||
s32 CGUIContextMenu::getSelectedItem() const
|
||||
{
|
||||
return HighLighted;
|
||||
}
|
||||
|
||||
|
||||
//! \return Returns a pointer to the submenu of an item.
|
||||
IGUIContextMenu* CGUIContextMenu::getSubMenu(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].SubMenu;
|
||||
}
|
||||
|
||||
|
||||
//! Returns command id of a menu item
|
||||
s32 CGUIContextMenu::getItemCommandId(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return -1;
|
||||
|
||||
return Items[idx].CommandId;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the command id of a menu item
|
||||
void CGUIContextMenu::setItemCommandId(u32 idx, s32 id)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].CommandId = id;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIElement::serializeAttributes(out,options);
|
||||
out->addPosition2d("Position", Pos);
|
||||
|
||||
if (Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU )
|
||||
{
|
||||
const IGUIContextMenu* const ptr = (const IGUIContextMenu*)Parent;
|
||||
// find the position of this item in its parent's list
|
||||
u32 i;
|
||||
// VC6 needs the cast for this
|
||||
for (i=0; (i<ptr->getItemCount()) && (ptr->getSubMenu(i) != (const IGUIContextMenu*)this); ++i)
|
||||
; // do nothing
|
||||
|
||||
out->addInt("ParentItem", i);
|
||||
}
|
||||
|
||||
out->addInt("CloseHandling", (s32)CloseHandling);
|
||||
|
||||
// write out the item list
|
||||
out->addInt("ItemCount", Items.size());
|
||||
|
||||
core::stringc tmp;
|
||||
|
||||
for (u32 i=0; i < Items.size(); ++i)
|
||||
{
|
||||
tmp = "IsSeparator"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].IsSeparator);
|
||||
|
||||
if (!Items[i].IsSeparator)
|
||||
{
|
||||
tmp = "Text"; tmp += i;
|
||||
out->addString(tmp.c_str(), Items[i].Text.c_str());
|
||||
tmp = "CommandID"; tmp += i;
|
||||
out->addInt(tmp.c_str(), Items[i].CommandId);
|
||||
tmp = "Enabled"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].Enabled);
|
||||
tmp = "Checked"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].Checked);
|
||||
tmp = "AutoChecking"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].AutoChecking);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIElement::deserializeAttributes(in,options);
|
||||
|
||||
Pos = in->getAttributeAsPosition2d("Position");
|
||||
|
||||
// link to this item's parent
|
||||
if (Parent && ( Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) )
|
||||
((CGUIContextMenu*)Parent)->setSubMenu(in->getAttributeAsInt("ParentItem"),this);
|
||||
|
||||
CloseHandling = (ECONTEXT_MENU_CLOSE)in->getAttributeAsInt("CloseHandling");
|
||||
|
||||
removeAllItems();
|
||||
|
||||
// read the item list
|
||||
const s32 count = in->getAttributeAsInt("ItemCount");
|
||||
|
||||
for (s32 i=0; i<count; ++i)
|
||||
{
|
||||
core::stringc tmp;
|
||||
core::stringw txt;
|
||||
s32 commandid=-1;
|
||||
bool enabled=true;
|
||||
bool checked=false;
|
||||
bool autochecking=false;
|
||||
|
||||
tmp = "IsSeparator"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) && in->getAttributeAsBool(tmp.c_str()) )
|
||||
addSeparator();
|
||||
else
|
||||
{
|
||||
tmp = "Text"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
txt = in->getAttributeAsStringW(tmp.c_str());
|
||||
|
||||
tmp = "CommandID"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
commandid = in->getAttributeAsInt(tmp.c_str());
|
||||
|
||||
tmp = "Enabled"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
enabled = in->getAttributeAsBool(tmp.c_str());
|
||||
|
||||
tmp = "Checked"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
checked = in->getAttributeAsBool(tmp.c_str());
|
||||
|
||||
tmp = "AutoChecking"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
autochecking = in->getAttributeAsBool(tmp.c_str());
|
||||
|
||||
addItem(core::stringw(txt.c_str()).c_str(), commandid, enabled, false, checked, autochecking);
|
||||
}
|
||||
}
|
||||
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
// because sometimes the element has no parent at click time
|
||||
void CGUIContextMenu::setEventParent(IGUIElement *parent)
|
||||
{
|
||||
EventParent = parent;
|
||||
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->setEventParent(parent);
|
||||
}
|
||||
|
||||
|
||||
bool CGUIContextMenu::hasOpenSubMenu() const
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu && Items[i].SubMenu->isVisible())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CGUIContextMenu::closeAllSubMenus()
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->setVisible(false);
|
||||
|
||||
//HighLighted = -1;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_CONTEXT_MENU_H_INCLUDED__
|
||||
#define __C_GUI_CONTEXT_MENU_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIContextMenu.h"
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
#include "IGUIFont.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! GUI Context menu interface.
|
||||
class CGUIContextMenu : public IGUIContextMenu
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIContextMenu(IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, core::rect<s32> rectangle,
|
||||
bool getFocus = true, bool allowFocus = true);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIContextMenu();
|
||||
|
||||
//! set behavior when menus are closed
|
||||
virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose);
|
||||
|
||||
//! get current behavior when the menue will be closed
|
||||
virtual ECONTEXT_MENU_CLOSE getCloseHandling() const;
|
||||
|
||||
//! Returns amount of menu items
|
||||
virtual u32 getItemCount() const;
|
||||
|
||||
//! Adds a menu item.
|
||||
virtual u32 addItem(const wchar_t* text, s32 commandid,
|
||||
bool enabled, bool hasSubMenu, bool checked, bool autoChecking);
|
||||
|
||||
//! Insert a menu item at specified position.
|
||||
virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled,
|
||||
bool hasSubMenu, bool checked, bool autoChecking);
|
||||
|
||||
//! Find a item which has the given CommandId starting from given index
|
||||
virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch) const;
|
||||
|
||||
//! Adds a separator item to the menu
|
||||
virtual void addSeparator();
|
||||
|
||||
//! Returns text of the menu item.
|
||||
virtual const wchar_t* getItemText(u32 idx) const;
|
||||
|
||||
//! Sets text of the menu item.
|
||||
virtual void setItemText(u32 idx, const wchar_t* text);
|
||||
|
||||
//! Returns if a menu item is enabled
|
||||
virtual bool isItemEnabled(u32 idx) const;
|
||||
|
||||
//! Sets if the menu item should be enabled.
|
||||
virtual void setItemEnabled(u32 idx, bool enabled);
|
||||
|
||||
//! Returns if a menu item is checked
|
||||
virtual bool isItemChecked(u32 idx) const;
|
||||
|
||||
//! Sets if the menu item should be checked.
|
||||
virtual void setItemChecked(u32 idx, bool enabled);
|
||||
|
||||
//! Removes a menu item
|
||||
virtual void removeItem(u32 idx);
|
||||
|
||||
//! Removes all menu items
|
||||
virtual void removeAllItems();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Returns the selected item in the menu
|
||||
virtual s32 getSelectedItem() const;
|
||||
|
||||
//! Returns a pointer to the submenu of an item.
|
||||
//! \return Pointer to the submenu of an item.
|
||||
virtual IGUIContextMenu* getSubMenu(u32 idx) const;
|
||||
|
||||
//! Sets the visible state of this element.
|
||||
virtual void setVisible(bool visible);
|
||||
|
||||
//! should the element change the checked status on clicking
|
||||
virtual void setItemAutoChecking(u32 idx, bool autoChecking);
|
||||
|
||||
//! does the element change the checked status on clicking
|
||||
virtual bool getItemAutoChecking(u32 idx) const;
|
||||
|
||||
//! Returns command id of a menu item
|
||||
virtual s32 getItemCommandId(u32 idx) const;
|
||||
|
||||
//! Sets the command id of a menu item
|
||||
virtual void setItemCommandId(u32 idx, s32 id);
|
||||
|
||||
//! Adds a sub menu from an element that already exists.
|
||||
virtual void setSubMenu(u32 index, CGUIContextMenu* menu);
|
||||
|
||||
//! When an eventparent is set it receives events instead of the usual parent element
|
||||
virtual void setEventParent(IGUIElement *parent);
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
protected:
|
||||
|
||||
void closeAllSubMenus();
|
||||
bool hasOpenSubMenu() const;
|
||||
|
||||
struct SItem
|
||||
{
|
||||
core::stringw Text;
|
||||
bool IsSeparator;
|
||||
bool Enabled;
|
||||
bool Checked;
|
||||
bool AutoChecking;
|
||||
core::dimension2d<u32> Dim;
|
||||
s32 PosY;
|
||||
CGUIContextMenu* SubMenu;
|
||||
s32 CommandId;
|
||||
};
|
||||
|
||||
virtual void recalculateSize();
|
||||
|
||||
//! returns true, if an element was highlighted
|
||||
virtual bool highlight(const core::position2d<s32>& p, bool canOpenSubMenu);
|
||||
|
||||
//! sends a click Returns:
|
||||
//! 0 if click went outside of the element,
|
||||
//! 1 if a valid button was clicked,
|
||||
//! 2 if a nonclickable element was clicked
|
||||
virtual u32 sendClick(const core::position2d<s32>& p);
|
||||
|
||||
//! returns the item highlight-area
|
||||
virtual core::rect<s32> getHRect(const SItem& i, const core::rect<s32>& absolute) const;
|
||||
|
||||
//! Gets drawing rect of Item
|
||||
virtual core::rect<s32> getRect(const SItem& i, const core::rect<s32>& absolute) const;
|
||||
|
||||
|
||||
core::array<SItem> Items;
|
||||
core::position2d<s32> Pos;
|
||||
IGUIElement* EventParent;
|
||||
IGUIFont *LastFont;
|
||||
ECONTEXT_MENU_CLOSE CloseHandling;
|
||||
s32 HighLighted;
|
||||
u32 ChangeTime;
|
||||
bool AllowFocus;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_CONTEXT_MENU_H_INCLUDED__
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,188 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_EDIT_BOX_H_INCLUDED__
|
||||
#define __C_GUI_EDIT_BOX_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEditBox.h"
|
||||
#include "irrArray.h"
|
||||
#include "IOSOperator.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class CGUIEditBox : public IGUIEditBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIEditBox();
|
||||
|
||||
//! Sets another skin independent font.
|
||||
virtual void setOverrideFont(IGUIFont* font=0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
/** \return The override font (may be 0) */
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
/** Currently this is the override font when one is set and the
|
||||
font of the active skin otherwise */
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets another color for the text.
|
||||
virtual void setOverrideColor(video::SColor color);
|
||||
|
||||
//! Gets the override color
|
||||
virtual video::SColor getOverrideColor() const;
|
||||
|
||||
//! Sets if the text should use the overide color or the
|
||||
//! color in the gui skin.
|
||||
virtual void enableOverrideColor(bool enable);
|
||||
|
||||
//! Checks if an override color is enabled
|
||||
/** \return true if the override color is enabled, false otherwise */
|
||||
virtual bool isOverrideColorEnabled(void) const;
|
||||
|
||||
//! Sets whether to draw the background
|
||||
virtual void setDrawBackground(bool draw);
|
||||
|
||||
//! Turns the border on or off
|
||||
virtual void setDrawBorder(bool border);
|
||||
|
||||
//! Enables or disables word wrap for using the edit box as multiline text editor.
|
||||
virtual void setWordWrap(bool enable);
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
//! \return true if word wrap is enabled, false otherwise
|
||||
virtual bool isWordWrapEnabled() const;
|
||||
|
||||
//! Enables or disables newlines.
|
||||
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
|
||||
instead a newline character will be inserted. */
|
||||
virtual void setMultiLine(bool enable);
|
||||
|
||||
//! Checks if multi line editing is enabled
|
||||
//! \return true if mult-line is enabled, false otherwise
|
||||
virtual bool isMultiLineEnabled() const;
|
||||
|
||||
//! Enables or disables automatic scrolling with cursor position
|
||||
//! \param enable: If set to true, the text will move around with the cursor position
|
||||
virtual void setAutoScroll(bool enable);
|
||||
|
||||
//! Checks to see if automatic scrolling is enabled
|
||||
//! \return true if automatic scrolling is enabled, false if not
|
||||
virtual bool isAutoScrollEnabled() const;
|
||||
|
||||
//! Gets the size area of the text in the edit box
|
||||
//! \return Returns the size in pixels of the text
|
||||
virtual core::dimension2du getTextDimension();
|
||||
|
||||
//! Sets text justification
|
||||
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical);
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Sets the new caption of this element.
|
||||
virtual void setText(const core::stringw& text);
|
||||
|
||||
//! Sets the maximum amount of characters which may be entered in the box.
|
||||
//! \param max: Maximum amount of characters. If 0, the character amount is
|
||||
//! infinity.
|
||||
virtual void setMax(u32 max);
|
||||
|
||||
//! Returns maximum amount of characters, previously set by setMax();
|
||||
virtual u32 getMax() const;
|
||||
|
||||
//! Sets whether the edit box is a password box. Setting this to true will
|
||||
/** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x
|
||||
\param passwordBox: true to enable password, false to disable
|
||||
\param passwordChar: the character that is displayed instead of letters */
|
||||
virtual void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*');
|
||||
|
||||
//! Returns true if the edit box is currently a password box.
|
||||
virtual bool isPasswordBox() const;
|
||||
|
||||
//! Updates the absolute position, splits text if required
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
virtual void setComposingText(const std::u32string& ct) {}
|
||||
virtual void clearComposingText() {}
|
||||
virtual const core::position2di& getICPos() const
|
||||
{
|
||||
static core::position2di unused;
|
||||
return unused;
|
||||
}
|
||||
protected:
|
||||
//! Breaks the single text line.
|
||||
void breakText();
|
||||
//! sets the area of the given line
|
||||
void setTextRect(s32 line);
|
||||
//! returns the line number that the cursor is on
|
||||
s32 getLineFromPos(s32 pos);
|
||||
//! adds a letter to the edit box
|
||||
void inputChar(wchar_t c);
|
||||
//! calculates the current scroll position
|
||||
void calculateScrollPos();
|
||||
//! calculated the FrameRect
|
||||
void calculateFrameRect();
|
||||
//! send some gui event to parent
|
||||
void sendGuiEvent(EGUI_EVENT_TYPE type);
|
||||
//! set text markers
|
||||
void setTextMarkers(s32 begin, s32 end);
|
||||
|
||||
bool processKey(const SEvent& event);
|
||||
bool processMouse(const SEvent& event);
|
||||
s32 getCursorPos(s32 x, s32 y);
|
||||
|
||||
bool MouseMarking;
|
||||
bool Border;
|
||||
bool Background;
|
||||
bool OverrideColorEnabled;
|
||||
s32 MarkBegin;
|
||||
s32 MarkEnd;
|
||||
|
||||
video::SColor OverrideColor;
|
||||
gui::IGUIFont *OverrideFont, *LastBreakFont;
|
||||
IOSOperator* Operator;
|
||||
|
||||
u32 BlinkStartTime;
|
||||
s32 CursorPos;
|
||||
s32 HScrollPos, VScrollPos; // scroll position in characters
|
||||
u32 Max;
|
||||
|
||||
bool WordWrap, MultiLine, AutoScroll, PasswordBox;
|
||||
wchar_t PasswordChar;
|
||||
EGUI_ALIGNMENT HAlign, VAlign;
|
||||
|
||||
core::array< core::stringw > BrokenText;
|
||||
core::array< s32 > BrokenTextPositions;
|
||||
|
||||
core::rect<s32> CurrentTextRect, FrameRect; // temporary values
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
#endif // __C_GUI_EDIT_BOX_H_INCLUDED__
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,322 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_ENVIRONMENT_H_INCLUDED__
|
||||
#define __C_GUI_ENVIRONMENT_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IGUIElement.h"
|
||||
#include "irrArray.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IOSOperator.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
class IXMLWriter;
|
||||
}
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIEnvironment : public IGUIEnvironment, public IGUIElement
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIEnvironment();
|
||||
|
||||
//! draws all gui elements
|
||||
virtual void drawAll();
|
||||
|
||||
//! returns the current video driver
|
||||
virtual video::IVideoDriver* getVideoDriver() const;
|
||||
|
||||
//! returns pointer to the filesystem
|
||||
virtual io::IFileSystem* getFileSystem() const;
|
||||
|
||||
//! returns a pointer to the OS operator
|
||||
virtual IOSOperator* getOSOperator() const;
|
||||
|
||||
//! posts an input event to the environment
|
||||
virtual bool postEventFromUser(const SEvent& event);
|
||||
|
||||
//! This sets a new event receiver for gui events. Usually you do not have to
|
||||
//! use this method, it is used by the internal engine.
|
||||
virtual void setUserEventReceiver(IEventReceiver* evr);
|
||||
|
||||
//! removes all elements from the environment
|
||||
virtual void clear();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! returns the current gui skin
|
||||
virtual IGUISkin* getSkin() const;
|
||||
|
||||
//! Sets a new GUI Skin
|
||||
virtual void setSkin(IGUISkin* skin);
|
||||
|
||||
//! Creates a new GUI Skin based on a template.
|
||||
/** \return Returns a pointer to the created skin.
|
||||
If you no longer need the skin, you should call IGUISkin::drop().
|
||||
See IReferenceCounted::drop() for more information. */
|
||||
virtual IGUISkin* createSkin(EGUI_SKIN_TYPE type);
|
||||
|
||||
//! Creates the image list from the given texture.
|
||||
virtual IGUIImageList* createImageList( video::ITexture* texture,
|
||||
core::dimension2d<s32> imageSize, bool useAlphaChannel );
|
||||
|
||||
//! returns the font
|
||||
virtual IGUIFont* getFont(const io::path& filename);
|
||||
|
||||
//! add an externally loaded font
|
||||
virtual IGUIFont* addFont(const io::path& name, IGUIFont* font);
|
||||
|
||||
//! remove loaded font
|
||||
virtual void removeFont(IGUIFont* font);
|
||||
|
||||
//! returns default font
|
||||
virtual IGUIFont* getBuiltInFont() const;
|
||||
|
||||
//! returns the sprite bank
|
||||
virtual IGUISpriteBank* getSpriteBank(const io::path& filename);
|
||||
|
||||
//! returns the sprite bank
|
||||
virtual IGUISpriteBank* addEmptySpriteBank(const io::path& name);
|
||||
|
||||
//! adds an button. The returned pointer must not be dropped.
|
||||
virtual IGUIButton* addButton(const core::rect<s32>& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0,const wchar_t* tooltiptext = 0);
|
||||
|
||||
//! adds a window. The returned pointer must not be dropped.
|
||||
virtual IGUIWindow* addWindow(const core::rect<s32>& rectangle, bool modal = false,
|
||||
const wchar_t* text=0, IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! adds a modal screen. The returned pointer must not be dropped.
|
||||
virtual IGUIElement* addModalScreen(IGUIElement* parent);
|
||||
|
||||
//! Adds a message box.
|
||||
virtual IGUIWindow* addMessageBox(const wchar_t* caption, const wchar_t* text=0,
|
||||
bool modal = true, s32 flag = EMBF_OK, IGUIElement* parent=0, s32 id=-1, video::ITexture* image=0);
|
||||
|
||||
//! adds a scrollbar. The returned pointer must not be dropped.
|
||||
virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds an image element.
|
||||
virtual IGUIImage* addImage(video::ITexture* image, core::position2d<s32> pos,
|
||||
bool useAlphaChannel=true, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0);
|
||||
|
||||
//! adds an image. The returned pointer must not be dropped.
|
||||
virtual IGUIImage* addImage(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0, bool useAlphaChannel=true);
|
||||
|
||||
//! adds a checkbox
|
||||
virtual IGUICheckBox* addCheckBox(bool checked, const core::rect<s32>& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0);
|
||||
|
||||
//! adds a list box
|
||||
virtual IGUIListBox* addListBox(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1, bool drawBackground=false);
|
||||
|
||||
//! adds a tree view
|
||||
virtual IGUITreeView* addTreeView(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1, bool drawBackground=false,
|
||||
bool scrollBarVertical = true, bool scrollBarHorizontal = false);
|
||||
|
||||
//! adds an mesh viewer. The returned pointer must not be dropped.
|
||||
virtual IGUIMeshViewer* addMeshViewer(const core::rect<s32>& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0);
|
||||
|
||||
//! Adds a file open dialog.
|
||||
virtual IGUIFileOpenDialog* addFileOpenDialog(const wchar_t* title = 0,
|
||||
bool modal=true, IGUIElement* parent=0, s32 id=-1,
|
||||
bool restoreCWD=false, io::path::char_type* startDir=0);
|
||||
|
||||
//! Adds a color select dialog.
|
||||
virtual IGUIColorSelectDialog* addColorSelectDialog(const wchar_t* title = 0, bool modal=true, IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! adds a static text. The returned pointer must not be dropped.
|
||||
virtual IGUIStaticText* addStaticText(const core::stringw& text, const core::rect<s32>& rectangle,
|
||||
bool border=false, bool wordWrap=true, IGUIElement* parent=0, s32 id=-1, bool drawBackground = false);
|
||||
|
||||
//! Adds an edit box. The returned pointer must not be dropped.
|
||||
virtual IGUIEditBox* addEditBox(const wchar_t* text, const core::rect<s32>& rectangle,
|
||||
bool border=false, IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a spin box to the environment
|
||||
virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect<s32>& rectangle,
|
||||
bool border=false,IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a tab control to the environment.
|
||||
virtual IGUITabControl* addTabControl(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, bool fillbackground=false, bool border=true, s32 id=-1);
|
||||
|
||||
//! Adds tab to the environment.
|
||||
virtual IGUITab* addTab(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a context menu to the environment.
|
||||
virtual IGUIContextMenu* addContextMenu(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a menu to the environment.
|
||||
virtual IGUIContextMenu* addMenu(IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a toolbar to the environment. It is like a menu is always placed on top
|
||||
//! in its parent, and contains buttons.
|
||||
virtual IGUIToolBar* addToolBar(IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a combo box to the environment.
|
||||
virtual IGUIComboBox* addComboBox(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a table element.
|
||||
virtual IGUITable* addTable(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1, bool drawBackground=false);
|
||||
|
||||
//! sets the focus to an element
|
||||
virtual bool setFocus(IGUIElement* element);
|
||||
|
||||
//! removes the focus from an element
|
||||
virtual bool removeFocus(IGUIElement* element);
|
||||
|
||||
//! Returns if the element has focus
|
||||
virtual bool hasFocus(IGUIElement* element) const;
|
||||
|
||||
//! Returns the element with the focus
|
||||
virtual IGUIElement* getFocus() const;
|
||||
|
||||
//! Returns the element last known to be under the mouse
|
||||
virtual IGUIElement* getHovered() const;
|
||||
|
||||
//! Adds an element for fading in or out.
|
||||
virtual IGUIInOutFader* addInOutFader(const core::rect<s32>* rectangle=0, IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Returns the root gui element.
|
||||
virtual IGUIElement* getRootGUIElement();
|
||||
|
||||
virtual void OnPostRender( u32 time );
|
||||
|
||||
//! Returns the default element factory which can create all built in elements
|
||||
virtual IGUIElementFactory* getDefaultGUIElementFactory() const;
|
||||
|
||||
//! Adds an element factory to the gui environment.
|
||||
/** Use this to extend the gui environment with new element types which it should be
|
||||
able to create automaticly, for example when loading data from xml files. */
|
||||
virtual void registerGUIElementFactory(IGUIElementFactory* factoryToAdd);
|
||||
|
||||
//! Returns amount of registered scene node factories.
|
||||
virtual u32 getRegisteredGUIElementFactoryCount() const;
|
||||
|
||||
//! Returns a scene node factory by index
|
||||
virtual IGUIElementFactory* getGUIElementFactory(u32 index) const;
|
||||
|
||||
//! Adds a GUI Element by its name
|
||||
virtual IGUIElement* addGUIElement(const c8* elementName, IGUIElement* parent=0);
|
||||
|
||||
//! Saves the current gui into a file.
|
||||
/** \param filename: Name of the file.
|
||||
\param start: The element to start saving from.
|
||||
if not specified, the root element will be used */
|
||||
virtual bool saveGUI( const io::path& filename, IGUIElement* start=0);
|
||||
|
||||
//! Saves the current gui into a file.
|
||||
/** \param file: The file to save the GUI to.
|
||||
\param start: The element to start saving from.
|
||||
if not specified, the root element will be used */
|
||||
virtual bool saveGUI(io::IWriteFile* file, IGUIElement* start=0);
|
||||
|
||||
//! Loads the gui. Note that the current gui is not cleared before.
|
||||
/** \param filename: Name of the file.
|
||||
\param parent: The parent of all loaded GUI elements,
|
||||
if not specified, the root element will be used */
|
||||
virtual bool loadGUI(const io::path& filename, IGUIElement* parent=0);
|
||||
|
||||
//! Loads the gui. Note that the current gui is not cleared before.
|
||||
/** \param file: IReadFile to load the GUI from
|
||||
\param parent: The parent of all loaded GUI elements,
|
||||
if not specified, the root element will be used */
|
||||
virtual bool loadGUI(io::IReadFile* file, IGUIElement* parent=0);
|
||||
|
||||
//! Writes attributes of the environment
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the environment.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! writes an element
|
||||
virtual void writeGUIElement(io::IXMLWriter* writer, IGUIElement* node);
|
||||
|
||||
//! reads an element
|
||||
virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* node);
|
||||
|
||||
virtual void removeHovered(IGUIElement* element);
|
||||
private:
|
||||
|
||||
IGUIElement* getNextElement(bool reverse=false, bool group=false);
|
||||
|
||||
void updateHoveredElement(core::position2d<s32> mousePos);
|
||||
|
||||
struct SFont
|
||||
{
|
||||
io::SNamedPath NamedPath;
|
||||
IGUIFont* Font;
|
||||
|
||||
bool operator < (const SFont& other) const
|
||||
{
|
||||
return (NamedPath < other.NamedPath);
|
||||
}
|
||||
};
|
||||
|
||||
struct SSpriteBank
|
||||
{
|
||||
io::SNamedPath NamedPath;
|
||||
IGUISpriteBank* Bank;
|
||||
|
||||
bool operator < (const SSpriteBank& other) const
|
||||
{
|
||||
return (NamedPath < other.NamedPath);
|
||||
}
|
||||
};
|
||||
|
||||
struct SToolTip
|
||||
{
|
||||
IGUIStaticText* Element;
|
||||
u32 LastTime;
|
||||
u32 EnterTime;
|
||||
u32 LaunchTime;
|
||||
u32 RelaunchTime;
|
||||
};
|
||||
|
||||
SToolTip ToolTip;
|
||||
|
||||
core::array<IGUIElementFactory*> GUIElementFactoryList;
|
||||
|
||||
core::array<SFont> Fonts;
|
||||
core::array<SSpriteBank> Banks;
|
||||
video::IVideoDriver* Driver;
|
||||
IGUIElement* Hovered;
|
||||
IGUIElement* HoveredNoSubelement; // subelements replaced by their parent, so you only have 'real' elements here
|
||||
IGUIElement* Focus;
|
||||
core::position2d<s32> LastHoveredMousePos;
|
||||
IGUISkin* CurrentSkin;
|
||||
io::IFileSystem* FileSystem;
|
||||
IEventReceiver* UserReceiver;
|
||||
IOSOperator* Operator;
|
||||
static const io::path DefaultFontName;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_ENVIRONMENT_H_INCLUDED__
|
||||
|
||||
|
||||
@@ -0,0 +1,446 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIFileOpenDialog.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUIFontBitmap.h"
|
||||
#include "IFileList.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
const s32 FOD_WIDTH = 350;
|
||||
const s32 FOD_HEIGHT = 250;
|
||||
|
||||
|
||||
//! constructor
|
||||
CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title,
|
||||
IGUIEnvironment* environment, IGUIElement* parent, s32 id,
|
||||
bool restoreCWD, io::path::char_type* startDir)
|
||||
: IGUIFileOpenDialog(environment, parent, id,
|
||||
core::rect<s32>((parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2,
|
||||
(parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2,
|
||||
(parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2+FOD_WIDTH,
|
||||
(parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2+FOD_HEIGHT)),
|
||||
FileNameText(0), FileList(0), Dragging(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
IGUIElement::setDebugName("CGUIFileOpenDialog");
|
||||
#endif
|
||||
|
||||
Text = title;
|
||||
|
||||
FileSystem = Environment?Environment->getFileSystem():0;
|
||||
|
||||
if (FileSystem)
|
||||
{
|
||||
FileSystem->grab();
|
||||
|
||||
if (restoreCWD)
|
||||
RestoreDirectory = FileSystem->getWorkingDirectory();
|
||||
if (startDir)
|
||||
{
|
||||
StartDirectory = startDir;
|
||||
FileSystem->changeWorkingDirectoryTo(startDir);
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
IGUISpriteBank* sprites = 0;
|
||||
video::SColor color(255,255,255,255);
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
{
|
||||
sprites = skin->getSpriteBank();
|
||||
color = skin->getColor(EGDC_WINDOW_SYMBOL);
|
||||
}
|
||||
|
||||
const s32 buttonw = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
|
||||
const s32 posx = RelativeRect.getWidth() - buttonw - 4;
|
||||
|
||||
CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
|
||||
L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close");
|
||||
CloseButton->setSubElement(true);
|
||||
CloseButton->setTabStop(false);
|
||||
if (sprites)
|
||||
{
|
||||
CloseButton->setSpriteBank(sprites);
|
||||
CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), color);
|
||||
CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), color);
|
||||
}
|
||||
CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
CloseButton->grab();
|
||||
|
||||
OKButton = Environment->addButton(
|
||||
core::rect<s32>(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50),
|
||||
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK");
|
||||
OKButton->setSubElement(true);
|
||||
OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
OKButton->grab();
|
||||
|
||||
CancelButton = Environment->addButton(
|
||||
core::rect<s32>(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75),
|
||||
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel");
|
||||
CancelButton->setSubElement(true);
|
||||
CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
CancelButton->grab();
|
||||
|
||||
FileBox = Environment->addListBox(core::rect<s32>(10, 55, RelativeRect.getWidth()-90, 230), this, -1, true);
|
||||
FileBox->setSubElement(true);
|
||||
FileBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
FileBox->grab();
|
||||
|
||||
FileNameText = Environment->addEditBox(0, core::rect<s32>(10, 30, RelativeRect.getWidth()-90, 50), true, this);
|
||||
FileNameText->setSubElement(true);
|
||||
FileNameText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
FileNameText->grab();
|
||||
|
||||
setTabGroup(true);
|
||||
|
||||
fillListBox();
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIFileOpenDialog::~CGUIFileOpenDialog()
|
||||
{
|
||||
if (CloseButton)
|
||||
CloseButton->drop();
|
||||
|
||||
if (OKButton)
|
||||
OKButton->drop();
|
||||
|
||||
if (CancelButton)
|
||||
CancelButton->drop();
|
||||
|
||||
if (FileBox)
|
||||
FileBox->drop();
|
||||
|
||||
if (FileNameText)
|
||||
FileNameText->drop();
|
||||
|
||||
if (FileSystem)
|
||||
{
|
||||
// revert to original CWD if path was set in constructor
|
||||
if (RestoreDirectory.size())
|
||||
FileSystem->changeWorkingDirectoryTo(RestoreDirectory);
|
||||
FileSystem->drop();
|
||||
}
|
||||
|
||||
if (FileList)
|
||||
FileList->drop();
|
||||
}
|
||||
|
||||
|
||||
//! returns the filename of the selected file. Returns NULL, if no file was selected.
|
||||
const wchar_t* CGUIFileOpenDialog::getFileName() const
|
||||
{
|
||||
return FileName.c_str();
|
||||
}
|
||||
|
||||
//! Returns the directory of the selected file. Returns NULL, if no directory was selected.
|
||||
const io::path& CGUIFileOpenDialog::getDirectoryName()
|
||||
{
|
||||
FileSystem->flattenFilename ( FileDirectory );
|
||||
return FileDirectory;
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIFileOpenDialog::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
Dragging = false;
|
||||
break;
|
||||
case EGET_BUTTON_CLICKED:
|
||||
if (event.GUIEvent.Caller == CloseButton ||
|
||||
event.GUIEvent.Caller == CancelButton)
|
||||
{
|
||||
sendCancelEvent();
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.Caller == OKButton )
|
||||
{
|
||||
if ( FileDirectory != L"" )
|
||||
{
|
||||
sendSelectedEvent( EGET_DIRECTORY_SELECTED );
|
||||
}
|
||||
if ( FileName != L"" )
|
||||
{
|
||||
sendSelectedEvent( EGET_FILE_SELECTED );
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EGET_LISTBOX_CHANGED:
|
||||
{
|
||||
s32 selected = FileBox->getSelected();
|
||||
if (FileList && FileSystem)
|
||||
{
|
||||
if (FileList->isDirectory(selected))
|
||||
{
|
||||
FileName = L"";
|
||||
FileDirectory = FileList->getFullFileName(selected);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileDirectory = L"";
|
||||
FileName = FileList->getFullFileName(selected);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EGET_LISTBOX_SELECTED_AGAIN:
|
||||
{
|
||||
const s32 selected = FileBox->getSelected();
|
||||
if (FileList && FileSystem)
|
||||
{
|
||||
if (FileList->isDirectory(selected))
|
||||
{
|
||||
FileDirectory = FileList->getFullFileName(selected);
|
||||
FileSystem->changeWorkingDirectoryTo(FileList->getFileName(selected));
|
||||
fillListBox();
|
||||
FileName = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
FileName = FileList->getFullFileName(selected);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EGET_EDITBOX_ENTER:
|
||||
if (event.GUIEvent.Caller == FileNameText)
|
||||
{
|
||||
io::path dir( FileNameText->getText () );
|
||||
if ( FileSystem->changeWorkingDirectoryTo( dir ) )
|
||||
{
|
||||
fillListBox();
|
||||
FileName = L"";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
return FileBox->OnEvent(event);
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
Dragging = true;
|
||||
Environment->setFocus(this);
|
||||
return true;
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
Dragging = false;
|
||||
return true;
|
||||
case EMIE_MOUSE_MOVED:
|
||||
|
||||
if ( !event.MouseInput.isLeftPressed () )
|
||||
Dragging = false;
|
||||
|
||||
if (Dragging)
|
||||
{
|
||||
// gui window should not be dragged outside its parent
|
||||
if (Parent)
|
||||
if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||
|
||||
event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||
|
||||
event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||
|
||||
event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1)
|
||||
|
||||
return true;
|
||||
|
||||
move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIFileOpenDialog::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
|
||||
rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
|
||||
rect, &AbsoluteClippingRect);
|
||||
|
||||
if (Text.size())
|
||||
{
|
||||
rect.UpperLeftCorner.X += 2;
|
||||
rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;
|
||||
|
||||
IGUIFont* font = skin->getFont(EGDF_WINDOW);
|
||||
if (font)
|
||||
font->draw(Text.c_str(), rect,
|
||||
skin->getColor(EGDC_ACTIVE_CAPTION),
|
||||
false, true, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
/* Not sure if this will really work out properly. Saving paths can be
|
||||
rather problematic. */
|
||||
void CGUIFileOpenDialog::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
IGUIFileOpenDialog::serializeAttributes(out,options);
|
||||
|
||||
out->addString("StartDirectory", StartDirectory.c_str());
|
||||
out->addBool("RestoreDirectory", (RestoreDirectory.size()!=0));
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
/* Note that thiese paths changes will happen at arbitrary places upon
|
||||
load of the gui description. This may be undesired. */
|
||||
void CGUIFileOpenDialog::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
StartDirectory = in->getAttributeAsString("StartDirectory");
|
||||
const bool restore = in->getAttributeAsBool("RestoreDirectory");
|
||||
if (restore)
|
||||
RestoreDirectory = FileSystem->getWorkingDirectory();
|
||||
else
|
||||
RestoreDirectory = "";
|
||||
if (StartDirectory.size())
|
||||
FileSystem->changeWorkingDirectoryTo(StartDirectory);
|
||||
|
||||
IGUIFileOpenDialog::deserializeAttributes(in,options);
|
||||
}
|
||||
|
||||
|
||||
//! fills the listbox with files.
|
||||
void CGUIFileOpenDialog::fillListBox()
|
||||
{
|
||||
IGUISkin *skin = Environment->getSkin();
|
||||
|
||||
if (!FileSystem || !FileBox || !skin)
|
||||
return;
|
||||
|
||||
if (FileList)
|
||||
FileList->drop();
|
||||
|
||||
FileBox->clear();
|
||||
|
||||
FileList = FileSystem->createFileList();
|
||||
core::stringw s;
|
||||
|
||||
#if !defined(_IRR_WINDOWS_CE_PLATFORM_)
|
||||
setlocale(LC_ALL,"");
|
||||
#endif
|
||||
|
||||
if (FileList)
|
||||
{
|
||||
for (u32 i=0; i < FileList->getFileCount(); ++i)
|
||||
{
|
||||
#ifndef _IRR_WCHAR_FILESYSTEM
|
||||
const c8 *cs = (const c8 *)FileList->getFileName(i).c_str();
|
||||
wchar_t *ws = new wchar_t[strlen(cs) + 1];
|
||||
int len = mbstowcs(ws,cs,strlen(cs));
|
||||
ws[len] = 0;
|
||||
s = ws;
|
||||
delete [] ws;
|
||||
#else
|
||||
s = FileList->getFileName(i).c_str();
|
||||
#endif
|
||||
FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE));
|
||||
}
|
||||
}
|
||||
|
||||
if (FileNameText)
|
||||
{
|
||||
#ifndef _IRR_WCHAR_FILESYSTEM
|
||||
const c8 *cs = (const c8 *)FileSystem->getWorkingDirectory().c_str();
|
||||
wchar_t *ws = new wchar_t[strlen(cs) + 1];
|
||||
int len = mbstowcs(ws,cs,strlen(cs));
|
||||
ws[len] = 0;
|
||||
s = ws;
|
||||
delete [] ws;
|
||||
#else
|
||||
s = FileSystem->getWorkingDirectory();
|
||||
#endif
|
||||
|
||||
FileDirectory = s;
|
||||
FileNameText->setText(s.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void CGUIFileOpenDialog::sendSelectedEvent( EGUI_EVENT_TYPE type)
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = type;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! sends the event that the file choose process has been canceld
|
||||
void CGUIFileOpenDialog::sendCancelEvent()
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
@@ -0,0 +1,84 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_FILE_OPEN_DIALOG_H_INCLUDED__
|
||||
#define __C_GUI_FILE_OPEN_DIALOG_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIFileOpenDialog.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIListBox.h"
|
||||
#include "IGUIEditBox.h"
|
||||
#include "IFileSystem.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIFileOpenDialog : public IGUIFileOpenDialog
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIFileOpenDialog(const wchar_t* title, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, bool restoreCWD=false,
|
||||
io::path::char_type* startDir=0);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIFileOpenDialog();
|
||||
|
||||
//! returns the filename of the selected file. Returns NULL, if no file was selected.
|
||||
virtual const wchar_t* getFileName() const;
|
||||
|
||||
//! Returns the directory of the selected file. Returns NULL, if no directory was selected.
|
||||
virtual const io::path& getDirectoryName();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
protected:
|
||||
|
||||
//! fills the listbox with files.
|
||||
void fillListBox();
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void sendSelectedEvent( EGUI_EVENT_TYPE type );
|
||||
|
||||
//! sends the event that the file choose process has been canceld
|
||||
void sendCancelEvent();
|
||||
|
||||
core::position2d<s32> DragStart;
|
||||
core::stringw FileName;
|
||||
io::path FileDirectory;
|
||||
io::path RestoreDirectory;
|
||||
io::path StartDirectory;
|
||||
|
||||
IGUIButton* CloseButton;
|
||||
IGUIButton* OKButton;
|
||||
IGUIButton* CancelButton;
|
||||
IGUIListBox* FileBox;
|
||||
IGUIEditBox* FileNameText;
|
||||
IGUIElement* EventParent;
|
||||
io::IFileSystem* FileSystem;
|
||||
io::IFileList* FileList;
|
||||
bool Dragging;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_FILE_OPEN_DIALOG_H_INCLUDED__
|
||||
|
||||
@@ -0,0 +1,589 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIFont.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "os.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IXMLReader.h"
|
||||
#include "IReadFile.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIFont::CGUIFont(IGUIEnvironment *env, const io::path& filename)
|
||||
: Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
|
||||
MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIFont");
|
||||
#endif
|
||||
|
||||
if (Environment)
|
||||
{
|
||||
// don't grab environment, to avoid circular references
|
||||
Driver = Environment->getVideoDriver();
|
||||
|
||||
SpriteBank = Environment->getSpriteBank(filename);
|
||||
if (!SpriteBank) // could be default-font which has no file
|
||||
SpriteBank = Environment->addEmptySpriteBank(filename);
|
||||
if (SpriteBank)
|
||||
SpriteBank->grab();
|
||||
}
|
||||
|
||||
if (Driver)
|
||||
Driver->grab();
|
||||
|
||||
setInvisibleCharacters ( L" " );
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIFont::~CGUIFont()
|
||||
{
|
||||
if (Driver)
|
||||
Driver->drop();
|
||||
|
||||
if (SpriteBank)
|
||||
{
|
||||
SpriteBank->drop();
|
||||
// TODO: spritebank still exists in gui-environment and should be removed here when it's
|
||||
// reference-count is 1. Just can't do that from here at the moment.
|
||||
// But spritebank would not be able to drop textures anyway because those are in texture-cache
|
||||
// where they can't be removed unless materials start reference-couting 'em.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! loads a font file from xml
|
||||
bool CGUIFont::load(io::IXMLReader* xml)
|
||||
{
|
||||
if (!SpriteBank)
|
||||
return false;
|
||||
|
||||
SpriteBank->clear();
|
||||
|
||||
while (xml->read())
|
||||
{
|
||||
if (io::EXN_ELEMENT == xml->getNodeType())
|
||||
{
|
||||
if (core::stringw(L"Texture") == xml->getNodeName())
|
||||
{
|
||||
// add a texture
|
||||
core::stringc fn = xml->getAttributeValue(L"filename");
|
||||
u32 i = (u32)xml->getAttributeValueAsInt(L"index");
|
||||
core::stringw alpha = xml->getAttributeValue(L"hasAlpha");
|
||||
|
||||
while (i+1 > SpriteBank->getTextureCount())
|
||||
SpriteBank->addTexture(0);
|
||||
|
||||
// disable mipmaps+filtering
|
||||
bool mipmap = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
|
||||
|
||||
// load texture
|
||||
SpriteBank->setTexture(i, Driver->getTexture(fn));
|
||||
|
||||
// set previous mip-map+filter state
|
||||
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap);
|
||||
|
||||
// couldn't load texture, abort.
|
||||
if (!SpriteBank->getTexture(i))
|
||||
{
|
||||
os::Printer::log("Unable to load all textures in the font, aborting", ELL_ERROR);
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// colorkey texture rather than alpha channel?
|
||||
if (alpha == core::stringw("false"))
|
||||
Driver->makeColorKeyTexture(SpriteBank->getTexture(i), core::position2di(0,0));
|
||||
}
|
||||
}
|
||||
else if (core::stringw(L"c") == xml->getNodeName())
|
||||
{
|
||||
// adding a character to this font
|
||||
SFontArea a;
|
||||
SGUISpriteFrame f;
|
||||
SGUISprite s;
|
||||
core::rect<s32> rectangle;
|
||||
|
||||
a.underhang = xml->getAttributeValueAsInt(L"u");
|
||||
a.overhang = xml->getAttributeValueAsInt(L"o");
|
||||
a.spriteno = SpriteBank->getSprites().size();
|
||||
s32 texno = xml->getAttributeValueAsInt(L"i");
|
||||
|
||||
// parse rectangle
|
||||
core::stringc rectstr = xml->getAttributeValue(L"r");
|
||||
wchar_t ch = xml->getAttributeValue(L"c")[0];
|
||||
|
||||
const c8 *c = rectstr.c_str();
|
||||
s32 val;
|
||||
val = 0;
|
||||
while (*c >= '0' && *c <= '9')
|
||||
{
|
||||
val *= 10;
|
||||
val += *c - '0';
|
||||
c++;
|
||||
}
|
||||
rectangle.UpperLeftCorner.X = val;
|
||||
while (*c == L' ' || *c == L',') c++;
|
||||
|
||||
val = 0;
|
||||
while (*c >= '0' && *c <= '9')
|
||||
{
|
||||
val *= 10;
|
||||
val += *c - '0';
|
||||
c++;
|
||||
}
|
||||
rectangle.UpperLeftCorner.Y = val;
|
||||
while (*c == L' ' || *c == L',') c++;
|
||||
|
||||
val = 0;
|
||||
while (*c >= '0' && *c <= '9')
|
||||
{
|
||||
val *= 10;
|
||||
val += *c - '0';
|
||||
c++;
|
||||
}
|
||||
rectangle.LowerRightCorner.X = val;
|
||||
while (*c == L' ' || *c == L',') c++;
|
||||
|
||||
val = 0;
|
||||
while (*c >= '0' && *c <= '9')
|
||||
{
|
||||
val *= 10;
|
||||
val += *c - '0';
|
||||
c++;
|
||||
}
|
||||
rectangle.LowerRightCorner.Y = val;
|
||||
|
||||
CharacterMap.insert(ch,Areas.size());
|
||||
|
||||
// make frame
|
||||
f.rectNumber = SpriteBank->getPositions().size();
|
||||
f.textureNumber = texno;
|
||||
|
||||
// add frame to sprite
|
||||
s.Frames.push_back(f);
|
||||
s.frameTime = 0;
|
||||
|
||||
// add rectangle to sprite bank
|
||||
SpriteBank->getPositions().push_back(rectangle);
|
||||
a.width = rectangle.getWidth();
|
||||
|
||||
// add sprite to sprite bank
|
||||
SpriteBank->getSprites().push_back(s);
|
||||
|
||||
// add character to font
|
||||
Areas.push_back(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set bad character
|
||||
WrongCharacter = getAreaFromCharacter(L' ');
|
||||
|
||||
setMaxHeight();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CGUIFont::setMaxHeight()
|
||||
{
|
||||
if ( !SpriteBank )
|
||||
return;
|
||||
|
||||
MaxHeight = 0;
|
||||
s32 t;
|
||||
|
||||
core::array< core::rect<s32> >& p = SpriteBank->getPositions();
|
||||
|
||||
for (u32 i=0; i<p.size(); ++i)
|
||||
{
|
||||
t = p[i].getHeight();
|
||||
if (t>MaxHeight)
|
||||
MaxHeight = t;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! loads a font file, native file needed, for texture parsing
|
||||
bool CGUIFont::load(io::IReadFile* file)
|
||||
{
|
||||
if (!Driver)
|
||||
return false;
|
||||
|
||||
return loadTexture(Driver->createImageFromFile(file),
|
||||
file->getFileName());
|
||||
}
|
||||
|
||||
|
||||
//! loads a font file, native file needed, for texture parsing
|
||||
bool CGUIFont::load(const io::path& filename)
|
||||
{
|
||||
if (!Driver)
|
||||
return false;
|
||||
|
||||
return loadTexture(Driver->createImageFromFile( filename ),
|
||||
filename);
|
||||
}
|
||||
|
||||
|
||||
//! load & prepare font from ITexture
|
||||
bool CGUIFont::loadTexture(video::IImage* image, const io::path& name)
|
||||
{
|
||||
if (!image || !SpriteBank)
|
||||
return false;
|
||||
|
||||
s32 lowerRightPositions = 0;
|
||||
|
||||
video::IImage* tmpImage=image;
|
||||
bool deleteTmpImage=false;
|
||||
switch(image->getColorFormat())
|
||||
{
|
||||
case video::ECF_R5G6B5:
|
||||
tmpImage = Driver->createImage(video::ECF_A1R5G5B5,image->getDimension());
|
||||
image->copyTo(tmpImage);
|
||||
deleteTmpImage=true;
|
||||
break;
|
||||
case video::ECF_A1R5G5B5:
|
||||
case video::ECF_A8R8G8B8:
|
||||
break;
|
||||
case video::ECF_R8G8B8:
|
||||
tmpImage = Driver->createImage(video::ECF_A8R8G8B8,image->getDimension());
|
||||
image->copyTo(tmpImage);
|
||||
deleteTmpImage=true;
|
||||
break;
|
||||
default:
|
||||
os::Printer::log("Unknown texture format provided for CGUIFont::loadTexture", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
readPositions(tmpImage, lowerRightPositions);
|
||||
|
||||
WrongCharacter = getAreaFromCharacter(L' ');
|
||||
|
||||
// output warnings
|
||||
if (!lowerRightPositions || !SpriteBank->getSprites().size())
|
||||
os::Printer::log("Either no upper or lower corner pixels in the font file. If this font was made using the new font tool, please load the XML file instead. If not, the font may be corrupted.", ELL_ERROR);
|
||||
else
|
||||
if (lowerRightPositions != (s32)SpriteBank->getPositions().size())
|
||||
os::Printer::log("The amount of upper corner pixels and the lower corner pixels is not equal, font file may be corrupted.", ELL_ERROR);
|
||||
|
||||
bool ret = ( !SpriteBank->getSprites().empty() && lowerRightPositions );
|
||||
|
||||
if ( ret )
|
||||
{
|
||||
bool flag[2];
|
||||
flag[0] = Driver->getTextureCreationFlag ( video::ETCF_ALLOW_NON_POWER_2 );
|
||||
flag[1] = Driver->getTextureCreationFlag ( video::ETCF_CREATE_MIP_MAPS );
|
||||
|
||||
Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, true);
|
||||
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false );
|
||||
|
||||
SpriteBank->addTexture(Driver->addTexture(name, tmpImage));
|
||||
|
||||
Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, flag[0] );
|
||||
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, flag[1] );
|
||||
}
|
||||
if (deleteTmpImage)
|
||||
tmpImage->drop();
|
||||
image->drop();
|
||||
|
||||
setMaxHeight();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void CGUIFont::readPositions(video::IImage* image, s32& lowerRightPositions)
|
||||
{
|
||||
if (!SpriteBank )
|
||||
return;
|
||||
|
||||
const core::dimension2d<u32> size = image->getDimension();
|
||||
|
||||
video::SColor colorTopLeft = image->getPixel(0,0);
|
||||
colorTopLeft.setAlpha(255);
|
||||
image->setPixel(0,0,colorTopLeft);
|
||||
video::SColor colorLowerRight = image->getPixel(1,0);
|
||||
video::SColor colorBackGround = image->getPixel(2,0);
|
||||
video::SColor colorBackGroundTransparent = 0;
|
||||
|
||||
image->setPixel(1,0,colorBackGround);
|
||||
|
||||
// start parsing
|
||||
|
||||
core::position2d<s32> pos(0,0);
|
||||
for (pos.Y=0; pos.Y<(s32)size.Height; ++pos.Y)
|
||||
{
|
||||
for (pos.X=0; pos.X<(s32)size.Width; ++pos.X)
|
||||
{
|
||||
const video::SColor c = image->getPixel(pos.X, pos.Y);
|
||||
if (c == colorTopLeft)
|
||||
{
|
||||
image->setPixel(pos.X, pos.Y, colorBackGroundTransparent);
|
||||
SpriteBank->getPositions().push_back(core::rect<s32>(pos, pos));
|
||||
}
|
||||
else
|
||||
if (c == colorLowerRight)
|
||||
{
|
||||
// too many lower right points
|
||||
if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions)
|
||||
{
|
||||
lowerRightPositions = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
image->setPixel(pos.X, pos.Y, colorBackGroundTransparent);
|
||||
SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos;
|
||||
// add frame to sprite bank
|
||||
SGUISpriteFrame f;
|
||||
f.rectNumber = lowerRightPositions;
|
||||
f.textureNumber = 0;
|
||||
SGUISprite s;
|
||||
s.Frames.push_back(f);
|
||||
s.frameTime = 0;
|
||||
SpriteBank->getSprites().push_back(s);
|
||||
// add character to font
|
||||
SFontArea a;
|
||||
a.overhang = 0;
|
||||
a.underhang = 0;
|
||||
a.spriteno = lowerRightPositions;
|
||||
a.width = SpriteBank->getPositions()[lowerRightPositions].getWidth();
|
||||
Areas.push_back(a);
|
||||
// map letter to character
|
||||
wchar_t ch = (wchar_t)(lowerRightPositions + 32);
|
||||
CharacterMap.set(ch, lowerRightPositions);
|
||||
|
||||
++lowerRightPositions;
|
||||
}
|
||||
else
|
||||
if (c == colorBackGround)
|
||||
image->setPixel(pos.X, pos.Y, colorBackGroundTransparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
||||
void CGUIFont::setKerningWidth(s32 kerning)
|
||||
{
|
||||
GlobalKerningWidth = kerning;
|
||||
}
|
||||
|
||||
|
||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
||||
s32 CGUIFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const
|
||||
{
|
||||
s32 ret = GlobalKerningWidth;
|
||||
|
||||
if (thisLetter)
|
||||
{
|
||||
ret += Areas[getAreaFromCharacter(*thisLetter)].overhang;
|
||||
|
||||
if (previousLetter)
|
||||
{
|
||||
ret += Areas[getAreaFromCharacter(*previousLetter)].underhang;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//! set an Pixel Offset on Drawing ( scale position on height )
|
||||
void CGUIFont::setKerningHeight(s32 kerning)
|
||||
{
|
||||
GlobalKerningHeight = kerning;
|
||||
}
|
||||
|
||||
|
||||
//! set an Pixel Offset on Drawing ( scale position on height )
|
||||
s32 CGUIFont::getKerningHeight () const
|
||||
{
|
||||
return GlobalKerningHeight;
|
||||
}
|
||||
|
||||
|
||||
//! returns the sprite number from a given character
|
||||
u32 CGUIFont::getSpriteNoFromChar(const wchar_t *c) const
|
||||
{
|
||||
return Areas[getAreaFromCharacter(*c)].spriteno;
|
||||
}
|
||||
|
||||
|
||||
s32 CGUIFont::getAreaFromCharacter(const wchar_t c) const
|
||||
{
|
||||
core::map<wchar_t, s32>::Node* n = CharacterMap.find(c);
|
||||
if (n)
|
||||
return n->getValue();
|
||||
else
|
||||
return WrongCharacter;
|
||||
}
|
||||
|
||||
void CGUIFont::setInvisibleCharacters( const wchar_t *s )
|
||||
{
|
||||
Invisible = s;
|
||||
}
|
||||
|
||||
|
||||
//! returns the dimension of text
|
||||
core::dimension2d<u32> CGUIFont::getDimension(const wchar_t* text) const
|
||||
{
|
||||
core::dimension2d<u32> dim(0, 0);
|
||||
core::dimension2d<u32> thisLine(0, MaxHeight);
|
||||
|
||||
for (const wchar_t* p = text; *p; ++p)
|
||||
{
|
||||
bool lineBreak=false;
|
||||
if (*p == L'\r') // Mac or Windows breaks
|
||||
{
|
||||
lineBreak = true;
|
||||
if (p[1] == L'\n') // Windows breaks
|
||||
++p;
|
||||
}
|
||||
else if (*p == L'\n') // Unix breaks
|
||||
{
|
||||
lineBreak = true;
|
||||
}
|
||||
if (lineBreak)
|
||||
{
|
||||
dim.Height += thisLine.Height;
|
||||
if (dim.Width < thisLine.Width)
|
||||
dim.Width = thisLine.Width;
|
||||
thisLine.Width = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
const SFontArea &area = Areas[getAreaFromCharacter(*p)];
|
||||
|
||||
thisLine.Width += area.underhang;
|
||||
thisLine.Width += area.width + area.overhang + GlobalKerningWidth;
|
||||
}
|
||||
|
||||
dim.Height += thisLine.Height;
|
||||
if (dim.Width < thisLine.Width)
|
||||
dim.Width = thisLine.Width;
|
||||
|
||||
return dim;
|
||||
}
|
||||
|
||||
//! draws some text and clips it to the specified rectangle if wanted
|
||||
void CGUIFont::draw(const core::stringw& text, const core::rect<s32>& position,
|
||||
video::SColor color,
|
||||
bool hcenter, bool vcenter, const core::rect<s32>* clip
|
||||
)
|
||||
{
|
||||
if (!Driver || !SpriteBank)
|
||||
return;
|
||||
|
||||
core::dimension2d<s32> textDimension; // NOTE: don't make this u32 or the >> later on can fail when the dimension width is < position width
|
||||
core::position2d<s32> offset = position.UpperLeftCorner;
|
||||
|
||||
if (hcenter || vcenter || clip)
|
||||
textDimension = getDimension(text.c_str());
|
||||
|
||||
if (hcenter)
|
||||
offset.X += (position.getWidth() - textDimension.Width) >> 1;
|
||||
|
||||
if (vcenter)
|
||||
offset.Y += (position.getHeight() - textDimension.Height) >> 1;
|
||||
|
||||
if (clip)
|
||||
{
|
||||
core::rect<s32> clippedRect(offset, textDimension);
|
||||
clippedRect.clipAgainst(*clip);
|
||||
if (!clippedRect.isValid())
|
||||
return;
|
||||
}
|
||||
|
||||
core::array<u32> indices(text.size());
|
||||
core::array<core::position2di> offsets(text.size());
|
||||
|
||||
for(u32 i = 0;i < text.size();i++)
|
||||
{
|
||||
wchar_t c = text[i];
|
||||
|
||||
bool lineBreak=false;
|
||||
if ( c == L'\r') // Mac or Windows breaks
|
||||
{
|
||||
lineBreak = true;
|
||||
if ( text[i + 1] == L'\n') // Windows breaks
|
||||
c = text[++i];
|
||||
}
|
||||
else if ( c == L'\n') // Unix breaks
|
||||
{
|
||||
lineBreak = true;
|
||||
}
|
||||
|
||||
if (lineBreak)
|
||||
{
|
||||
offset.Y += MaxHeight;
|
||||
offset.X = position.UpperLeftCorner.X;
|
||||
|
||||
if ( hcenter )
|
||||
{
|
||||
offset.X += (position.getWidth() - textDimension.Width) >> 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
SFontArea& area = Areas[getAreaFromCharacter(c)];
|
||||
|
||||
offset.X += area.underhang;
|
||||
if ( Invisible.findFirst ( c ) < 0 )
|
||||
{
|
||||
indices.push_back(area.spriteno);
|
||||
offsets.push_back(offset);
|
||||
}
|
||||
|
||||
offset.X += area.width + area.overhang + GlobalKerningWidth;
|
||||
}
|
||||
|
||||
SpriteBank->draw2DSpriteBatch(indices, offsets, clip, color);
|
||||
}
|
||||
|
||||
|
||||
//! Calculates the index of the character in the text which is on a specific position.
|
||||
s32 CGUIFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
|
||||
{
|
||||
s32 x = 0;
|
||||
s32 idx = 0;
|
||||
|
||||
while (text[idx])
|
||||
{
|
||||
const SFontArea& a = Areas[getAreaFromCharacter(text[idx])];
|
||||
|
||||
x += a.width + a.overhang + a.underhang + GlobalKerningWidth;
|
||||
|
||||
if (x >= pixel_x)
|
||||
return idx;
|
||||
|
||||
++idx;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
IGUISpriteBank* CGUIFont::getSpriteBank() const
|
||||
{
|
||||
return SpriteBank;
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_FONT_H_INCLUDED__
|
||||
#define __C_GUI_FONT_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIFontBitmap.h"
|
||||
#include "irrString.h"
|
||||
#include "irrMap.h"
|
||||
#include "IXMLReader.h"
|
||||
#include "IReadFile.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace video
|
||||
{
|
||||
class IVideoDriver;
|
||||
class IImage;
|
||||
}
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class IGUIEnvironment;
|
||||
|
||||
class CGUIFont : public IGUIFontBitmap
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIFont(IGUIEnvironment* env, const io::path& filename);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIFont();
|
||||
|
||||
//! loads a font from a texture file
|
||||
bool load(const io::path& filename);
|
||||
|
||||
//! loads a font from a texture file
|
||||
bool load(io::IReadFile* file);
|
||||
|
||||
//! loads a font from an XML file
|
||||
bool load(io::IXMLReader* xml);
|
||||
|
||||
//! draws an text and clips it to the specified rectangle if wanted
|
||||
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
|
||||
video::SColor color, bool hcenter=false,
|
||||
bool vcenter=false, const core::rect<s32>* clip=0);
|
||||
|
||||
virtual void drawQuick(const core::stringw& text, const core::rect<s32>& position,
|
||||
video::SColor color, bool hcenter=false,
|
||||
bool vcenter=false, const core::rect<s32>* clip=0)
|
||||
{
|
||||
draw(text, position, color, hcenter, vcenter, clip);
|
||||
}
|
||||
|
||||
virtual void draw(const std::vector<GlyphLayout>& gls, const core::rect<s32>& position,
|
||||
video::SColor color, bool hcenter=false,
|
||||
bool vcenter=false, const core::rect<s32>* clip=0) {}
|
||||
|
||||
virtual void initGlyphLayouts(const core::stringw& text,
|
||||
std::vector<GlyphLayout>& gls, u32 shape_flag = 0) {}
|
||||
|
||||
//! returns the dimension of a text
|
||||
virtual core::dimension2d<u32> getDimension(const wchar_t* text) const;
|
||||
|
||||
//! Calculates the index of the character in the text which is on a specific position.
|
||||
virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const;
|
||||
|
||||
//! Returns the type of this font
|
||||
virtual EGUI_FONT_TYPE getType() const { return EGFT_BITMAP; }
|
||||
|
||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
||||
virtual void setKerningWidth (s32 kerning);
|
||||
virtual void setKerningHeight (s32 kerning);
|
||||
|
||||
virtual s32 getHeightPerLine() const { return (s32)getDimension(L"A").Height + getKerningHeight(); }
|
||||
|
||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
||||
virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const;
|
||||
virtual s32 getKerningHeight() const;
|
||||
|
||||
//! gets the sprite bank
|
||||
virtual IGUISpriteBank* getSpriteBank() const;
|
||||
|
||||
//! returns the sprite number from a given character
|
||||
virtual u32 getSpriteNoFromChar(const wchar_t *c) const;
|
||||
|
||||
virtual void setInvisibleCharacters( const wchar_t *s );
|
||||
virtual void setScale(f32 scale) {}
|
||||
virtual f32 getInverseShaping() const { return 1.0f; }
|
||||
virtual f32 getScale() const { return 1.0f; }
|
||||
|
||||
private:
|
||||
|
||||
struct SFontArea
|
||||
{
|
||||
SFontArea() : underhang(0), overhang(0), width(0), spriteno(0) {}
|
||||
s32 underhang;
|
||||
s32 overhang;
|
||||
s32 width;
|
||||
u32 spriteno;
|
||||
};
|
||||
|
||||
//! load & prepare font from ITexture
|
||||
bool loadTexture(video::IImage * image, const io::path& name);
|
||||
|
||||
void readPositions(video::IImage* texture, s32& lowerRightPositions);
|
||||
|
||||
s32 getAreaFromCharacter (const wchar_t c) const;
|
||||
void setMaxHeight();
|
||||
|
||||
core::array<SFontArea> Areas;
|
||||
core::map<wchar_t, s32> CharacterMap;
|
||||
video::IVideoDriver* Driver;
|
||||
IGUISpriteBank* SpriteBank;
|
||||
IGUIEnvironment* Environment;
|
||||
u32 WrongCharacter;
|
||||
s32 MaxHeight;
|
||||
s32 GlobalKerningWidth, GlobalKerningHeight;
|
||||
|
||||
core::stringw Invisible;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_FONT_H_INCLUDED__
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIImage.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CGUIImage::CGUIImage(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
|
||||
: IGUIImage(environment, parent, id, rectangle), Texture(0), Color(255,255,255,255),
|
||||
UseAlphaChannel(false), ScaleImage(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIImage");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIImage::~CGUIImage()
|
||||
{
|
||||
if (Texture)
|
||||
Texture->drop();
|
||||
}
|
||||
|
||||
|
||||
//! sets an image
|
||||
void CGUIImage::setImage(video::ITexture* image)
|
||||
{
|
||||
if (image == Texture)
|
||||
return;
|
||||
|
||||
if (Texture)
|
||||
Texture->drop();
|
||||
|
||||
Texture = image;
|
||||
|
||||
if (Texture)
|
||||
Texture->grab();
|
||||
}
|
||||
|
||||
//! Gets the image texture
|
||||
video::ITexture* CGUIImage::getImage() const
|
||||
{
|
||||
return Texture;
|
||||
}
|
||||
|
||||
//! sets the color of the image
|
||||
void CGUIImage::setColor(video::SColor color)
|
||||
{
|
||||
Color = color;
|
||||
}
|
||||
|
||||
//! Gets the color of the image
|
||||
video::SColor CGUIImage::getColor() const
|
||||
{
|
||||
return Color;
|
||||
}
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIImage::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
if (Texture)
|
||||
{
|
||||
//if (ScaleImage)
|
||||
//{
|
||||
const video::SColor Colors[] = {Color,Color,Color,Color};
|
||||
|
||||
skin->draw2DImage(Texture, AbsoluteRect,
|
||||
core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(Texture->getOriginalSize())),
|
||||
&AbsoluteClippingRect, Colors, UseAlphaChannel);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// Environment->getVideoDriver()->draw2DImage(Texture, AbsoluteRect.UpperLeftCorner,
|
||||
// core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(Texture->getOriginalSize())),
|
||||
// &AbsoluteClippingRect, Color, UseAlphaChannel);
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_DARK_SHADOW), AbsoluteRect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! sets if the image should use its alpha channel to draw itself
|
||||
void CGUIImage::setUseAlphaChannel(bool use)
|
||||
{
|
||||
UseAlphaChannel = use;
|
||||
}
|
||||
|
||||
|
||||
//! sets if the image should use its alpha channel to draw itself
|
||||
void CGUIImage::setScaleImage(bool scale)
|
||||
{
|
||||
ScaleImage = scale;
|
||||
}
|
||||
|
||||
|
||||
//! Returns true if the image is scaled to fit, false if not
|
||||
bool CGUIImage::isImageScaled() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return ScaleImage;
|
||||
}
|
||||
|
||||
//! Returns true if the image is using the alpha channel, false if not
|
||||
bool CGUIImage::isAlphaChannelUsed() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return UseAlphaChannel;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIImage::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIImage::serializeAttributes(out,options);
|
||||
|
||||
out->addTexture ("Texture", Texture);
|
||||
out->addBool ("UseAlphaChannel", UseAlphaChannel);
|
||||
out->addColor ("Color", Color);
|
||||
out->addBool ("ScaleImage", ScaleImage);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIImage::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIImage::deserializeAttributes(in,options);
|
||||
|
||||
setImage(in->getAttributeAsTexture("Texture"));
|
||||
setUseAlphaChannel(in->getAttributeAsBool("UseAlphaChannel"));
|
||||
setColor(in->getAttributeAsColor("Color"));
|
||||
setScaleImage(in->getAttributeAsBool("ScaleImage"));
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_IMAGE_H_INCLUDED__
|
||||
#define __C_GUI_IMAGE_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIImage.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIImage : public IGUIImage
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIImage(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIImage();
|
||||
|
||||
//! sets an image
|
||||
virtual void setImage(video::ITexture* image);
|
||||
|
||||
//! Gets the image texture
|
||||
virtual video::ITexture* getImage() const;
|
||||
|
||||
//! sets the color of the image
|
||||
virtual void setColor(video::SColor color);
|
||||
|
||||
//! sets if the image should scale to fit the element
|
||||
virtual void setScaleImage(bool scale);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! sets if the image should use its alpha channel to draw itself
|
||||
virtual void setUseAlphaChannel(bool use);
|
||||
|
||||
//! Gets the color of the image
|
||||
virtual video::SColor getColor() const;
|
||||
|
||||
//! Returns true if the image is scaled to fit, false if not
|
||||
virtual bool isImageScaled() const;
|
||||
|
||||
//! Returns true if the image is using the alpha channel, false if not
|
||||
virtual bool isAlphaChannelUsed() const;
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
private:
|
||||
video::ITexture* Texture;
|
||||
video::SColor Color;
|
||||
bool UseAlphaChannel;
|
||||
bool ScaleImage;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_IMAGE_H_INCLUDED__
|
||||
@@ -0,0 +1,93 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de
|
||||
// modified by Thomas Alten
|
||||
|
||||
#include "CGUIImageList.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIImageList::CGUIImageList( video::IVideoDriver* driver )
|
||||
: Driver( driver ),
|
||||
Texture( 0 ),
|
||||
ImageCount( 0 ),
|
||||
ImageSize( 0, 0 ),
|
||||
ImagesPerRow( 0 ),
|
||||
UseAlphaChannel( false )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName( "CGUIImageList" );
|
||||
#endif
|
||||
|
||||
if( Driver )
|
||||
{
|
||||
Driver->grab();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIImageList::~CGUIImageList()
|
||||
{
|
||||
if( Driver )
|
||||
{
|
||||
Driver->drop();
|
||||
}
|
||||
|
||||
if( Texture )
|
||||
{
|
||||
Texture->drop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Creates the image list from texture.
|
||||
bool CGUIImageList::createImageList(video::ITexture* texture,
|
||||
core::dimension2d<s32> imageSize,
|
||||
bool useAlphaChannel)
|
||||
{
|
||||
if( !texture )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Texture = texture;
|
||||
Texture->grab();
|
||||
|
||||
ImageSize = imageSize;
|
||||
|
||||
ImagesPerRow = Texture->getSize().Width / ImageSize.Width;
|
||||
ImageCount = ImagesPerRow * Texture->getSize().Height / ImageSize.Height;
|
||||
|
||||
UseAlphaChannel = useAlphaChannel;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Draws an image and clips it to the specified rectangle if wanted
|
||||
void CGUIImageList::draw( s32 index, const core::position2d<s32>& destPos,
|
||||
const core::rect<s32>* clip /*= 0*/ )
|
||||
{
|
||||
core::rect<s32> sourceRect;
|
||||
|
||||
if( !Driver || index < 0 || index >= ImageCount )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sourceRect.UpperLeftCorner.X = ( index % ImagesPerRow ) * ImageSize.Width;
|
||||
sourceRect.UpperLeftCorner.Y = ( index / ImagesPerRow ) * ImageSize.Height;
|
||||
sourceRect.LowerRightCorner.X = sourceRect.UpperLeftCorner.X + ImageSize.Width;
|
||||
sourceRect.LowerRightCorner.Y = sourceRect.UpperLeftCorner.Y + ImageSize.Height;
|
||||
|
||||
Driver->draw2DImage( Texture, destPos, sourceRect, clip,
|
||||
video::SColor( 255, 255, 255, 255 ), UseAlphaChannel );
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
@@ -0,0 +1,68 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de
|
||||
|
||||
#ifndef __C_GUI_IMAGE_LIST_H_INCLUDED__
|
||||
#define __C_GUI_IMAGE_LIST_H_INCLUDED__
|
||||
|
||||
#include "IGUIImageList.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIImageList : public IGUIImageList
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIImageList( video::IVideoDriver* Driver );
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIImageList();
|
||||
|
||||
//! Creates the image list from texture.
|
||||
//! \param texture: The texture to use
|
||||
//! \param imageSize: Size of a single image
|
||||
//! \param useAlphaChannel: true if the alpha channel from the texture should be used
|
||||
//! \return
|
||||
//! true if the image list was created
|
||||
bool createImageList(
|
||||
video::ITexture* texture,
|
||||
core::dimension2d<s32> imageSize,
|
||||
bool useAlphaChannel );
|
||||
|
||||
//! Draws an image and clips it to the specified rectangle if wanted
|
||||
//! \param index: Index of the image
|
||||
//! \param destPos: Position of the image to draw
|
||||
//! \param clip: Optional pointer to a rectalgle against which the text will be clipped.
|
||||
//! If the pointer is null, no clipping will be done.
|
||||
virtual void draw( s32 index, const core::position2d<s32>& destPos,
|
||||
const core::rect<s32>* clip = 0 );
|
||||
|
||||
//! Returns the count of Images in the list.
|
||||
//! \return Returns the count of Images in the list.
|
||||
virtual s32 getImageCount() const
|
||||
{ return ImageCount; }
|
||||
|
||||
//! Returns the size of the images in the list.
|
||||
//! \return Returns the size of the images in the list.
|
||||
virtual core::dimension2d<s32> getImageSize() const
|
||||
{ return ImageSize; }
|
||||
|
||||
private:
|
||||
|
||||
video::IVideoDriver* Driver;
|
||||
video::ITexture* Texture;
|
||||
s32 ImageCount;
|
||||
core::dimension2d<s32> ImageSize;
|
||||
s32 ImagesPerRow;
|
||||
bool UseAlphaChannel;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIInOutFader.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CGUIInOutFader::CGUIInOutFader(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
|
||||
: IGUIInOutFader(environment, parent, id, rectangle)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIInOutFader");
|
||||
#endif
|
||||
|
||||
Action = EFA_NOTHING;
|
||||
StartTime = 0;
|
||||
EndTime = 0;
|
||||
|
||||
setColor(video::SColor(0,0,0,0));
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIInOutFader::draw()
|
||||
{
|
||||
if (!IsVisible || !Action)
|
||||
return;
|
||||
|
||||
u32 now = os::Timer::getTime();
|
||||
if (now > EndTime && Action == EFA_FADE_IN)
|
||||
{
|
||||
Action = EFA_NOTHING;
|
||||
return;
|
||||
}
|
||||
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
if (driver)
|
||||
{
|
||||
f32 d;
|
||||
|
||||
if (now > EndTime)
|
||||
d = 0.0f;
|
||||
else
|
||||
d = (EndTime - now) / (f32)(EndTime - StartTime);
|
||||
|
||||
video::SColor newCol = FullColor.getInterpolated(TransColor, d);
|
||||
driver->draw2DRectangle(newCol, AbsoluteRect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! Gets the color to fade out to or to fade in from.
|
||||
video::SColor CGUIInOutFader::getColor() const
|
||||
{
|
||||
return Color[1];
|
||||
}
|
||||
|
||||
|
||||
//! Sets the color to fade out to or to fade in from.
|
||||
void CGUIInOutFader::setColor(video::SColor color)
|
||||
{
|
||||
video::SColor s = color;
|
||||
video::SColor d = color;
|
||||
|
||||
s.setAlpha ( 255 );
|
||||
d.setAlpha ( 0 );
|
||||
setColor ( s,d );
|
||||
|
||||
/*
|
||||
Color[0] = color;
|
||||
|
||||
FullColor = Color[0];
|
||||
TransColor = Color[0];
|
||||
|
||||
if (Action == EFA_FADE_OUT)
|
||||
{
|
||||
FullColor.setAlpha(0);
|
||||
TransColor.setAlpha(255);
|
||||
}
|
||||
else
|
||||
if (Action == EFA_FADE_IN)
|
||||
{
|
||||
FullColor.setAlpha(255);
|
||||
TransColor.setAlpha(0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void CGUIInOutFader::setColor(video::SColor source, video::SColor dest)
|
||||
{
|
||||
Color[0] = source;
|
||||
Color[1] = dest;
|
||||
|
||||
if (Action == EFA_FADE_OUT)
|
||||
{
|
||||
FullColor = Color[1];
|
||||
TransColor = Color[0];
|
||||
}
|
||||
else
|
||||
if (Action == EFA_FADE_IN)
|
||||
{
|
||||
FullColor = Color[0];
|
||||
TransColor = Color[1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the fade in or out process is done.
|
||||
bool CGUIInOutFader::isReady() const
|
||||
{
|
||||
u32 now = os::Timer::getTime();
|
||||
bool ret = (now > EndTime);
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//! Starts the fade in process.
|
||||
void CGUIInOutFader::fadeIn(u32 time)
|
||||
{
|
||||
StartTime = os::Timer::getTime();
|
||||
EndTime = StartTime + time;
|
||||
Action = EFA_FADE_IN;
|
||||
setColor(Color[0],Color[1]);
|
||||
}
|
||||
|
||||
|
||||
//! Starts the fade out process.
|
||||
void CGUIInOutFader::fadeOut(u32 time)
|
||||
{
|
||||
StartTime = os::Timer::getTime();
|
||||
EndTime = StartTime + time;
|
||||
Action = EFA_FADE_OUT;
|
||||
setColor(Color[0],Color[1]);
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIInOutFader::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIInOutFader::serializeAttributes(out,options);
|
||||
|
||||
out->addColor ("FullColor", FullColor);
|
||||
out->addColor ("TransColor", TransColor);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIInOutFader::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIInOutFader::deserializeAttributes(in,options);
|
||||
|
||||
FullColor = in->getAttributeAsColor("FullColor");
|
||||
TransColor = in->getAttributeAsColor("TransColor");
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_IN_OUT_FADER_H_INCLUDED__
|
||||
#define __C_GUI_IN_OUT_FADER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIInOutFader.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIInOutFader : public IGUIInOutFader
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIInOutFader(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Gets the color to fade out to or to fade in from.
|
||||
virtual video::SColor getColor() const;
|
||||
|
||||
//! Sets the color to fade out to or to fade in from.
|
||||
virtual void setColor(video::SColor color );
|
||||
virtual void setColor(video::SColor source, video::SColor dest);
|
||||
|
||||
//! Starts the fade in process.
|
||||
virtual void fadeIn(u32 time);
|
||||
|
||||
//! Starts the fade out process.
|
||||
virtual void fadeOut(u32 time);
|
||||
|
||||
//! Returns if the fade in or out process is done.
|
||||
virtual bool isReady() const;
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
private:
|
||||
|
||||
enum EFadeAction
|
||||
{
|
||||
EFA_NOTHING = 0,
|
||||
EFA_FADE_IN,
|
||||
EFA_FADE_OUT
|
||||
};
|
||||
|
||||
u32 StartTime;
|
||||
u32 EndTime;
|
||||
EFadeAction Action;
|
||||
|
||||
video::SColor Color[2];
|
||||
video::SColor FullColor;
|
||||
video::SColor TransColor;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_IN_OUT_FADER_H_INCLUDED__
|
||||
|
||||
@@ -0,0 +1,914 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIListBox.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "CGUIListBox.h"
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
#include "CGUIScrollBar.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle, bool clip,
|
||||
bool drawBack, bool moveOverSelect)
|
||||
: IGUIListBox(environment, parent, id, rectangle), Selected(-1),
|
||||
ItemHeight(0),ItemHeightOverride(0),
|
||||
TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0),
|
||||
ScrollBar(0), selectTime(0), LastKeyTime(0), Selecting(false), DrawBack(drawBack),
|
||||
MoveOverSelect(moveOverSelect), AutoScroll(true), HighlightWhenNotFocused(true)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIListBox");
|
||||
#endif
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
const s32 s = skin->getSize(EGDS_SCROLLBAR_SIZE);
|
||||
|
||||
ScrollBar = new CGUIScrollBar(false, Environment, this, -1,
|
||||
core::rect<s32>(RelativeRect.getWidth() - s, 0, RelativeRect.getWidth(), RelativeRect.getHeight()),
|
||||
!clip);
|
||||
ScrollBar->setSubElement(true);
|
||||
ScrollBar->setTabStop(false);
|
||||
ScrollBar->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
ScrollBar->setVisible(false);
|
||||
ScrollBar->setPos(0);
|
||||
|
||||
setNotClipped(!clip);
|
||||
|
||||
// this element can be tabbed to
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIListBox::~CGUIListBox()
|
||||
{
|
||||
if (ScrollBar)
|
||||
ScrollBar->drop();
|
||||
|
||||
if (Font)
|
||||
Font->drop();
|
||||
|
||||
if (IconBank)
|
||||
IconBank->drop();
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of list items
|
||||
u32 CGUIListBox::getItemCount() const
|
||||
{
|
||||
return Items.size();
|
||||
}
|
||||
|
||||
|
||||
//! returns string of a list item. the may be a value from 0 to itemCount-1
|
||||
const wchar_t* CGUIListBox::getListItem(u32 id) const
|
||||
{
|
||||
if (id>=Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[id].text.c_str();
|
||||
}
|
||||
|
||||
|
||||
//! Returns the icon of an item
|
||||
s32 CGUIListBox::getIcon(u32 id) const
|
||||
{
|
||||
if (id>=Items.size())
|
||||
return -1;
|
||||
|
||||
return Items[id].icon;
|
||||
}
|
||||
|
||||
|
||||
//! adds a list item, returns id of item
|
||||
u32 CGUIListBox::addItem(const wchar_t* text)
|
||||
{
|
||||
return addItem(text, -1);
|
||||
}
|
||||
|
||||
|
||||
//! adds a list item, returns id of item
|
||||
void CGUIListBox::removeItem(u32 id)
|
||||
{
|
||||
if (id >= Items.size())
|
||||
return;
|
||||
|
||||
if ((u32)Selected==id)
|
||||
{
|
||||
Selected = -1;
|
||||
}
|
||||
else if ((u32)Selected > id)
|
||||
{
|
||||
Selected -= 1;
|
||||
selectTime = os::Timer::getTime();
|
||||
}
|
||||
|
||||
Items.erase(id);
|
||||
|
||||
recalculateItemHeight();
|
||||
}
|
||||
|
||||
|
||||
s32 CGUIListBox::getItemAt(s32 xpos, s32 ypos) const
|
||||
{
|
||||
if ( xpos < AbsoluteRect.UpperLeftCorner.X || xpos >= AbsoluteRect.LowerRightCorner.X
|
||||
|| ypos < AbsoluteRect.UpperLeftCorner.Y || ypos >= AbsoluteRect.LowerRightCorner.Y
|
||||
)
|
||||
return -1;
|
||||
|
||||
if ( ItemHeight == 0 )
|
||||
return -1;
|
||||
|
||||
s32 item = ((ypos - AbsoluteRect.UpperLeftCorner.Y - 1) + ScrollBar->getPos()) / ItemHeight;
|
||||
if ( item < 0 || item >= (s32)Items.size())
|
||||
return -1;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
//! clears the list
|
||||
void CGUIListBox::clear()
|
||||
{
|
||||
Items.clear();
|
||||
ItemsIconWidth = 0;
|
||||
Selected = -1;
|
||||
|
||||
if (ScrollBar)
|
||||
ScrollBar->setPos(0);
|
||||
|
||||
recalculateItemHeight();
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::recalculateItemHeight()
|
||||
{
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
if (Font != skin->getFont())
|
||||
{
|
||||
if (Font)
|
||||
Font->drop();
|
||||
|
||||
Font = skin->getFont();
|
||||
if ( 0 == ItemHeightOverride )
|
||||
ItemHeight = 0;
|
||||
|
||||
if (Font)
|
||||
{
|
||||
if ( 0 == ItemHeightOverride )
|
||||
ItemHeight = Font->getDimension(L"A").Height + 4;
|
||||
|
||||
Font->grab();
|
||||
}
|
||||
}
|
||||
|
||||
TotalItemHeight = ItemHeight * Items.size();
|
||||
ScrollBar->setMax( core::max_(0, TotalItemHeight - AbsoluteRect.getHeight()) );
|
||||
s32 minItemHeight = ItemHeight > 0 ? ItemHeight : 1;
|
||||
ScrollBar->setSmallStep ( minItemHeight );
|
||||
ScrollBar->setLargeStep ( 2*minItemHeight );
|
||||
|
||||
if ( TotalItemHeight <= AbsoluteRect.getHeight() )
|
||||
ScrollBar->setVisible(false);
|
||||
else
|
||||
ScrollBar->setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
//! returns id of selected item. returns -1 if no item is selected.
|
||||
s32 CGUIListBox::getSelected() const
|
||||
{
|
||||
return Selected;
|
||||
}
|
||||
|
||||
|
||||
//! sets the selected item. Set this to -1 if no item should be selected
|
||||
void CGUIListBox::setSelected(s32 id)
|
||||
{
|
||||
if ((u32)id>=Items.size())
|
||||
Selected = -1;
|
||||
else
|
||||
Selected = id;
|
||||
|
||||
selectTime = os::Timer::getTime();
|
||||
|
||||
recalculateScrollPos();
|
||||
}
|
||||
|
||||
//! sets the selected item. Set this to -1 if no item should be selected
|
||||
void CGUIListBox::setSelected(const wchar_t *item)
|
||||
{
|
||||
s32 index = -1;
|
||||
|
||||
if ( item )
|
||||
{
|
||||
for ( index = 0; index < (s32) Items.size(); ++index )
|
||||
{
|
||||
if ( Items[index].text == item )
|
||||
break;
|
||||
}
|
||||
}
|
||||
setSelected ( index );
|
||||
}
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIListBox::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (event.KeyInput.PressedDown &&
|
||||
(event.KeyInput.Key == IRR_KEY_DOWN ||
|
||||
event.KeyInput.Key == IRR_KEY_UP ||
|
||||
event.KeyInput.Key == IRR_KEY_HOME ||
|
||||
event.KeyInput.Key == IRR_KEY_END ||
|
||||
event.KeyInput.Key == IRR_KEY_NEXT ||
|
||||
event.KeyInput.Key == IRR_KEY_PRIOR))
|
||||
{
|
||||
s32 oldSelected = Selected;
|
||||
switch (event.KeyInput.Key)
|
||||
{
|
||||
case IRR_KEY_DOWN:
|
||||
Selected += 1;
|
||||
break;
|
||||
case IRR_KEY_UP:
|
||||
Selected -= 1;
|
||||
break;
|
||||
case IRR_KEY_HOME:
|
||||
Selected = 0;
|
||||
break;
|
||||
case IRR_KEY_END:
|
||||
Selected = (s32)Items.size()-1;
|
||||
break;
|
||||
case IRR_KEY_NEXT:
|
||||
Selected += AbsoluteRect.getHeight() / ItemHeight;
|
||||
break;
|
||||
case IRR_KEY_PRIOR:
|
||||
Selected -= AbsoluteRect.getHeight() / ItemHeight;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (Selected >= (s32)Items.size())
|
||||
Selected = Items.size() - 1;
|
||||
else
|
||||
if (Selected<0)
|
||||
Selected = 0;
|
||||
|
||||
recalculateScrollPos();
|
||||
|
||||
// post the news
|
||||
|
||||
if (oldSelected != Selected && Parent && !Selecting && !MoveOverSelect)
|
||||
{
|
||||
SEvent e;
|
||||
e.EventType = EET_GUI_EVENT;
|
||||
e.GUIEvent.Caller = this;
|
||||
e.GUIEvent.Element = 0;
|
||||
e.GUIEvent.EventType = EGET_LISTBOX_CHANGED;
|
||||
Parent->OnEvent(e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!event.KeyInput.PressedDown &&
|
||||
(event.KeyInput.Key == IRR_KEY_RETURN ||
|
||||
event.KeyInput.Key == IRR_KEY_SPACE))
|
||||
{
|
||||
if (Parent)
|
||||
{
|
||||
SEvent e;
|
||||
e.EventType = EET_GUI_EVENT;
|
||||
e.GUIEvent.Caller = this;
|
||||
e.GUIEvent.Element = 0;
|
||||
e.GUIEvent.EventType = EGET_LISTBOX_SELECTED_AGAIN;
|
||||
Parent->OnEvent(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (event.KeyInput.PressedDown && event.KeyInput.Char)
|
||||
{
|
||||
// change selection based on text as it is typed.
|
||||
u32 now = os::Timer::getTime();
|
||||
|
||||
if (now - LastKeyTime < 500)
|
||||
{
|
||||
// add to key buffer if it isn't a key repeat
|
||||
if (!(KeyBuffer.size() == 1 && KeyBuffer[0] == event.KeyInput.Char))
|
||||
{
|
||||
KeyBuffer += L" ";
|
||||
KeyBuffer[KeyBuffer.size()-1] = event.KeyInput.Char;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyBuffer = L" ";
|
||||
KeyBuffer[0] = event.KeyInput.Char;
|
||||
}
|
||||
LastKeyTime = now;
|
||||
|
||||
// find the selected item, starting at the current selection
|
||||
s32 start = Selected;
|
||||
// dont change selection if the key buffer matches the current item
|
||||
if (Selected > -1 && KeyBuffer.size() > 1)
|
||||
{
|
||||
if (Items[Selected].text.size() >= KeyBuffer.size() &&
|
||||
KeyBuffer.equals_ignore_case(Items[Selected].text.subString(0,KeyBuffer.size())))
|
||||
return true;
|
||||
}
|
||||
|
||||
s32 current;
|
||||
for (current = start+1; current < (s32)Items.size(); ++current)
|
||||
{
|
||||
if (Items[current].text.size() >= KeyBuffer.size())
|
||||
{
|
||||
if (KeyBuffer.equals_ignore_case(Items[current].text.subString(0,KeyBuffer.size())))
|
||||
{
|
||||
if (Parent && Selected != current && !Selecting && !MoveOverSelect)
|
||||
{
|
||||
SEvent e;
|
||||
e.EventType = EET_GUI_EVENT;
|
||||
e.GUIEvent.Caller = this;
|
||||
e.GUIEvent.Element = 0;
|
||||
e.GUIEvent.EventType = EGET_LISTBOX_CHANGED;
|
||||
Parent->OnEvent(e);
|
||||
}
|
||||
setSelected(current);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (current = 0; current <= start; ++current)
|
||||
{
|
||||
if (Items[current].text.size() >= KeyBuffer.size())
|
||||
{
|
||||
if (KeyBuffer.equals_ignore_case(Items[current].text.subString(0,KeyBuffer.size())))
|
||||
{
|
||||
if (Parent && Selected != current && !Selecting && !MoveOverSelect)
|
||||
{
|
||||
Selected = current;
|
||||
SEvent e;
|
||||
e.EventType = EET_GUI_EVENT;
|
||||
e.GUIEvent.Caller = this;
|
||||
e.GUIEvent.Element = 0;
|
||||
e.GUIEvent.EventType = EGET_LISTBOX_CHANGED;
|
||||
Parent->OnEvent(e);
|
||||
}
|
||||
setSelected(current);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case EET_GUI_EVENT:
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case gui::EGET_SCROLL_BAR_CHANGED:
|
||||
if (event.GUIEvent.Caller == ScrollBar)
|
||||
return true;
|
||||
break;
|
||||
case gui::EGET_ELEMENT_FOCUS_LOST:
|
||||
{
|
||||
if (event.GUIEvent.Caller == this)
|
||||
Selecting = false;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
{
|
||||
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
|
||||
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
ScrollBar->setPos(ScrollBar->getPos() + (event.MouseInput.Wheel < 0 ? -1 : 1)*-ItemHeight/2);
|
||||
return true;
|
||||
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
{
|
||||
Selecting = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
{
|
||||
Selecting = false;
|
||||
|
||||
if (isPointInside(p))
|
||||
selectNew(event.MouseInput.Y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case EMIE_MOUSE_MOVED:
|
||||
if (Selecting || MoveOverSelect)
|
||||
{
|
||||
if (isPointInside(p))
|
||||
{
|
||||
selectNew(event.MouseInput.Y, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EET_LOG_TEXT_EVENT:
|
||||
case EET_USER_EVENT:
|
||||
case EET_JOYSTICK_INPUT_EVENT:
|
||||
case EEVENT_TYPE::EGUIET_FORCE_32_BIT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::selectNew(s32 ypos, bool onlyHover)
|
||||
{
|
||||
u32 now = os::Timer::getTime();
|
||||
s32 oldSelected = Selected;
|
||||
|
||||
Selected = getItemAt(AbsoluteRect.UpperLeftCorner.X, ypos);
|
||||
if (Selected<0 && !Items.empty())
|
||||
Selected = 0;
|
||||
|
||||
recalculateScrollPos();
|
||||
|
||||
gui::EGUI_EVENT_TYPE eventType = (Selected == oldSelected && now < selectTime + 500) ? EGET_LISTBOX_SELECTED_AGAIN : EGET_LISTBOX_CHANGED;
|
||||
selectTime = now;
|
||||
// post the news
|
||||
if (Parent && !onlyHover)
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = eventType;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Update the position and size of the listbox, and update the scrollbar
|
||||
void CGUIListBox::updateAbsolutePosition()
|
||||
{
|
||||
IGUIElement::updateAbsolutePosition();
|
||||
|
||||
recalculateItemHeight();
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIListBox::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
recalculateItemHeight(); // if the font changed
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
core::rect<s32>* clipRect = 0;
|
||||
|
||||
// draw background
|
||||
core::rect<s32> frameRect(AbsoluteRect);
|
||||
|
||||
// draw items
|
||||
|
||||
core::rect<s32> clientClip(AbsoluteRect);
|
||||
clientClip.UpperLeftCorner.Y += 1;
|
||||
clientClip.UpperLeftCorner.X += 1;
|
||||
if (ScrollBar->isVisible())
|
||||
clientClip.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE);
|
||||
clientClip.LowerRightCorner.Y -= 1;
|
||||
clientClip.clipAgainst(AbsoluteClippingRect);
|
||||
|
||||
skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT), true,
|
||||
DrawBack, frameRect, &clientClip);
|
||||
|
||||
if (clipRect)
|
||||
clientClip.clipAgainst(*clipRect);
|
||||
|
||||
frameRect = AbsoluteRect;
|
||||
frameRect.UpperLeftCorner.X += 1;
|
||||
if (ScrollBar->isVisible())
|
||||
frameRect.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE);
|
||||
|
||||
frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight;
|
||||
|
||||
frameRect.UpperLeftCorner.Y -= ScrollBar->getPos();
|
||||
frameRect.LowerRightCorner.Y -= ScrollBar->getPos();
|
||||
|
||||
bool hl = (HighlightWhenNotFocused || Environment->hasFocus(this) || Environment->hasFocus(ScrollBar));
|
||||
|
||||
for (s32 i=0; i<(s32)Items.size(); ++i)
|
||||
{
|
||||
if (frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y &&
|
||||
frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y)
|
||||
{
|
||||
if (i == Selected && hl)
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), frameRect, &clientClip);
|
||||
|
||||
core::rect<s32> textRect = frameRect;
|
||||
textRect.UpperLeftCorner.X += 3;
|
||||
|
||||
if (Font)
|
||||
{
|
||||
if (IconBank && (Items[i].icon > -1))
|
||||
{
|
||||
core::position2di iconPos = textRect.UpperLeftCorner;
|
||||
iconPos.Y += textRect.getHeight() / 2;
|
||||
iconPos.X += ItemsIconWidth/2;
|
||||
|
||||
if ( i==Selected && hl )
|
||||
{
|
||||
IconBank->draw2DSprite( (u32)Items[i].icon, iconPos, &clientClip,
|
||||
hasItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) ?
|
||||
getItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_ICON_HIGHLIGHT),
|
||||
selectTime, os::Timer::getTime(), false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
IconBank->draw2DSprite( (u32)Items[i].icon, iconPos, &clientClip,
|
||||
hasItemOverrideColor(i, EGUI_LBC_ICON) ? getItemOverrideColor(i, EGUI_LBC_ICON) : getItemDefaultColor(EGUI_LBC_ICON),
|
||||
0 , (i==Selected) ? os::Timer::getTime() : 0, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
textRect.UpperLeftCorner.X += ItemsIconWidth+3;
|
||||
|
||||
if ( i==Selected && hl )
|
||||
{
|
||||
Font->draw(Items[i].text.c_str(), textRect,
|
||||
hasItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) ?
|
||||
getItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_TEXT_HIGHLIGHT),
|
||||
false, true, &clientClip);
|
||||
}
|
||||
else
|
||||
{
|
||||
Font->draw(Items[i].text.c_str(), textRect,
|
||||
hasItemOverrideColor(i, EGUI_LBC_TEXT) ? getItemOverrideColor(i, EGUI_LBC_TEXT) : getItemDefaultColor(EGUI_LBC_TEXT),
|
||||
false, true, &clientClip);
|
||||
}
|
||||
|
||||
textRect.UpperLeftCorner.X -= ItemsIconWidth+3;
|
||||
}
|
||||
}
|
||||
|
||||
frameRect.UpperLeftCorner.Y += ItemHeight;
|
||||
frameRect.LowerRightCorner.Y += ItemHeight;
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! adds an list item with an icon
|
||||
u32 CGUIListBox::addItem(const wchar_t* text, s32 icon)
|
||||
{
|
||||
ListItem i;
|
||||
i.text = text;
|
||||
i.icon = icon;
|
||||
|
||||
Items.push_back(i);
|
||||
recalculateItemHeight();
|
||||
recalculateItemWidth(icon);
|
||||
|
||||
return Items.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::setSpriteBank(IGUISpriteBank* bank)
|
||||
{
|
||||
if ( bank == IconBank )
|
||||
return;
|
||||
if (IconBank)
|
||||
IconBank->drop();
|
||||
|
||||
IconBank = bank;
|
||||
if (IconBank)
|
||||
IconBank->grab();
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::recalculateScrollPos()
|
||||
{
|
||||
if (!AutoScroll)
|
||||
return;
|
||||
|
||||
const s32 selPos = (Selected == -1 ? TotalItemHeight : Selected * ItemHeight) - ScrollBar->getPos();
|
||||
|
||||
if (selPos < 0)
|
||||
{
|
||||
ScrollBar->setPos(ScrollBar->getPos() + selPos);
|
||||
}
|
||||
else
|
||||
if (selPos > AbsoluteRect.getHeight() - ItemHeight)
|
||||
{
|
||||
ScrollBar->setPos(ScrollBar->getPos() + selPos - AbsoluteRect.getHeight() + ItemHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::setAutoScrollEnabled(bool scroll)
|
||||
{
|
||||
AutoScroll = scroll;
|
||||
}
|
||||
|
||||
|
||||
bool CGUIListBox::isAutoScrollEnabled() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return AutoScroll;
|
||||
}
|
||||
|
||||
|
||||
bool CGUIListBox::getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc & useColorLabel, core::stringc & colorLabel) const
|
||||
{
|
||||
switch ( colorType )
|
||||
{
|
||||
case EGUI_LBC_TEXT:
|
||||
useColorLabel = "UseColText";
|
||||
colorLabel = "ColText";
|
||||
break;
|
||||
case EGUI_LBC_TEXT_HIGHLIGHT:
|
||||
useColorLabel = "UseColTextHl";
|
||||
colorLabel = "ColTextHl";
|
||||
break;
|
||||
case EGUI_LBC_ICON:
|
||||
useColorLabel = "UseColIcon";
|
||||
colorLabel = "ColIcon";
|
||||
break;
|
||||
case EGUI_LBC_ICON_HIGHLIGHT:
|
||||
useColorLabel = "UseColIconHl";
|
||||
colorLabel = "ColIconHl";
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIListBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIListBox::serializeAttributes(out,options);
|
||||
|
||||
// todo: out->addString ("IconBank", IconBank->getName?);
|
||||
out->addBool ("DrawBack", DrawBack);
|
||||
out->addBool ("MoveOverSelect", MoveOverSelect);
|
||||
out->addBool ("AutoScroll", AutoScroll);
|
||||
|
||||
out->addInt("ItemCount", Items.size());
|
||||
for (u32 i=0;i<Items.size(); ++i)
|
||||
{
|
||||
core::stringc label("text");
|
||||
label += i;
|
||||
out->addString(label.c_str(), Items[i].text.c_str() );
|
||||
|
||||
for ( s32 c=0; c < (s32)EGUI_LBC_COUNT; ++c )
|
||||
{
|
||||
core::stringc useColorLabel, colorLabel;
|
||||
if ( !getSerializationLabels((EGUI_LISTBOX_COLOR)c, useColorLabel, colorLabel) )
|
||||
return;
|
||||
label = useColorLabel; label += i;
|
||||
if ( Items[i].OverrideColors[c].Use )
|
||||
{
|
||||
out->addBool(label.c_str(), true );
|
||||
label = colorLabel; label += i;
|
||||
out->addColor(label.c_str(), Items[i].OverrideColors[c].Color);
|
||||
}
|
||||
else
|
||||
{
|
||||
out->addBool(label.c_str(), false );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIListBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
clear();
|
||||
|
||||
DrawBack = in->getAttributeAsBool("DrawBack");
|
||||
MoveOverSelect = in->getAttributeAsBool("MoveOverSelect");
|
||||
AutoScroll = in->getAttributeAsBool("AutoScroll");
|
||||
|
||||
IGUIListBox::deserializeAttributes(in,options);
|
||||
|
||||
const s32 count = in->getAttributeAsInt("ItemCount");
|
||||
for (s32 i=0; i<count; ++i)
|
||||
{
|
||||
core::stringc label("text");
|
||||
ListItem item;
|
||||
|
||||
label += i;
|
||||
item.text = in->getAttributeAsStringW(label.c_str());
|
||||
|
||||
addItem(item.text.c_str(), item.icon);
|
||||
|
||||
for ( u32 c=0; c < EGUI_LBC_COUNT; ++c )
|
||||
{
|
||||
core::stringc useColorLabel, colorLabel;
|
||||
if ( !getSerializationLabels((EGUI_LISTBOX_COLOR)c, useColorLabel, colorLabel) )
|
||||
return;
|
||||
label = useColorLabel; label += i;
|
||||
Items[i].OverrideColors[c].Use = in->getAttributeAsBool(label.c_str());
|
||||
if ( Items[i].OverrideColors[c].Use )
|
||||
{
|
||||
label = colorLabel; label += i;
|
||||
Items[i].OverrideColors[c].Color = in->getAttributeAsColor(label.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::recalculateItemWidth(s32 icon)
|
||||
{
|
||||
if (IconBank && icon > -1 &&
|
||||
IconBank->getSprites().size() > (u32)icon &&
|
||||
IconBank->getSprites()[(u32)icon].Frames.size())
|
||||
{
|
||||
u32 rno = IconBank->getSprites()[(u32)icon].Frames[0].rectNumber;
|
||||
if (IconBank->getPositions().size() > rno)
|
||||
{
|
||||
const s32 w = IconBank->getPositions()[rno].getWidth();
|
||||
if (w > ItemsIconWidth)
|
||||
ItemsIconWidth = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::setItem(u32 index, const wchar_t* text, s32 icon)
|
||||
{
|
||||
if ( index >= Items.size() )
|
||||
return;
|
||||
|
||||
Items[index].text = text;
|
||||
Items[index].icon = icon;
|
||||
|
||||
recalculateItemHeight();
|
||||
recalculateItemWidth(icon);
|
||||
}
|
||||
|
||||
|
||||
//! Insert the item at the given index
|
||||
//! Return the index on success or -1 on failure.
|
||||
s32 CGUIListBox::insertItem(u32 index, const wchar_t* text, s32 icon)
|
||||
{
|
||||
ListItem i;
|
||||
i.text = text;
|
||||
i.icon = icon;
|
||||
|
||||
Items.insert(i, index);
|
||||
recalculateItemHeight();
|
||||
recalculateItemWidth(icon);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::swapItems(u32 index1, u32 index2)
|
||||
{
|
||||
if ( index1 >= Items.size() || index2 >= Items.size() )
|
||||
return;
|
||||
|
||||
ListItem dummmy = Items[index1];
|
||||
Items[index1] = Items[index2];
|
||||
Items[index2] = dummmy;
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::setItemOverrideColor(u32 index, video::SColor color)
|
||||
{
|
||||
for ( u32 c=0; c < EGUI_LBC_COUNT; ++c )
|
||||
{
|
||||
Items[index].OverrideColors[c].Use = true;
|
||||
Items[index].OverrideColors[c].Color = color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color)
|
||||
{
|
||||
if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
|
||||
return;
|
||||
|
||||
Items[index].OverrideColors[colorType].Use = true;
|
||||
Items[index].OverrideColors[colorType].Color = color;
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::clearItemOverrideColor(u32 index)
|
||||
{
|
||||
for (u32 c=0; c < (u32)EGUI_LBC_COUNT; ++c )
|
||||
{
|
||||
Items[index].OverrideColors[c].Use = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGUIListBox::clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType)
|
||||
{
|
||||
if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
|
||||
return;
|
||||
|
||||
Items[index].OverrideColors[colorType].Use = false;
|
||||
}
|
||||
|
||||
|
||||
bool CGUIListBox::hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const
|
||||
{
|
||||
if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
|
||||
return false;
|
||||
|
||||
return Items[index].OverrideColors[colorType].Use;
|
||||
}
|
||||
|
||||
|
||||
video::SColor CGUIListBox::getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const
|
||||
{
|
||||
if ( (u32)index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
|
||||
return video::SColor();
|
||||
|
||||
return Items[index].OverrideColors[colorType].Color;
|
||||
}
|
||||
|
||||
|
||||
video::SColor CGUIListBox::getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const
|
||||
{
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if ( !skin )
|
||||
return video::SColor();
|
||||
|
||||
switch ( colorType )
|
||||
{
|
||||
case EGUI_LBC_TEXT:
|
||||
return skin->getColor(EGDC_BUTTON_TEXT);
|
||||
case EGUI_LBC_TEXT_HIGHLIGHT:
|
||||
return skin->getColor(EGDC_HIGH_LIGHT_TEXT);
|
||||
case EGUI_LBC_ICON:
|
||||
return skin->getColor(EGDC_ICON);
|
||||
case EGUI_LBC_ICON_HIGHLIGHT:
|
||||
return skin->getColor(EGDC_ICON_HIGH_LIGHT);
|
||||
default:
|
||||
return video::SColor();
|
||||
}
|
||||
}
|
||||
|
||||
//! set global itemHeight
|
||||
void CGUIListBox::setItemHeight( s32 height )
|
||||
{
|
||||
ItemHeight = height;
|
||||
ItemHeightOverride = 1;
|
||||
}
|
||||
|
||||
|
||||
//! Sets whether to draw the background
|
||||
void CGUIListBox::setDrawBackground(bool draw)
|
||||
{
|
||||
DrawBack = draw;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_LIST_BOX_H_INCLUDED__
|
||||
#define __C_GUI_LIST_BOX_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIListBox.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class IGUIFont;
|
||||
class IGUIScrollBar;
|
||||
|
||||
class CGUIListBox : public IGUIListBox
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle, bool clip=true,
|
||||
bool drawBack=false, bool moveOverSelect=false);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIListBox();
|
||||
|
||||
//! returns amount of list items
|
||||
virtual u32 getItemCount() const;
|
||||
|
||||
//! returns string of a list item. the id may be a value from 0 to itemCount-1
|
||||
virtual const wchar_t* getListItem(u32 id) const;
|
||||
|
||||
//! adds an list item, returns id of item
|
||||
virtual u32 addItem(const wchar_t* text);
|
||||
|
||||
//! clears the list
|
||||
virtual void clear();
|
||||
|
||||
//! returns id of selected item. returns -1 if no item is selected.
|
||||
virtual s32 getSelected() const;
|
||||
|
||||
//! sets the selected item. Set this to -1 if no item should be selected
|
||||
virtual void setSelected(s32 id);
|
||||
|
||||
//! sets the selected item. Set this to -1 if no item should be selected
|
||||
virtual void setSelected(const wchar_t *item);
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! adds an list item with an icon
|
||||
//! \param text Text of list entry
|
||||
//! \param icon Sprite index of the Icon within the current sprite bank. Set it to -1 if you want no icon
|
||||
//! \return
|
||||
//! returns the id of the new created item
|
||||
virtual u32 addItem(const wchar_t* text, s32 icon);
|
||||
|
||||
//! Returns the icon of an item
|
||||
virtual s32 getIcon(u32 id) const;
|
||||
|
||||
//! removes an item from the list
|
||||
virtual void removeItem(u32 id);
|
||||
|
||||
//! get the the id of the item at the given absolute coordinates
|
||||
virtual s32 getItemAt(s32 xpos, s32 ypos) const;
|
||||
|
||||
//! Sets the sprite bank which should be used to draw list icons. This font is set to the sprite bank of
|
||||
//! the built-in-font by default. A sprite can be displayed in front of every list item.
|
||||
//! An icon is an index within the icon sprite bank. Several default icons are available in the
|
||||
//! skin through getIcon
|
||||
virtual void setSpriteBank(IGUISpriteBank* bank);
|
||||
|
||||
//! set whether the listbox should scroll to newly selected items
|
||||
virtual void setAutoScrollEnabled(bool scroll);
|
||||
|
||||
//! returns true if automatic scrolling is enabled, false if not.
|
||||
virtual bool isAutoScrollEnabled() const;
|
||||
|
||||
//! Update the position and size of the listbox, and update the scrollbar
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
//! set all item colors at given index to color
|
||||
virtual void setItemOverrideColor(u32 index, video::SColor color);
|
||||
|
||||
//! set all item colors of specified type at given index to color
|
||||
virtual void setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color);
|
||||
|
||||
//! clear all item colors at index
|
||||
virtual void clearItemOverrideColor(u32 index);
|
||||
|
||||
//! clear item color at index for given colortype
|
||||
virtual void clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType);
|
||||
|
||||
//! has the item at index its color overwritten?
|
||||
virtual bool hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const;
|
||||
|
||||
//! return the overwrite color at given item index.
|
||||
virtual video::SColor getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const;
|
||||
|
||||
//! return the default color which is used for the given colorType
|
||||
virtual video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const;
|
||||
|
||||
//! set the item at the given index
|
||||
virtual void setItem(u32 index, const wchar_t* text, s32 icon);
|
||||
|
||||
//! Insert the item at the given index
|
||||
//! Return the index on success or -1 on failure.
|
||||
virtual s32 insertItem(u32 index, const wchar_t* text, s32 icon);
|
||||
|
||||
//! Swap the items at the given indices
|
||||
virtual void swapItems(u32 index1, u32 index2);
|
||||
|
||||
//! set global itemHeight
|
||||
virtual void setItemHeight( s32 height );
|
||||
|
||||
//! Sets whether to draw the background
|
||||
virtual void setDrawBackground(bool draw);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
struct ListItem
|
||||
{
|
||||
ListItem() : icon(-1)
|
||||
{}
|
||||
|
||||
core::stringw text;
|
||||
s32 icon;
|
||||
|
||||
// A multicolor extension
|
||||
struct ListItemOverrideColor
|
||||
{
|
||||
ListItemOverrideColor() : Use(false) {}
|
||||
bool Use;
|
||||
video::SColor Color;
|
||||
};
|
||||
ListItemOverrideColor OverrideColors[EGUI_LBC_COUNT];
|
||||
};
|
||||
|
||||
void recalculateItemHeight();
|
||||
void selectNew(s32 ypos, bool onlyHover=false);
|
||||
void recalculateScrollPos();
|
||||
|
||||
// extracted that function to avoid copy&paste code
|
||||
void recalculateItemWidth(s32 icon);
|
||||
|
||||
// get labels used for serialization
|
||||
bool getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc & useColorLabel, core::stringc & colorLabel) const;
|
||||
|
||||
core::array< ListItem > Items;
|
||||
s32 Selected;
|
||||
s32 ItemHeight;
|
||||
s32 ItemHeightOverride;
|
||||
s32 TotalItemHeight;
|
||||
s32 ItemsIconWidth;
|
||||
gui::IGUIFont* Font;
|
||||
gui::IGUISpriteBank* IconBank;
|
||||
gui::IGUIScrollBar* ScrollBar;
|
||||
u32 selectTime;
|
||||
u32 LastKeyTime;
|
||||
core::stringw KeyBuffer;
|
||||
bool Selecting;
|
||||
bool DrawBack;
|
||||
bool MoveOverSelect;
|
||||
bool AutoScroll;
|
||||
bool HighlightWhenNotFocused;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,294 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIMenu.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUIWindow.h"
|
||||
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIMenu::CGUIMenu(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle)
|
||||
: CGUIContextMenu(environment, parent, id, rectangle, false, true)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIMenu");
|
||||
#endif
|
||||
|
||||
Type = EGUIET_MENU;
|
||||
|
||||
setNotClipped(false);
|
||||
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIMenu::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
IGUIFont* font = skin->getFont(EGDF_MENU);
|
||||
|
||||
if (font != LastFont)
|
||||
{
|
||||
if (LastFont)
|
||||
LastFont->drop();
|
||||
LastFont = font;
|
||||
if (LastFont)
|
||||
LastFont->grab();
|
||||
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
|
||||
// draw frame
|
||||
|
||||
skin->draw3DToolBar(this, rect, &AbsoluteClippingRect);
|
||||
|
||||
// loop through all menu items
|
||||
|
||||
rect = AbsoluteRect;
|
||||
|
||||
for (s32 i=0; i<(s32)Items.size(); ++i)
|
||||
{
|
||||
if (!Items[i].IsSeparator)
|
||||
{
|
||||
rect = getRect(Items[i], AbsoluteRect);
|
||||
|
||||
// draw highlighted
|
||||
if (i == HighLighted && Items[i].Enabled)
|
||||
{
|
||||
skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_DARK_SHADOW),
|
||||
true, true, rect, &AbsoluteClippingRect);
|
||||
}
|
||||
// draw text
|
||||
|
||||
EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT;
|
||||
|
||||
if (i == HighLighted)
|
||||
c = EGDC_HIGH_LIGHT_TEXT;
|
||||
|
||||
if (!Items[i].Enabled)
|
||||
c = EGDC_GRAY_TEXT;
|
||||
|
||||
if (font)
|
||||
font->draw(Items[i].Text.c_str(), rect,
|
||||
skin->getColor(c), true, true, &AbsoluteClippingRect);
|
||||
}
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIMenu::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case gui::EGET_ELEMENT_FOCUS_LOST:
|
||||
if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element))
|
||||
{
|
||||
closeAllSubMenus();
|
||||
HighLighted = -1;
|
||||
}
|
||||
break;
|
||||
case gui::EGET_ELEMENT_FOCUSED:
|
||||
if (event.GUIEvent.Caller == this && Parent)
|
||||
{
|
||||
Parent->bringToFront(this);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
{
|
||||
if (!Environment->hasFocus(this))
|
||||
{
|
||||
Environment->setFocus(this);
|
||||
}
|
||||
|
||||
if (Parent)
|
||||
Parent->bringToFront(this);
|
||||
|
||||
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
|
||||
bool shouldCloseSubMenu = hasOpenSubMenu();
|
||||
if (!AbsoluteClippingRect.isPointInside(p))
|
||||
{
|
||||
shouldCloseSubMenu = false;
|
||||
}
|
||||
highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true);
|
||||
if ( shouldCloseSubMenu )
|
||||
{
|
||||
Environment->removeFocus(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
{
|
||||
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
|
||||
if (!AbsoluteClippingRect.isPointInside(p))
|
||||
{
|
||||
s32 t = sendClick(p);
|
||||
if ((t==0 || t==1) && Environment->hasFocus(this))
|
||||
Environment->removeFocus(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
case EMIE_MOUSE_MOVED:
|
||||
if (Environment->hasFocus(this) && HighLighted >= 0)
|
||||
{
|
||||
s32 oldHighLighted = HighLighted;
|
||||
highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true);
|
||||
if ( HighLighted < 0 )
|
||||
HighLighted = oldHighLighted; // keep last hightlight active when moving outside the area
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
void CGUIMenu::recalculateSize()
|
||||
{
|
||||
core::rect<s32> clientRect; // client rect of parent
|
||||
if ( Parent && Parent->hasType(EGUIET_WINDOW) )
|
||||
{
|
||||
clientRect = static_cast<IGUIWindow*>(Parent)->getClientRect();
|
||||
}
|
||||
else if ( Parent )
|
||||
{
|
||||
clientRect = core::rect<s32>(0,0, Parent->getAbsolutePosition().getWidth(),
|
||||
Parent->getAbsolutePosition().getHeight());
|
||||
}
|
||||
else
|
||||
{
|
||||
clientRect = RelativeRect;
|
||||
}
|
||||
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
IGUIFont* font = skin->getFont(EGDF_MENU);
|
||||
|
||||
if (!font)
|
||||
{
|
||||
if (Parent && skin)
|
||||
RelativeRect = core::rect<s32>(clientRect.UpperLeftCorner.X, clientRect.UpperLeftCorner.Y,
|
||||
clientRect.LowerRightCorner.X, clientRect.UpperLeftCorner.Y+skin->getSize(EGDS_MENU_HEIGHT));
|
||||
return;
|
||||
}
|
||||
|
||||
core::rect<s32> rect;
|
||||
rect.UpperLeftCorner = clientRect.UpperLeftCorner;
|
||||
s32 height = font->getDimension(L"A").Height + 5;
|
||||
//if (skin && height < skin->getSize ( EGDS_MENU_HEIGHT ))
|
||||
// height = skin->getSize(EGDS_MENU_HEIGHT);
|
||||
s32 width = rect.UpperLeftCorner.X;
|
||||
s32 i;
|
||||
|
||||
for (i=0; i<(s32)Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].IsSeparator)
|
||||
{
|
||||
Items[i].Dim.Width = 0;
|
||||
Items[i].Dim.Height = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
Items[i].Dim = font->getDimension(Items[i].Text.c_str());
|
||||
Items[i].Dim.Width += 20;
|
||||
}
|
||||
|
||||
Items[i].PosY = width;
|
||||
width += Items[i].Dim.Width;
|
||||
}
|
||||
|
||||
width = clientRect.getWidth();
|
||||
|
||||
rect.LowerRightCorner.X = rect.UpperLeftCorner.X + width;
|
||||
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + height;
|
||||
|
||||
setRelativePosition(rect);
|
||||
|
||||
// recalculate submenus
|
||||
for (i=0; i<(s32)Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
{
|
||||
// move submenu
|
||||
s32 w = Items[i].SubMenu->getAbsolutePosition().getWidth();
|
||||
s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight();
|
||||
|
||||
Items[i].SubMenu->setRelativePosition(
|
||||
core::rect<s32>(Items[i].PosY, height ,
|
||||
Items[i].PosY+w-5, height+h));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! returns the item highlight-area
|
||||
core::rect<s32> CGUIMenu::getHRect(const SItem& i, const core::rect<s32>& absolute) const
|
||||
{
|
||||
core::rect<s32> r = absolute;
|
||||
r.UpperLeftCorner.X += i.PosY;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X + i.Dim.Width;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//! Gets drawing rect of Item
|
||||
core::rect<s32> CGUIMenu::getRect(const SItem& i, const core::rect<s32>& absolute) const
|
||||
{
|
||||
return getHRect(i, absolute);
|
||||
}
|
||||
|
||||
|
||||
void CGUIMenu::updateAbsolutePosition()
|
||||
{
|
||||
if (Parent)
|
||||
DesiredRect.LowerRightCorner.X = Parent->getAbsolutePosition().getWidth();
|
||||
|
||||
IGUIElement::updateAbsolutePosition();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_MENU_H_INCLUDED__
|
||||
#define __C_GUI_MENU_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "CGUIContextMenu.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! GUI menu interface.
|
||||
class CGUIMenu : public CGUIContextMenu
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! Updates the absolute position.
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void recalculateSize();
|
||||
|
||||
//! returns the item highlight-area
|
||||
virtual core::rect<s32> getHRect(const SItem& i, const core::rect<s32>& absolute) const;
|
||||
|
||||
//! Gets drawing rect of Item
|
||||
virtual core::rect<s32> getRect(const SItem& i, const core::rect<s32>& absolute) const;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
#endif // __C_GUI_MENU_H_INCLUDED__
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIMeshViewer.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IAnimatedMesh.h"
|
||||
#include "IMesh.h"
|
||||
#include "os.h"
|
||||
#include "IGUISkin.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CGUIMeshViewer::CGUIMeshViewer(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
|
||||
: IGUIMeshViewer(environment, parent, id, rectangle), Mesh(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIMeshViewer");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIMeshViewer::~CGUIMeshViewer()
|
||||
{
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
}
|
||||
|
||||
|
||||
//! sets the mesh to be shown
|
||||
void CGUIMeshViewer::setMesh(scene::IAnimatedMesh* mesh)
|
||||
{
|
||||
if (mesh)
|
||||
mesh->grab();
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
|
||||
Mesh = mesh;
|
||||
|
||||
/* This might be used for proper transformation etc.
|
||||
core::vector3df center(0.0f,0.0f,0.0f);
|
||||
core::aabbox3d<f32> box;
|
||||
|
||||
box = Mesh->getMesh(0)->getBoundingBox();
|
||||
center = (box.MaxEdge + box.MinEdge) / 2;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//! Gets the displayed mesh
|
||||
scene::IAnimatedMesh* CGUIMeshViewer::getMesh() const
|
||||
{
|
||||
return Mesh;
|
||||
}
|
||||
|
||||
|
||||
//! sets the material
|
||||
void CGUIMeshViewer::setMaterial(const video::SMaterial& material)
|
||||
{
|
||||
Material = material;
|
||||
}
|
||||
|
||||
|
||||
//! gets the material
|
||||
const video::SMaterial& CGUIMeshViewer::getMaterial() const
|
||||
{
|
||||
return Material;
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIMeshViewer::OnEvent(const SEvent& event)
|
||||
{
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIMeshViewer::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
core::rect<s32> viewPort = AbsoluteRect;
|
||||
viewPort.LowerRightCorner.X -= 1;
|
||||
viewPort.LowerRightCorner.Y -= 1;
|
||||
viewPort.UpperLeftCorner.X += 1;
|
||||
viewPort.UpperLeftCorner.Y += 1;
|
||||
|
||||
viewPort.clipAgainst(AbsoluteClippingRect);
|
||||
|
||||
// draw the frame
|
||||
|
||||
core::rect<s32> frameRect(AbsoluteRect);
|
||||
frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + 1;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), frameRect, &AbsoluteClippingRect);
|
||||
|
||||
frameRect.LowerRightCorner.Y = AbsoluteRect.LowerRightCorner.Y;
|
||||
frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + 1;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), frameRect, &AbsoluteClippingRect);
|
||||
|
||||
frameRect = AbsoluteRect;
|
||||
frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X - 1;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect);
|
||||
|
||||
frameRect = AbsoluteRect;
|
||||
frameRect.UpperLeftCorner.Y = AbsoluteRect.LowerRightCorner.Y - 1;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect);
|
||||
|
||||
// draw the mesh
|
||||
|
||||
if (Mesh)
|
||||
{
|
||||
//TODO: if outside of screen, dont draw.
|
||||
// - why is the absolute clipping rect not already the screen?
|
||||
|
||||
core::rect<s32> oldViewPort = driver->getViewPort();
|
||||
|
||||
driver->setViewPort(viewPort);
|
||||
|
||||
core::matrix4 mat;
|
||||
|
||||
//CameraControl->calculateProjectionMatrix(mat);
|
||||
//driver->setTransform(video::TS_PROJECTION, mat);
|
||||
|
||||
mat.makeIdentity();
|
||||
mat.setTranslation(core::vector3df(0,0,0));
|
||||
driver->setTransform(video::ETS_WORLD, mat);
|
||||
|
||||
//CameraControl->calculateViewMatrix(mat);
|
||||
//driver->setTransform(video::TS_VIEW, mat);
|
||||
|
||||
driver->setMaterial(Material);
|
||||
|
||||
u32 frame = 0;
|
||||
if(Mesh->getFrameCount())
|
||||
frame = (os::Timer::getTime()/20)%Mesh->getFrameCount();
|
||||
const scene::IMesh* const m = Mesh->getMesh(frame);
|
||||
for (u32 i=0; i<m->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
|
||||
driver->drawVertexPrimitiveList(mb->getVertices(),
|
||||
mb->getVertexCount(), mb->getIndices(),
|
||||
mb->getIndexCount()/ 3, mb->getVertexType(),
|
||||
scene::EPT_TRIANGLES, mb->getIndexType());
|
||||
}
|
||||
|
||||
driver->setViewPort(oldViewPort);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_MESH_VIEWER_H_INCLUDED__
|
||||
#define __C_GUI_MESH_VIEWER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIMeshViewer.h"
|
||||
#include "SMaterial.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIMeshViewer : public IGUIMeshViewer
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIMeshViewer(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIMeshViewer();
|
||||
|
||||
//! sets the mesh to be shown
|
||||
virtual void setMesh(scene::IAnimatedMesh* mesh);
|
||||
|
||||
//! Gets the displayed mesh
|
||||
virtual scene::IAnimatedMesh* getMesh() const;
|
||||
|
||||
//! sets the material
|
||||
virtual void setMaterial(const video::SMaterial& material);
|
||||
|
||||
//! gets the material
|
||||
virtual const video::SMaterial& getMaterial() const;
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
private:
|
||||
|
||||
video::SMaterial Material;
|
||||
scene::IAnimatedMesh* Mesh;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_MESH_VIEWER_H_INCLUDED__
|
||||
|
||||
@@ -0,0 +1,463 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIMessageBox.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "ITexture.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIMessageBox::CGUIMessageBox(IGUIEnvironment* environment, const wchar_t* caption,
|
||||
const wchar_t* text, s32 flags,
|
||||
IGUIElement* parent, s32 id, core::rect<s32> rectangle, video::ITexture* image)
|
||||
: CGUIWindow(environment, parent, id, rectangle),
|
||||
OkButton(0), CancelButton(0), YesButton(0), NoButton(0), StaticText(0),
|
||||
Icon(0), IconTexture(image),
|
||||
Flags(flags), MessageText(text), Pressed(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIMessageBox");
|
||||
#endif
|
||||
|
||||
// set element type
|
||||
Type = EGUIET_MESSAGE_BOX;
|
||||
|
||||
// remove focus
|
||||
Environment->setFocus(0);
|
||||
|
||||
// remove buttons
|
||||
|
||||
getMaximizeButton()->remove();
|
||||
getMinimizeButton()->remove();
|
||||
|
||||
if (caption)
|
||||
setText(caption);
|
||||
|
||||
Environment->setFocus(this);
|
||||
|
||||
if ( IconTexture )
|
||||
IconTexture->grab();
|
||||
|
||||
refreshControls();
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIMessageBox::~CGUIMessageBox()
|
||||
{
|
||||
if (StaticText)
|
||||
StaticText->drop();
|
||||
|
||||
if (OkButton)
|
||||
OkButton->drop();
|
||||
|
||||
if (CancelButton)
|
||||
CancelButton->drop();
|
||||
|
||||
if (YesButton)
|
||||
YesButton->drop();
|
||||
|
||||
if (NoButton)
|
||||
NoButton->drop();
|
||||
|
||||
if (Icon)
|
||||
Icon->drop();
|
||||
|
||||
if ( IconTexture )
|
||||
IconTexture->drop();
|
||||
}
|
||||
|
||||
void CGUIMessageBox::setButton(IGUIButton*& button, bool isAvailable, const core::rect<s32> & btnRect, const wchar_t * text, IGUIElement*& focusMe)
|
||||
{
|
||||
// add/remove ok button
|
||||
if (isAvailable)
|
||||
{
|
||||
if (!button)
|
||||
{
|
||||
button = Environment->addButton(btnRect, this);
|
||||
button->setSubElement(true);
|
||||
button->grab();
|
||||
}
|
||||
else
|
||||
button->setRelativePosition(btnRect);
|
||||
|
||||
button->setText(text);
|
||||
|
||||
focusMe = button;
|
||||
}
|
||||
else if (button)
|
||||
{
|
||||
button->drop();
|
||||
button->remove();
|
||||
button =0;
|
||||
}
|
||||
}
|
||||
|
||||
void CGUIMessageBox::refreshControls()
|
||||
{
|
||||
// Layout can be seen as 4 boxes (a layoutmanager would be nice)
|
||||
// One box at top over the whole width for title
|
||||
// Two boxes with same height at the middle beside each other for icon and for text
|
||||
// One box at the bottom for the buttons
|
||||
|
||||
const IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
const s32 buttonHeight = skin->getSize(EGDS_BUTTON_HEIGHT);
|
||||
const s32 buttonWidth = skin->getSize(EGDS_BUTTON_WIDTH);
|
||||
const s32 titleHeight = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH)+2; // titlebar has no own constant
|
||||
const s32 buttonDistance = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
|
||||
const s32 borderWidth = skin->getSize(EGDS_MESSAGE_BOX_GAP_SPACE);
|
||||
|
||||
// add the static text for the message
|
||||
core::rect<s32> staticRect;
|
||||
staticRect.UpperLeftCorner.X = borderWidth;
|
||||
staticRect.UpperLeftCorner.Y = titleHeight + borderWidth;
|
||||
staticRect.LowerRightCorner.X = staticRect.UpperLeftCorner.X + skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH);
|
||||
staticRect.LowerRightCorner.Y = staticRect.UpperLeftCorner.Y + skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT);
|
||||
if (!StaticText)
|
||||
{
|
||||
StaticText = Environment->addStaticText(MessageText.c_str(), staticRect, false, false, this);
|
||||
|
||||
StaticText->setWordWrap(true);
|
||||
StaticText->setSubElement(true);
|
||||
StaticText->grab();
|
||||
}
|
||||
else
|
||||
{
|
||||
StaticText->setRelativePosition(staticRect);
|
||||
StaticText->setText(MessageText.c_str());
|
||||
}
|
||||
|
||||
s32 textHeight = StaticText->getTextHeight();
|
||||
s32 textWidth = StaticText->getTextWidth() + 6; // +6 because the static itself needs that
|
||||
const s32 iconHeight = IconTexture ? IconTexture->getOriginalSize().Height : 0;
|
||||
|
||||
if ( textWidth < skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH) )
|
||||
textWidth = skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH) + 6;
|
||||
// no neeed to check for max because it couldn't get larger due to statictextbox.
|
||||
if ( textHeight < skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT) )
|
||||
textHeight = skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT);
|
||||
if ( textHeight > skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT) )
|
||||
textHeight = skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT);
|
||||
|
||||
// content is text + icons + borders (but not titlebar)
|
||||
s32 contentHeight = textHeight > iconHeight ? textHeight : iconHeight;
|
||||
contentHeight += borderWidth;
|
||||
s32 contentWidth = 0;
|
||||
|
||||
// add icon
|
||||
if ( IconTexture )
|
||||
{
|
||||
core::position2d<s32> iconPos;
|
||||
iconPos.Y = titleHeight + borderWidth;
|
||||
if ( iconHeight < textHeight )
|
||||
iconPos.Y += (textHeight-iconHeight) / 2;
|
||||
iconPos.X = borderWidth;
|
||||
|
||||
if (!Icon)
|
||||
{
|
||||
Icon = Environment->addImage(IconTexture, iconPos, true, this);
|
||||
Icon->setSubElement(true);
|
||||
Icon->grab();
|
||||
}
|
||||
else
|
||||
{
|
||||
core::rect<s32> iconRect( iconPos.X, iconPos.Y, iconPos.X + IconTexture->getOriginalSize().Width, iconPos.Y + IconTexture->getOriginalSize().Height );
|
||||
Icon->setRelativePosition(iconRect);
|
||||
}
|
||||
|
||||
contentWidth += borderWidth + IconTexture->getOriginalSize().Width;
|
||||
}
|
||||
else if ( Icon )
|
||||
{
|
||||
Icon->drop();
|
||||
Icon->remove();
|
||||
Icon = 0;
|
||||
}
|
||||
|
||||
// position text
|
||||
core::rect<s32> textRect;
|
||||
textRect.UpperLeftCorner.X = contentWidth + borderWidth;
|
||||
textRect.UpperLeftCorner.Y = titleHeight + borderWidth;
|
||||
if ( textHeight < iconHeight )
|
||||
textRect.UpperLeftCorner.Y += (iconHeight-textHeight) / 2;
|
||||
textRect.LowerRightCorner.X = textRect.UpperLeftCorner.X + textWidth;
|
||||
textRect.LowerRightCorner.Y = textRect.UpperLeftCorner.Y + textHeight;
|
||||
contentWidth += 2*borderWidth + textWidth;
|
||||
StaticText->setRelativePosition( textRect );
|
||||
|
||||
// find out button size needs
|
||||
s32 countButtons = 0;
|
||||
if (Flags & EMBF_OK)
|
||||
++countButtons;
|
||||
if (Flags & EMBF_CANCEL)
|
||||
++countButtons;
|
||||
if (Flags & EMBF_YES)
|
||||
++countButtons;
|
||||
if (Flags & EMBF_NO)
|
||||
++countButtons;
|
||||
|
||||
s32 buttonBoxWidth = countButtons * buttonWidth + 2 * borderWidth;
|
||||
if ( countButtons > 1 )
|
||||
buttonBoxWidth += (countButtons-1) * buttonDistance;
|
||||
s32 buttonBoxHeight = buttonHeight + 2 * borderWidth;
|
||||
|
||||
// calc new message box sizes
|
||||
core::rect<s32> tmp = getRelativePosition();
|
||||
s32 msgBoxHeight = titleHeight + contentHeight + buttonBoxHeight;
|
||||
s32 msgBoxWidth = contentWidth > buttonBoxWidth ? contentWidth : buttonBoxWidth;
|
||||
|
||||
// adjust message box position
|
||||
tmp.UpperLeftCorner.Y = (Parent->getAbsolutePosition().getHeight() - msgBoxHeight) / 2;
|
||||
tmp.LowerRightCorner.Y = tmp.UpperLeftCorner.Y + msgBoxHeight;
|
||||
tmp.UpperLeftCorner.X = (Parent->getAbsolutePosition().getWidth() - msgBoxWidth) / 2;
|
||||
tmp.LowerRightCorner.X = tmp.UpperLeftCorner.X + msgBoxWidth;
|
||||
setRelativePosition(tmp);
|
||||
|
||||
// add buttons
|
||||
|
||||
core::rect<s32> btnRect;
|
||||
btnRect.UpperLeftCorner.Y = titleHeight + contentHeight + borderWidth;
|
||||
btnRect.LowerRightCorner.Y = btnRect.UpperLeftCorner.Y + buttonHeight;
|
||||
btnRect.UpperLeftCorner.X = borderWidth;
|
||||
if ( contentWidth > buttonBoxWidth )
|
||||
btnRect.UpperLeftCorner.X += (contentWidth - buttonBoxWidth) / 2; // center buttons
|
||||
btnRect.LowerRightCorner.X = btnRect.UpperLeftCorner.X + buttonWidth;
|
||||
|
||||
IGUIElement* focusMe = 0;
|
||||
setButton(OkButton, (Flags & EMBF_OK) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_OK), focusMe);
|
||||
if ( Flags & EMBF_OK )
|
||||
btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0);
|
||||
setButton(CancelButton, (Flags & EMBF_CANCEL) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_CANCEL), focusMe);
|
||||
if ( Flags & EMBF_CANCEL )
|
||||
btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0);
|
||||
setButton(YesButton, (Flags & EMBF_YES) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_YES), focusMe);
|
||||
if ( Flags & EMBF_YES )
|
||||
btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0);
|
||||
setButton(NoButton, (Flags & EMBF_NO) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_NO), focusMe);
|
||||
|
||||
if (Environment->hasFocus(this) && focusMe)
|
||||
Environment->setFocus(focusMe);
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIMessageBox::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
SEvent outevent;
|
||||
outevent.EventType = EET_GUI_EVENT;
|
||||
outevent.GUIEvent.Caller = this;
|
||||
outevent.GUIEvent.Element = 0;
|
||||
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
|
||||
if (event.KeyInput.PressedDown)
|
||||
{
|
||||
switch (event.KeyInput.Key)
|
||||
{
|
||||
case IRR_KEY_RETURN:
|
||||
if (OkButton)
|
||||
{
|
||||
OkButton->setPressed(true);
|
||||
Pressed = true;
|
||||
}
|
||||
break;
|
||||
case IRR_KEY_Y:
|
||||
if (YesButton)
|
||||
{
|
||||
YesButton->setPressed(true);
|
||||
Pressed = true;
|
||||
}
|
||||
break;
|
||||
case IRR_KEY_N:
|
||||
if (NoButton)
|
||||
{
|
||||
NoButton->setPressed(true);
|
||||
Pressed = true;
|
||||
}
|
||||
break;
|
||||
case IRR_KEY_ESCAPE:
|
||||
if (Pressed)
|
||||
{
|
||||
// cancel press
|
||||
if (OkButton) OkButton->setPressed(false);
|
||||
if (YesButton) YesButton->setPressed(false);
|
||||
if (NoButton) NoButton->setPressed(false);
|
||||
Pressed = false;
|
||||
}
|
||||
else
|
||||
if (CancelButton)
|
||||
{
|
||||
CancelButton->setPressed(true);
|
||||
Pressed = true;
|
||||
}
|
||||
else
|
||||
if (CloseButton && CloseButton->isVisible())
|
||||
{
|
||||
CloseButton->setPressed(true);
|
||||
Pressed = true;
|
||||
}
|
||||
break;
|
||||
default: // no other key is handled here
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (Pressed)
|
||||
{
|
||||
if (OkButton && event.KeyInput.Key == IRR_KEY_RETURN)
|
||||
{
|
||||
setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC
|
||||
Environment->setFocus(0);
|
||||
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK;
|
||||
Parent->OnEvent(outevent);
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if ((CancelButton || CloseButton) && event.KeyInput.Key == IRR_KEY_ESCAPE)
|
||||
{
|
||||
setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC
|
||||
Environment->setFocus(0);
|
||||
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL;
|
||||
Parent->OnEvent(outevent);
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (YesButton && event.KeyInput.Key == IRR_KEY_Y)
|
||||
{
|
||||
setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC
|
||||
Environment->setFocus(0);
|
||||
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES;
|
||||
Parent->OnEvent(outevent);
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (NoButton && event.KeyInput.Key == IRR_KEY_N)
|
||||
{
|
||||
setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC
|
||||
Environment->setFocus(0);
|
||||
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_NO;
|
||||
Parent->OnEvent(outevent);
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EET_GUI_EVENT:
|
||||
if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
|
||||
{
|
||||
if (event.GUIEvent.Caller == OkButton)
|
||||
{
|
||||
setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC
|
||||
Environment->setFocus(0);
|
||||
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK;
|
||||
Parent->OnEvent(outevent);
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.Caller == CancelButton ||
|
||||
event.GUIEvent.Caller == CloseButton)
|
||||
{
|
||||
setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC
|
||||
Environment->setFocus(0);
|
||||
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL;
|
||||
Parent->OnEvent(outevent);
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.Caller == YesButton)
|
||||
{
|
||||
setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC
|
||||
Environment->setFocus(0);
|
||||
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES;
|
||||
Parent->OnEvent(outevent);
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.Caller == NoButton)
|
||||
{
|
||||
setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC
|
||||
Environment->setFocus(0);
|
||||
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_NO;
|
||||
Parent->OnEvent(outevent);
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CGUIWindow::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIMessageBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
CGUIWindow::serializeAttributes(out,options);
|
||||
|
||||
out->addBool ("OkayButton", (Flags & EMBF_OK) != 0 );
|
||||
out->addBool ("CancelButton", (Flags & EMBF_CANCEL) != 0 );
|
||||
out->addBool ("YesButton", (Flags & EMBF_YES) != 0 );
|
||||
out->addBool ("NoButton", (Flags & EMBF_NO) != 0 );
|
||||
out->addTexture ("Texture", IconTexture);
|
||||
|
||||
out->addString ("MessageText", MessageText.c_str());
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIMessageBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
Flags = 0;
|
||||
|
||||
Flags = in->getAttributeAsBool("OkayButton") ? EMBF_OK : 0;
|
||||
Flags |= in->getAttributeAsBool("CancelButton")? EMBF_CANCEL : 0;
|
||||
Flags |= in->getAttributeAsBool("YesButton") ? EMBF_YES : 0;
|
||||
Flags |= in->getAttributeAsBool("NoButton") ? EMBF_NO : 0;
|
||||
|
||||
if ( IconTexture )
|
||||
{
|
||||
IconTexture->drop();
|
||||
IconTexture = NULL;
|
||||
}
|
||||
IconTexture = in->getAttributeAsTexture("Texture");
|
||||
if ( IconTexture )
|
||||
IconTexture->grab();
|
||||
|
||||
MessageText = in->getAttributeAsStringW("MessageText").c_str();
|
||||
|
||||
CGUIWindow::deserializeAttributes(in,options);
|
||||
|
||||
refreshControls();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_MESSAGE_BOX_H_INCLUDED__
|
||||
#define __C_GUI_MESSAGE_BOX_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "CGUIWindow.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "IGUIImage.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class CGUIMessageBox : public CGUIWindow
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIMessageBox(IGUIEnvironment* environment, const wchar_t* caption,
|
||||
const wchar_t* text, s32 flag,
|
||||
IGUIElement* parent, s32 id, core::rect<s32> rectangle, video::ITexture* image=0);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIMessageBox();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
private:
|
||||
|
||||
void refreshControls();
|
||||
void setButton(IGUIButton*& button, bool isAvailable, const core::rect<s32> & btnRect, const wchar_t * text, IGUIElement*& focusMe);
|
||||
|
||||
IGUIButton* OkButton;
|
||||
IGUIButton* CancelButton;
|
||||
IGUIButton* YesButton;
|
||||
IGUIButton* NoButton;
|
||||
IGUIStaticText* StaticText;
|
||||
IGUIImage * Icon;
|
||||
video::ITexture * IconTexture;
|
||||
|
||||
s32 Flags;
|
||||
core::stringw MessageText;
|
||||
bool Pressed;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,235 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIModalScreen.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "os.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUISkin.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIModalScreen::CGUIModalScreen(IGUIEnvironment* environment, IGUIElement* parent, s32 id)
|
||||
: IGUIElement(EGUIET_MODAL_SCREEN, environment, parent, id, core::recti(0, 0, parent->getAbsolutePosition().getWidth(), parent->getAbsolutePosition().getHeight()) ),
|
||||
MouseDownTime(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIModalScreen");
|
||||
#endif
|
||||
setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
|
||||
// this element is a tab group
|
||||
setTabGroup(true);
|
||||
}
|
||||
|
||||
bool CGUIModalScreen::canTakeFocus(IGUIElement* target) const
|
||||
{
|
||||
return (target && ((const IGUIElement*)target == this // this element can take it
|
||||
|| isMyChild(target) // own children also
|
||||
|| (target->getType() == EGUIET_MODAL_SCREEN ) // other modals also fine (is now on top or explicitely requested)
|
||||
|| (target->getParent() && target->getParent()->getType() == EGUIET_MODAL_SCREEN ))) // children of other modals will do
|
||||
;
|
||||
}
|
||||
|
||||
bool CGUIModalScreen::isVisible() const
|
||||
{
|
||||
// any parent invisible?
|
||||
IGUIElement * parentElement = getParent();
|
||||
while ( parentElement )
|
||||
{
|
||||
if ( !parentElement->isVisible() )
|
||||
return false;
|
||||
parentElement = parentElement->getParent();
|
||||
}
|
||||
|
||||
// if we have no children then the modal is probably abused as a way to block input
|
||||
if ( Children.empty() )
|
||||
{
|
||||
return IGUIElement::isVisible();
|
||||
}
|
||||
|
||||
// any child visible?
|
||||
bool visible = false;
|
||||
core::list<IGUIElement*>::ConstIterator it = Children.begin();
|
||||
for (; it != Children.end(); ++it)
|
||||
{
|
||||
if ( (*it)->isVisible() )
|
||||
{
|
||||
visible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return visible;
|
||||
}
|
||||
|
||||
bool CGUIModalScreen::isPointInside(const core::position2d<s32>& point) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIModalScreen::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (!isEnabled() || !isVisible() )
|
||||
return IGUIElement::OnEvent(event);
|
||||
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUSED:
|
||||
if ( event.GUIEvent.Caller == this && isMyChild(event.GUIEvent.Element) )
|
||||
{
|
||||
Environment->removeFocus(0); // can't setFocus otherwise at it still has focus here
|
||||
Environment->setFocus(event.GUIEvent.Element);
|
||||
MouseDownTime = os::Timer::getTime();
|
||||
return true;
|
||||
}
|
||||
if ( !canTakeFocus(event.GUIEvent.Caller))
|
||||
{
|
||||
if ( !Children.empty() )
|
||||
Environment->setFocus(*(Children.begin()));
|
||||
else
|
||||
Environment->setFocus(this);
|
||||
}
|
||||
IGUIElement::OnEvent(event);
|
||||
return false;
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
if ( !canTakeFocus(event.GUIEvent.Element))
|
||||
{
|
||||
if ( isMyChild(event.GUIEvent.Caller) )
|
||||
{
|
||||
if ( !Children.empty() )
|
||||
Environment->setFocus(*(Children.begin()));
|
||||
else
|
||||
Environment->setFocus(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
MouseDownTime = os::Timer::getTime();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
case EGET_ELEMENT_CLOSED:
|
||||
// do not interfere with children being removed
|
||||
return IGUIElement::OnEvent(event);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
|
||||
{
|
||||
MouseDownTime = os::Timer::getTime();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
IGUIElement::OnEvent(event); // anyone knows why events are passed on here? Causes p.e. problems when this is child of a CGUIWindow.
|
||||
|
||||
return true; // absorb everything else
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIModalScreen::draw()
|
||||
{
|
||||
IGUISkin *skin = Environment->getSkin();
|
||||
|
||||
if (!skin)
|
||||
return;
|
||||
|
||||
u32 now = os::Timer::getTime();
|
||||
if (now - MouseDownTime < 300 && (now / 70)%2)
|
||||
{
|
||||
core::list<IGUIElement*>::Iterator it = Children.begin();
|
||||
core::rect<s32> r;
|
||||
video::SColor c = Environment->getSkin()->getColor(gui::EGDC_3D_HIGH_LIGHT);
|
||||
|
||||
for (; it != Children.end(); ++it)
|
||||
{
|
||||
if ((*it)->isVisible())
|
||||
{
|
||||
r = (*it)->getAbsolutePosition();
|
||||
r.LowerRightCorner.X += 1;
|
||||
r.LowerRightCorner.Y += 1;
|
||||
r.UpperLeftCorner.X -= 1;
|
||||
r.UpperLeftCorner.Y -= 1;
|
||||
|
||||
skin->draw2DRectangle(this, c, r, &AbsoluteClippingRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! Removes a child.
|
||||
void CGUIModalScreen::removeChild(IGUIElement* child)
|
||||
{
|
||||
IGUIElement::removeChild(child);
|
||||
|
||||
if (Children.empty())
|
||||
{
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! adds a child
|
||||
void CGUIModalScreen::addChild(IGUIElement* child)
|
||||
{
|
||||
IGUIElement::addChild(child);
|
||||
Environment->setFocus(child);
|
||||
}
|
||||
|
||||
|
||||
void CGUIModalScreen::updateAbsolutePosition()
|
||||
{
|
||||
core::rect<s32> parentRect(0,0,0,0);
|
||||
|
||||
if (Parent)
|
||||
{
|
||||
parentRect = Parent->getAbsolutePosition();
|
||||
RelativeRect.UpperLeftCorner.X = 0;
|
||||
RelativeRect.UpperLeftCorner.Y = 0;
|
||||
RelativeRect.LowerRightCorner.X = parentRect.getWidth();
|
||||
RelativeRect.LowerRightCorner.Y = parentRect.getHeight();
|
||||
}
|
||||
|
||||
IGUIElement::updateAbsolutePosition();
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIModalScreen::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIElement::serializeAttributes(out,options);
|
||||
}
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIModalScreen::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIElement::deserializeAttributes(in, options);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_MODAL_SCREEN_H_INCLUDED__
|
||||
#define __C_GUI_MODAL_SCREEN_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIElement.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIModalScreen : public IGUIElement
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIModalScreen(IGUIEnvironment* environment, IGUIElement* parent, s32 id);
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! Removes a child.
|
||||
virtual void removeChild(IGUIElement* child);
|
||||
|
||||
//! Adds a child
|
||||
virtual void addChild(IGUIElement* child);
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Updates the absolute position.
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
//! Modalscreen is not a typical element, but rather acts like a state for it's children.
|
||||
//! isVisible is overriden to give this a useful behavior, so that a modal will no longer
|
||||
//! be active when its parent is invisible or all its children are invisible.
|
||||
virtual bool isVisible() const;
|
||||
|
||||
//! Modals are infinite so every point is inside
|
||||
virtual bool isPointInside(const core::position2d<s32>& point) const;
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
protected:
|
||||
virtual bool canTakeFocus(IGUIElement* target) const;
|
||||
|
||||
private:
|
||||
|
||||
u32 MouseDownTime;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,572 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIScrollBar.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "CGUIButton.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUIFontBitmap.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CGUIScrollBar::CGUIScrollBar(bool horizontal, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id,
|
||||
core::rect<s32> rectangle, bool noclip)
|
||||
: IGUIScrollBar(environment, parent, id, rectangle), UpButton(0),
|
||||
DownButton(0), Dragging(false), Horizontal(horizontal),
|
||||
DraggedBySlider(false), TrayClick(false), Pos(0), DrawPos(0),
|
||||
DrawHeight(0), Min(0), Max(100), SmallStep(10), LargeStep(50), DesiredPos(0),
|
||||
LastChange(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIScrollBar");
|
||||
#endif
|
||||
|
||||
refreshControls();
|
||||
|
||||
setNotClipped(noclip);
|
||||
|
||||
// this element can be tabbed to
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
|
||||
setPos(0);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIScrollBar::~CGUIScrollBar()
|
||||
{
|
||||
if (UpButton)
|
||||
UpButton->drop();
|
||||
|
||||
if (DownButton)
|
||||
DownButton->drop();
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIScrollBar::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (event.KeyInput.PressedDown)
|
||||
{
|
||||
const s32 oldPos = Pos;
|
||||
bool absorb = true;
|
||||
switch (event.KeyInput.Key)
|
||||
{
|
||||
case IRR_KEY_LEFT:
|
||||
case IRR_KEY_UP:
|
||||
setPos(Pos-SmallStep);
|
||||
break;
|
||||
case IRR_KEY_RIGHT:
|
||||
case IRR_KEY_DOWN:
|
||||
setPos(Pos+SmallStep);
|
||||
break;
|
||||
case IRR_KEY_HOME:
|
||||
setPos(Min);
|
||||
break;
|
||||
case IRR_KEY_PRIOR:
|
||||
setPos(Pos-LargeStep);
|
||||
break;
|
||||
case IRR_KEY_END:
|
||||
setPos(Max);
|
||||
break;
|
||||
case IRR_KEY_NEXT:
|
||||
setPos(Pos+LargeStep);
|
||||
break;
|
||||
default:
|
||||
absorb = false;
|
||||
}
|
||||
|
||||
if (Pos != oldPos)
|
||||
{
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
if (absorb)
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EET_GUI_EVENT:
|
||||
if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
|
||||
{
|
||||
if (event.GUIEvent.Caller == UpButton)
|
||||
setPos(Pos-SmallStep);
|
||||
else
|
||||
if (event.GUIEvent.Caller == DownButton)
|
||||
setPos(Pos+SmallStep);
|
||||
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
|
||||
{
|
||||
if (event.GUIEvent.Caller == this)
|
||||
Dragging = false;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
{
|
||||
const core::position2di p(event.MouseInput.X, event.MouseInput.Y);
|
||||
bool isInside = isPointInside ( p );
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
if (Environment->hasFocus(this))
|
||||
{
|
||||
// thanks to a bug report by REAPER
|
||||
// thanks to tommi by tommi for another bugfix
|
||||
// everybody needs a little thanking. hallo niko!;-)
|
||||
setPos( getPos() +
|
||||
( event.MouseInput.Wheel * SmallStep * (Horizontal ? 1 : -1 ) )
|
||||
);
|
||||
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
{
|
||||
if (isInside)
|
||||
{
|
||||
Dragging = true;
|
||||
DraggedBySlider = SliderRect.isPointInside(p);
|
||||
TrayClick = !DraggedBySlider;
|
||||
DesiredPos = getPosFromMousePos(p);
|
||||
Environment->setFocus ( this );
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
case EMIE_MOUSE_MOVED:
|
||||
{
|
||||
if ( !event.MouseInput.isLeftPressed () )
|
||||
Dragging = false;
|
||||
|
||||
if ( !Dragging )
|
||||
{
|
||||
if ( event.MouseInput.Event == EMIE_MOUSE_MOVED )
|
||||
break;
|
||||
return isInside;
|
||||
}
|
||||
|
||||
if ( event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP )
|
||||
Dragging = false;
|
||||
|
||||
const s32 newPos = getPosFromMousePos(p);
|
||||
const s32 oldPos = Pos;
|
||||
|
||||
if (!DraggedBySlider)
|
||||
{
|
||||
if ( isInside )
|
||||
{
|
||||
DraggedBySlider = SliderRect.isPointInside(p);
|
||||
TrayClick = !DraggedBySlider;
|
||||
}
|
||||
|
||||
if (DraggedBySlider)
|
||||
{
|
||||
setPos(newPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
TrayClick = false;
|
||||
if (event.MouseInput.Event == EMIE_MOUSE_MOVED)
|
||||
return isInside;
|
||||
}
|
||||
}
|
||||
|
||||
if (DraggedBySlider)
|
||||
{
|
||||
setPos(newPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
DesiredPos = newPos;
|
||||
}
|
||||
|
||||
if (Pos != oldPos && Parent)
|
||||
{
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
return isInside;
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
void CGUIScrollBar::OnPostRender(u32 timeMs)
|
||||
{
|
||||
if (Dragging && !DraggedBySlider && TrayClick && timeMs > LastChange + 200)
|
||||
{
|
||||
LastChange = timeMs;
|
||||
|
||||
const s32 oldPos = Pos;
|
||||
|
||||
if (DesiredPos >= Pos + LargeStep)
|
||||
setPos(Pos + LargeStep);
|
||||
else
|
||||
if (DesiredPos <= Pos - LargeStep)
|
||||
setPos(Pos - LargeStep);
|
||||
else
|
||||
if (DesiredPos >= Pos - LargeStep && DesiredPos <= Pos + LargeStep)
|
||||
setPos(DesiredPos);
|
||||
|
||||
if (Pos != oldPos && Parent)
|
||||
{
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIScrollBar::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
|
||||
|
||||
video::SColor iconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
|
||||
if ( iconColor != CurrentIconColor )
|
||||
{
|
||||
refreshControls();
|
||||
}
|
||||
|
||||
|
||||
SliderRect = AbsoluteRect;
|
||||
|
||||
// draws the background
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_SCROLLBAR), SliderRect, &AbsoluteClippingRect);
|
||||
|
||||
if ( core::isnotzero ( range() ) )
|
||||
{
|
||||
// recalculate slider rectangle
|
||||
if (Horizontal)
|
||||
{
|
||||
SliderRect.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X + DrawPos + RelativeRect.getHeight() - DrawHeight/2;
|
||||
SliderRect.LowerRightCorner.X = SliderRect.UpperLeftCorner.X + DrawHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
SliderRect.UpperLeftCorner.Y = AbsoluteRect.UpperLeftCorner.Y + DrawPos + RelativeRect.getWidth() - DrawHeight/2;
|
||||
SliderRect.LowerRightCorner.Y = SliderRect.UpperLeftCorner.Y + DrawHeight;
|
||||
}
|
||||
|
||||
skin->draw3DButtonPaneStandard(this, SliderRect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
// draw buttons
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
void CGUIScrollBar::updateAbsolutePosition()
|
||||
{
|
||||
IGUIElement::updateAbsolutePosition();
|
||||
// todo: properly resize
|
||||
refreshControls();
|
||||
setPos ( Pos );
|
||||
}
|
||||
|
||||
//!
|
||||
s32 CGUIScrollBar::getPosFromMousePos(const core::position2di &pos) const
|
||||
{
|
||||
f32 w, p;
|
||||
if (Horizontal)
|
||||
{
|
||||
w = RelativeRect.getWidth() - f32(RelativeRect.getHeight())*3.0f;
|
||||
p = pos.X - AbsoluteRect.UpperLeftCorner.X - RelativeRect.getHeight()*1.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
w = RelativeRect.getHeight() - f32(RelativeRect.getWidth())*3.0f;
|
||||
p = pos.Y - AbsoluteRect.UpperLeftCorner.Y - RelativeRect.getWidth()*1.5f;
|
||||
}
|
||||
return (s32) ( p/w * range() ) + Min;
|
||||
}
|
||||
|
||||
|
||||
//! sets the position of the scrollbar
|
||||
void CGUIScrollBar::setPos(s32 pos)
|
||||
{
|
||||
Pos = core::s32_clamp ( pos, Min, Max );
|
||||
|
||||
if ( !core::isnotzero ( range() ) )
|
||||
return;
|
||||
|
||||
if (Horizontal)
|
||||
{
|
||||
f32 f = (RelativeRect.getWidth() - ((f32)RelativeRect.getHeight()*3.0f)) / range();
|
||||
DrawPos = (s32)( ( ( Pos - Min ) * f) + ((f32)RelativeRect.getHeight() * 0.5f));
|
||||
DrawHeight = RelativeRect.getHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
f32 f = (RelativeRect.getHeight() - ((f32)RelativeRect.getWidth()*3.0f)) / range();
|
||||
|
||||
DrawPos = (s32)( ( ( Pos - Min ) * f) + ((f32)RelativeRect.getWidth() * 0.5f));
|
||||
DrawHeight = RelativeRect.getWidth();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! gets the small step value
|
||||
s32 CGUIScrollBar::getSmallStep() const
|
||||
{
|
||||
return SmallStep;
|
||||
}
|
||||
|
||||
|
||||
//! sets the small step value
|
||||
void CGUIScrollBar::setSmallStep(s32 step)
|
||||
{
|
||||
if (step > 0)
|
||||
SmallStep = step;
|
||||
else
|
||||
SmallStep = 10;
|
||||
}
|
||||
|
||||
|
||||
//! gets the small step value
|
||||
s32 CGUIScrollBar::getLargeStep() const
|
||||
{
|
||||
return LargeStep;
|
||||
}
|
||||
|
||||
|
||||
//! sets the small step value
|
||||
void CGUIScrollBar::setLargeStep(s32 step)
|
||||
{
|
||||
if (step > 0)
|
||||
LargeStep = step;
|
||||
else
|
||||
LargeStep = 50;
|
||||
}
|
||||
|
||||
|
||||
//! gets the maximum value of the scrollbar.
|
||||
s32 CGUIScrollBar::getMax() const
|
||||
{
|
||||
return Max;
|
||||
}
|
||||
|
||||
|
||||
//! sets the maximum value of the scrollbar.
|
||||
void CGUIScrollBar::setMax(s32 max)
|
||||
{
|
||||
Max = max;
|
||||
if ( Min > Max )
|
||||
Min = Max;
|
||||
|
||||
bool enable = core::isnotzero ( range() );
|
||||
UpButton->setEnabled(enable);
|
||||
DownButton->setEnabled(enable);
|
||||
setPos(Pos);
|
||||
}
|
||||
|
||||
//! gets the minimum value of the scrollbar.
|
||||
s32 CGUIScrollBar::getMin() const
|
||||
{
|
||||
return Min;
|
||||
}
|
||||
|
||||
|
||||
//! sets the minimum value of the scrollbar.
|
||||
void CGUIScrollBar::setMin(s32 min)
|
||||
{
|
||||
Min = min;
|
||||
if ( Max < Min )
|
||||
Max = Min;
|
||||
|
||||
|
||||
bool enable = core::isnotzero ( range() );
|
||||
UpButton->setEnabled(enable);
|
||||
DownButton->setEnabled(enable);
|
||||
setPos(Pos);
|
||||
}
|
||||
|
||||
|
||||
//! gets the current position of the scrollbar
|
||||
s32 CGUIScrollBar::getPos() const
|
||||
{
|
||||
return Pos;
|
||||
}
|
||||
|
||||
|
||||
//! refreshes the position and text on child buttons
|
||||
void CGUIScrollBar::refreshControls()
|
||||
{
|
||||
CurrentIconColor = video::SColor(255,255,255,255);
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
IGUISpriteBank* sprites = 0;
|
||||
|
||||
if (skin)
|
||||
{
|
||||
sprites = skin->getSpriteBank();
|
||||
CurrentIconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
|
||||
}
|
||||
|
||||
if (Horizontal)
|
||||
{
|
||||
s32 h = RelativeRect.getHeight();
|
||||
if (!UpButton)
|
||||
{
|
||||
UpButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,0, h, h), NoClip);
|
||||
UpButton->setSubElement(true);
|
||||
UpButton->setTabStop(false);
|
||||
}
|
||||
if (sprites)
|
||||
{
|
||||
UpButton->setSpriteBank(sprites);
|
||||
UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor);
|
||||
UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor);
|
||||
}
|
||||
UpButton->setRelativePosition(core::rect<s32>(0,0, h, h));
|
||||
UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
if (!DownButton)
|
||||
{
|
||||
DownButton = new CGUIButton(Environment, this, -1, core::rect<s32>(RelativeRect.getWidth()-h, 0, RelativeRect.getWidth(), h), NoClip);
|
||||
DownButton->setSubElement(true);
|
||||
DownButton->setTabStop(false);
|
||||
}
|
||||
if (sprites)
|
||||
{
|
||||
DownButton->setSpriteBank(sprites);
|
||||
DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor);
|
||||
DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor);
|
||||
}
|
||||
DownButton->setRelativePosition(core::rect<s32>(RelativeRect.getWidth()-h, 0, RelativeRect.getWidth(), h));
|
||||
DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 w = RelativeRect.getWidth();
|
||||
if (!UpButton)
|
||||
{
|
||||
UpButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,0, w, w), NoClip);
|
||||
UpButton->setSubElement(true);
|
||||
UpButton->setTabStop(false);
|
||||
}
|
||||
if (sprites)
|
||||
{
|
||||
UpButton->setSpriteBank(sprites);
|
||||
UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor);
|
||||
UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor);
|
||||
}
|
||||
UpButton->setRelativePosition(core::rect<s32>(0,0, w, w));
|
||||
UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
if (!DownButton)
|
||||
{
|
||||
DownButton = new CGUIButton(Environment, this, -1, core::rect<s32>(0,RelativeRect.getHeight()-w, w, RelativeRect.getHeight()), NoClip);
|
||||
DownButton->setSubElement(true);
|
||||
DownButton->setTabStop(false);
|
||||
}
|
||||
if (sprites)
|
||||
{
|
||||
DownButton->setSpriteBank(sprites);
|
||||
DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor);
|
||||
DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor);
|
||||
}
|
||||
DownButton->setRelativePosition(core::rect<s32>(0,RelativeRect.getHeight()-w, w, RelativeRect.getHeight()));
|
||||
DownButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIScrollBar::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIScrollBar::serializeAttributes(out,options);
|
||||
|
||||
out->addBool("Horizontal", Horizontal);
|
||||
out->addInt ("Value", Pos);
|
||||
out->addInt ("Min", Min);
|
||||
out->addInt ("Max", Max);
|
||||
out->addInt ("SmallStep", SmallStep);
|
||||
out->addInt ("LargeStep", LargeStep);
|
||||
// CurrentIconColor - not serialized as continuiously updated
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIScrollBar::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIScrollBar::deserializeAttributes(in,options);
|
||||
|
||||
Horizontal = in->getAttributeAsBool("Horizontal");
|
||||
setMin(in->getAttributeAsInt("Min"));
|
||||
setMax(in->getAttributeAsInt("Max"));
|
||||
setPos(in->getAttributeAsInt("Value"));
|
||||
setSmallStep(in->getAttributeAsInt("SmallStep"));
|
||||
setLargeStep(in->getAttributeAsInt("LargeStep"));
|
||||
// CurrentIconColor - not serialized as continuiously updated
|
||||
|
||||
refreshControls();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_SCROLL_BAR_H_INCLUDED__
|
||||
#define __C_GUI_SCROLL_BAR_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIScrollBar.h"
|
||||
#include "IGUIButton.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIScrollBar : public IGUIScrollBar
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIScrollBar(bool horizontal, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, core::rect<s32> rectangle,
|
||||
bool noclip=false);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIScrollBar();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
virtual void OnPostRender(u32 timeMs);
|
||||
|
||||
|
||||
//! gets the maximum value of the scrollbar.
|
||||
virtual s32 getMax() const;
|
||||
|
||||
//! sets the maximum value of the scrollbar.
|
||||
virtual void setMax(s32 max);
|
||||
|
||||
//! gets the minimum value of the scrollbar.
|
||||
virtual s32 getMin() const;
|
||||
|
||||
//! sets the minimum value of the scrollbar.
|
||||
virtual void setMin(s32 min);
|
||||
|
||||
//! gets the small step value
|
||||
virtual s32 getSmallStep() const;
|
||||
|
||||
//! sets the small step value
|
||||
virtual void setSmallStep(s32 step);
|
||||
|
||||
//! gets the large step value
|
||||
virtual s32 getLargeStep() const;
|
||||
|
||||
//! sets the large step value
|
||||
virtual void setLargeStep(s32 step);
|
||||
|
||||
//! gets the current position of the scrollbar
|
||||
virtual s32 getPos() const;
|
||||
|
||||
//! sets the position of the scrollbar
|
||||
virtual void setPos(s32 pos);
|
||||
|
||||
//! updates the rectangle
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
private:
|
||||
|
||||
void refreshControls();
|
||||
s32 getPosFromMousePos(const core::position2di &p) const;
|
||||
|
||||
IGUIButton* UpButton;
|
||||
IGUIButton* DownButton;
|
||||
|
||||
core::rect<s32> SliderRect;
|
||||
|
||||
bool Dragging;
|
||||
bool Horizontal;
|
||||
bool DraggedBySlider;
|
||||
bool TrayClick;
|
||||
s32 Pos;
|
||||
s32 DrawPos;
|
||||
s32 DrawHeight;
|
||||
s32 Min;
|
||||
s32 Max;
|
||||
s32 SmallStep;
|
||||
s32 LargeStep;
|
||||
s32 DesiredPos;
|
||||
u32 LastChange;
|
||||
video::SColor CurrentIconColor;
|
||||
|
||||
f32 range () const { return (f32) ( Max - Min ); }
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,253 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_SKIN_H_INCLUDED__
|
||||
#define __C_GUI_SKIN_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
class IVideoDriver;
|
||||
}
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUISkin : public IGUISkin
|
||||
{
|
||||
public:
|
||||
|
||||
CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUISkin();
|
||||
|
||||
//! returns default color
|
||||
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const;
|
||||
|
||||
//! sets a default color
|
||||
virtual void setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor);
|
||||
|
||||
//! returns size for the given size type
|
||||
virtual s32 getSize(EGUI_DEFAULT_SIZE size) const;
|
||||
|
||||
//! sets a default size
|
||||
virtual void setSize(EGUI_DEFAULT_SIZE which, s32 size);
|
||||
|
||||
//! returns the default font
|
||||
virtual IGUIFont* getFont(EGUI_DEFAULT_FONT which=EGDF_DEFAULT) const;
|
||||
|
||||
//! sets a default font
|
||||
virtual void setFont(IGUIFont* font, EGUI_DEFAULT_FONT which=EGDF_DEFAULT);
|
||||
|
||||
//! sets the sprite bank used for drawing icons
|
||||
virtual void setSpriteBank(IGUISpriteBank* bank);
|
||||
|
||||
//! gets the sprite bank used for drawing icons
|
||||
virtual IGUISpriteBank* getSpriteBank() const;
|
||||
|
||||
//! Returns a default icon
|
||||
/** Returns the sprite index within the sprite bank */
|
||||
virtual u32 getIcon(EGUI_DEFAULT_ICON icon) const;
|
||||
|
||||
//! Sets a default icon
|
||||
/** Sets the sprite index used for drawing icons like arrows,
|
||||
close buttons and ticks in checkboxes
|
||||
\param icon: Enum specifying which icon to change
|
||||
\param index: The sprite index used to draw this icon */
|
||||
virtual void setIcon(EGUI_DEFAULT_ICON icon, u32 index);
|
||||
|
||||
//! Returns a default text.
|
||||
/** For example for Message box button captions:
|
||||
"OK", "Cancel", "Yes", "No" and so on. */
|
||||
virtual const wchar_t* getDefaultText(EGUI_DEFAULT_TEXT text) const;
|
||||
|
||||
//! Sets a default text.
|
||||
/** For example for Message box button captions:
|
||||
"OK", "Cancel", "Yes", "No" and so on. */
|
||||
virtual void setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText);
|
||||
|
||||
//! draws a standard 3d button pane
|
||||
/** Used for drawing for example buttons in normal state.
|
||||
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
|
||||
EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
|
||||
\param rect: Defining area where to draw.
|
||||
\param clip: Clip area.
|
||||
\param element: Pointer to the element which wishes to draw this. This parameter
|
||||
is usually not used by ISkin, but can be used for example by more complex
|
||||
implementations to find out how to draw the part exactly. */
|
||||
virtual void draw3DButtonPaneStandard(IGUIElement* element,
|
||||
const core::rect<s32>& rect,
|
||||
const core::rect<s32>* clip=0);
|
||||
|
||||
//! draws a pressed 3d button pane
|
||||
/** Used for drawing for example buttons in pressed state.
|
||||
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
|
||||
EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
|
||||
\param rect: Defining area where to draw.
|
||||
\param clip: Clip area.
|
||||
\param element: Pointer to the element which wishes to draw this. This parameter
|
||||
is usually not used by ISkin, but can be used for example by more complex
|
||||
implementations to find out how to draw the part exactly. */
|
||||
virtual void draw3DButtonPanePressed(IGUIElement* element,
|
||||
const core::rect<s32>& rect,
|
||||
const core::rect<s32>* clip=0);
|
||||
|
||||
//! draws a sunken 3d pane
|
||||
/** Used for drawing the background of edit, combo or check boxes.
|
||||
\param element: Pointer to the element which wishes to draw this. This parameter
|
||||
is usually not used by ISkin, but can be used for example by more complex
|
||||
implementations to find out how to draw the part exactly.
|
||||
\param bgcolor: Background color.
|
||||
\param flat: Specifies if the sunken pane should be flat or displayed as sunken
|
||||
deep into the ground.
|
||||
\param rect: Defining area where to draw.
|
||||
\param clip: Clip area. */
|
||||
virtual void draw3DSunkenPane(IGUIElement* element,
|
||||
video::SColor bgcolor, bool flat,
|
||||
bool fillBackGround,
|
||||
const core::rect<s32>& rect,
|
||||
const core::rect<s32>* clip=0);
|
||||
|
||||
//! draws a window background
|
||||
/** Used for drawing the background of dialogs and windows.
|
||||
\param element: Pointer to the element which wishes to draw this. This parameter
|
||||
is usually not used by ISkin, but can be used for example by more complex
|
||||
implementations to find out how to draw the part exactly.
|
||||
\param titleBarColor: Title color.
|
||||
\param drawTitleBar: True to enable title drawing.
|
||||
\param rect: Defining area where to draw.
|
||||
\param clip: Clip area.
|
||||
\param checkClientArea: When set to non-null the function will not draw anything,
|
||||
but will instead return the clientArea which can be used for drawing by the calling window.
|
||||
That is the area without borders and without titlebar.
|
||||
\return Returns rect where it would be good to draw title bar text. This will
|
||||
work even when checkClientArea is set to a non-null value.*/
|
||||
virtual core::rect<s32> draw3DWindowBackground(IGUIElement* element,
|
||||
bool drawTitleBar, video::SColor titleBarColor,
|
||||
const core::rect<s32>& rect,
|
||||
const core::rect<s32>* clip,
|
||||
core::rect<s32>* checkClientArea);
|
||||
|
||||
//! draws a standard 3d menu pane
|
||||
/** Used for drawing for menus and context menus.
|
||||
It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
|
||||
EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
|
||||
\param element: Pointer to the element which wishes to draw this. This parameter
|
||||
is usually not used by ISkin, but can be used for example by more complex
|
||||
implementations to find out how to draw the part exactly.
|
||||
\param rect: Defining area where to draw.
|
||||
\param clip: Clip area. */
|
||||
virtual void draw3DMenuPane(IGUIElement* element,
|
||||
const core::rect<s32>& rect,
|
||||
const core::rect<s32>* clip=0);
|
||||
|
||||
//! draws a standard 3d tool bar
|
||||
/** Used for drawing for toolbars and menus.
|
||||
\param element: Pointer to the element which wishes to draw this. This parameter
|
||||
is usually not used by ISkin, but can be used for example by more complex
|
||||
implementations to find out how to draw the part exactly.
|
||||
\param rect: Defining area where to draw.
|
||||
\param clip: Clip area. */
|
||||
virtual void draw3DToolBar(IGUIElement* element,
|
||||
const core::rect<s32>& rect,
|
||||
const core::rect<s32>* clip=0);
|
||||
|
||||
//! draws a tab button
|
||||
/** Used for drawing for tab buttons on top of tabs.
|
||||
\param element: Pointer to the element which wishes to draw this. This parameter
|
||||
is usually not used by ISkin, but can be used for example by more complex
|
||||
implementations to find out how to draw the part exactly.
|
||||
\param active: Specifies if the tab is currently active.
|
||||
\param rect: Defining area where to draw.
|
||||
\param clip: Clip area. */
|
||||
virtual void draw3DTabButton(IGUIElement* element, bool active,
|
||||
const core::rect<s32>& rect, const core::rect<s32>* clip=0, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT);
|
||||
|
||||
//! draws a tab control body
|
||||
/** \param element: Pointer to the element which wishes to draw this. This parameter
|
||||
is usually not used by ISkin, but can be used for example by more complex
|
||||
implementations to find out how to draw the part exactly.
|
||||
\param border: Specifies if the border should be drawn.
|
||||
\param background: Specifies if the background should be drawn.
|
||||
\param rect: Defining area where to draw.
|
||||
\param clip: Clip area. */
|
||||
virtual void draw3DTabBody(IGUIElement* element, bool border, bool background,
|
||||
const core::rect<s32>& rect, const core::rect<s32>* clip=0, s32 tabHeight=-1, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT);
|
||||
|
||||
//! draws an icon, usually from the skin's sprite bank
|
||||
/** \param element: Pointer to the element which wishes to draw this icon.
|
||||
This parameter is usually not used by IGUISkin, but can be used for example
|
||||
by more complex implementations to find out how to draw the part exactly.
|
||||
\param icon: Specifies the icon to be drawn.
|
||||
\param position: The position to draw the icon
|
||||
\param starttime: The time at the start of the animation
|
||||
\param currenttime: The present time, used to calculate the frame number
|
||||
\param loop: Whether the animation should loop or not
|
||||
\param clip: Clip area. */
|
||||
virtual void drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon,
|
||||
const core::position2di position,
|
||||
u32 starttime=0, u32 currenttime=0,
|
||||
bool loop=false, const core::rect<s32>* clip=0);
|
||||
|
||||
|
||||
//! draws a 2d rectangle.
|
||||
/** \param element: Pointer to the element which wishes to draw this icon.
|
||||
This parameter is usually not used by IGUISkin, but can be used for example
|
||||
by more complex implementations to find out how to draw the part exactly.
|
||||
\param color: Color of the rectangle to draw. The alpha component specifies how
|
||||
transparent the rectangle will be.
|
||||
\param pos: Position of the rectangle.
|
||||
\param clip: Pointer to rectangle against which the rectangle will be clipped.
|
||||
If the pointer is null, no clipping will be performed. */
|
||||
virtual void draw2DRectangle(IGUIElement* element, const video::SColor &color,
|
||||
const core::rect<s32>& pos, const core::rect<s32>* clip = 0);
|
||||
|
||||
|
||||
//! get the type of this skin
|
||||
virtual EGUI_SKIN_TYPE getType() const;
|
||||
|
||||
//! Writes attributes of the object.
|
||||
//! Implement this to expose the attributes of your scene node animator for
|
||||
//! scripting languages, editors, debuggers or xml serialization purposes.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the object.
|
||||
//! Implement this to set the attributes of your scene node animator for
|
||||
//! scripting languages, editors, debuggers or xml deserialization purposes.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
virtual void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
const video::SColor* const colors, bool useAlphaChannelOfTexture);
|
||||
|
||||
private:
|
||||
|
||||
video::SColor Colors[EGDC_COUNT];
|
||||
s32 Sizes[EGDS_COUNT];
|
||||
u32 Icons[EGDI_COUNT];
|
||||
IGUIFont* Fonts[EGDF_COUNT];
|
||||
IGUISpriteBank* SpriteBank;
|
||||
core::stringw Texts[EGDT_COUNT];
|
||||
video::IVideoDriver* Driver;
|
||||
bool UseGradient;
|
||||
|
||||
EGUI_SKIN_TYPE Type;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
// Copyright (C) 2006-2012 Michael Zeilfelder
|
||||
// This file uses the licence of the Irrlicht Engine.
|
||||
|
||||
#include "CGUISpinBox.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "CGUIEditBox.h"
|
||||
#include "CGUIButton.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IEventReceiver.h"
|
||||
#include "fast_atof.h"
|
||||
#include <wchar.h>
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUISpinBox::CGUISpinBox(const wchar_t* text, bool border,IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle)
|
||||
: IGUISpinBox(environment, parent, id, rectangle),
|
||||
EditBox(0), ButtonSpinUp(0), ButtonSpinDown(0), StepSize(1.f),
|
||||
RangeMin(-FLT_MAX), RangeMax(FLT_MAX), FormatString(L"%f"),
|
||||
DecimalPlaces(-1)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUISpinBox");
|
||||
#endif
|
||||
|
||||
CurrentIconColor = video::SColor(255,255,255,255);
|
||||
s32 ButtonWidth = 16;
|
||||
|
||||
ButtonSpinDown = Environment->addButton(
|
||||
core::rect<s32>(rectangle.getWidth() - ButtonWidth, rectangle.getHeight()/2 +1,
|
||||
rectangle.getWidth(), rectangle.getHeight()), this);
|
||||
ButtonSpinDown->grab();
|
||||
ButtonSpinDown->setSubElement(true);
|
||||
ButtonSpinDown->setTabStop(false);
|
||||
ButtonSpinDown->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_CENTER, EGUIA_LOWERRIGHT);
|
||||
|
||||
ButtonSpinUp = Environment->addButton(
|
||||
core::rect<s32>(rectangle.getWidth() - ButtonWidth, 0,
|
||||
rectangle.getWidth(), rectangle.getHeight()/2), this);
|
||||
ButtonSpinUp->grab();
|
||||
ButtonSpinUp->setSubElement(true);
|
||||
ButtonSpinUp->setTabStop(false);
|
||||
ButtonSpinUp->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_CENTER);
|
||||
|
||||
const core::rect<s32> rectEdit(0, 0, rectangle.getWidth() - ButtonWidth - 1, rectangle.getHeight());
|
||||
EditBox = Environment->addEditBox(text, rectEdit, border, this, -1);
|
||||
EditBox->grab();
|
||||
EditBox->setSubElement(true);
|
||||
EditBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
|
||||
refreshSprites();
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUISpinBox::~CGUISpinBox()
|
||||
{
|
||||
if (ButtonSpinUp)
|
||||
ButtonSpinUp->drop();
|
||||
if (ButtonSpinDown)
|
||||
ButtonSpinDown->drop();
|
||||
if (EditBox)
|
||||
EditBox->drop();
|
||||
}
|
||||
|
||||
void CGUISpinBox::refreshSprites()
|
||||
{
|
||||
IGUISpriteBank *sb = 0;
|
||||
if (Environment && Environment->getSkin())
|
||||
{
|
||||
sb = Environment->getSkin()->getSpriteBank();
|
||||
}
|
||||
|
||||
if (sb)
|
||||
{
|
||||
IGUISkin * skin = Environment->getSkin();
|
||||
CurrentIconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
|
||||
ButtonSpinDown->setSpriteBank(sb);
|
||||
ButtonSpinDown->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_SMALL_CURSOR_DOWN), CurrentIconColor);
|
||||
ButtonSpinDown->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_SMALL_CURSOR_DOWN), CurrentIconColor);
|
||||
ButtonSpinUp->setSpriteBank(sb);
|
||||
ButtonSpinUp->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_SMALL_CURSOR_UP), CurrentIconColor);
|
||||
ButtonSpinUp->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_SMALL_CURSOR_UP), CurrentIconColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
ButtonSpinDown->setText(L"-");
|
||||
ButtonSpinUp->setText(L"+");
|
||||
}
|
||||
}
|
||||
|
||||
IGUIEditBox* CGUISpinBox::getEditBox() const
|
||||
{
|
||||
return EditBox;
|
||||
}
|
||||
|
||||
|
||||
void CGUISpinBox::setValue(f32 val)
|
||||
{
|
||||
wchar_t str[100];
|
||||
|
||||
swprintf(str, 99, FormatString.c_str(), val);
|
||||
EditBox->setText(str);
|
||||
verifyValueRange();
|
||||
}
|
||||
|
||||
|
||||
f32 CGUISpinBox::getValue() const
|
||||
{
|
||||
const wchar_t* val = EditBox->getText();
|
||||
if ( !val )
|
||||
return 0.f;
|
||||
core::stringc tmp(val);
|
||||
return core::fast_atof(tmp.c_str());
|
||||
}
|
||||
|
||||
|
||||
void CGUISpinBox::setRange(f32 min, f32 max)
|
||||
{
|
||||
if (max<min)
|
||||
core::swap(min, max);
|
||||
RangeMin = min;
|
||||
RangeMax = max;
|
||||
|
||||
// we have to round the range - otherwise we can get into an infinte setValue/verifyValueRange cycle.
|
||||
wchar_t str[100];
|
||||
swprintf(str, 99, FormatString.c_str(), RangeMin);
|
||||
RangeMin = core::fast_atof(core::stringc(str).c_str());
|
||||
swprintf(str, 99, FormatString.c_str(), RangeMax);
|
||||
RangeMax = core::fast_atof(core::stringc(str).c_str());
|
||||
|
||||
verifyValueRange();
|
||||
}
|
||||
|
||||
|
||||
f32 CGUISpinBox::getMin() const
|
||||
{
|
||||
return RangeMin;
|
||||
}
|
||||
|
||||
|
||||
f32 CGUISpinBox::getMax() const
|
||||
{
|
||||
return RangeMax;
|
||||
}
|
||||
|
||||
|
||||
f32 CGUISpinBox::getStepSize() const
|
||||
{
|
||||
return StepSize;
|
||||
}
|
||||
|
||||
|
||||
void CGUISpinBox::setStepSize(f32 step)
|
||||
{
|
||||
StepSize = step;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the number of decimal places to display.
|
||||
void CGUISpinBox::setDecimalPlaces(s32 places)
|
||||
{
|
||||
DecimalPlaces = places;
|
||||
if (places == -1)
|
||||
FormatString = "%f";
|
||||
else
|
||||
{
|
||||
FormatString = "%.";
|
||||
FormatString += places;
|
||||
FormatString += "f";
|
||||
}
|
||||
setRange( RangeMin, RangeMax );
|
||||
setValue(getValue());
|
||||
}
|
||||
|
||||
|
||||
bool CGUISpinBox::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (IsEnabled)
|
||||
{
|
||||
bool changeEvent = false;
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
{
|
||||
f32 val = getValue() + (StepSize * (event.MouseInput.Wheel < 0 ? -1.f : 1.f));
|
||||
setValue(val);
|
||||
changeEvent = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case EET_GUI_EVENT:
|
||||
if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
|
||||
{
|
||||
if (event.GUIEvent.Caller == ButtonSpinUp)
|
||||
{
|
||||
f32 val = getValue();
|
||||
val += StepSize;
|
||||
setValue(val);
|
||||
changeEvent = true;
|
||||
}
|
||||
else if ( event.GUIEvent.Caller == ButtonSpinDown)
|
||||
{
|
||||
f32 val = getValue();
|
||||
val -= StepSize;
|
||||
setValue(val);
|
||||
changeEvent = true;
|
||||
}
|
||||
}
|
||||
if (event.GUIEvent.EventType == EGET_EDITBOX_CHANGED || event.GUIEvent.EventType == EGET_EDITBOX_ENTER)
|
||||
{
|
||||
if (event.GUIEvent.Caller == EditBox)
|
||||
{
|
||||
verifyValueRange();
|
||||
changeEvent = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( changeEvent )
|
||||
{
|
||||
SEvent e;
|
||||
e.EventType = EET_GUI_EVENT;
|
||||
e.GUIEvent.Caller = this;
|
||||
e.GUIEvent.Element = 0;
|
||||
|
||||
e.GUIEvent.EventType = EGET_SPINBOX_CHANGED;
|
||||
if ( Parent )
|
||||
Parent->OnEvent(e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
void CGUISpinBox::draw()
|
||||
{
|
||||
if ( !isVisible() )
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
|
||||
video::SColor iconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
|
||||
if ( iconColor != CurrentIconColor )
|
||||
{
|
||||
refreshSprites();
|
||||
}
|
||||
|
||||
IGUISpinBox::draw();
|
||||
}
|
||||
|
||||
void CGUISpinBox::verifyValueRange()
|
||||
{
|
||||
f32 val = getValue();
|
||||
if ( val+core::ROUNDING_ERROR_f32 < RangeMin )
|
||||
val = RangeMin;
|
||||
else if ( val-core::ROUNDING_ERROR_f32 > RangeMax )
|
||||
val = RangeMax;
|
||||
else
|
||||
return;
|
||||
|
||||
setValue(val);
|
||||
}
|
||||
|
||||
|
||||
//! Sets the new caption of the element
|
||||
void CGUISpinBox::setText(const core::stringw& text)
|
||||
{
|
||||
EditBox->setText(text);
|
||||
setValue(getValue());
|
||||
verifyValueRange();
|
||||
}
|
||||
|
||||
|
||||
//! Returns caption of this element.
|
||||
const wchar_t* CGUISpinBox::getText() const
|
||||
{
|
||||
return EditBox->getText();
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUISpinBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
IGUIElement::serializeAttributes(out, options);
|
||||
out->addFloat("Min", getMin());
|
||||
out->addFloat("Max", getMax());
|
||||
out->addFloat("Step", getStepSize());
|
||||
out->addInt("DecimalPlaces", DecimalPlaces);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUISpinBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
IGUIElement::deserializeAttributes(in, options);
|
||||
setRange(in->getAttributeAsFloat("Min"), in->getAttributeAsFloat("Max"));
|
||||
setStepSize(in->getAttributeAsFloat("Step"));
|
||||
setDecimalPlaces(in->getAttributeAsInt("DecimalPlaces"));
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright (C) 2006-2012 Michael Zeilfelder
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_SPIN_BOX_H_INCLUDED__
|
||||
#define __C_GUI_SPIN_BOX_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISpinBox.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class IGUIEditBox;
|
||||
class IGUIButton;
|
||||
|
||||
class CGUISpinBox : public IGUISpinBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUISpinBox(const wchar_t* text, bool border, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUISpinBox();
|
||||
|
||||
//! Access the edit box used in the spin control
|
||||
/** \param enable: If set to true, the override color, which can be set
|
||||
with IGUIEditBox::setOverrideColor is used, otherwise the
|
||||
EGDC_BUTTON_TEXT color of the skin. */
|
||||
virtual IGUIEditBox* getEditBox() const;
|
||||
|
||||
//! set the current value of the spinbox
|
||||
/** \param val: value to be set in the spinbox */
|
||||
virtual void setValue(f32 val);
|
||||
|
||||
//! Get the current value of the spinbox
|
||||
virtual f32 getValue() const;
|
||||
|
||||
//! set the range of values which can be used in the spinbox
|
||||
/** \param min: minimum value
|
||||
\param max: maximum value */
|
||||
virtual void setRange(f32 min, f32 max);
|
||||
|
||||
//! get the minimum value which can be used in the spinbox
|
||||
virtual f32 getMin() const;
|
||||
|
||||
//! get the maximum value which can be used in the spinbox
|
||||
virtual f32 getMax() const;
|
||||
|
||||
//! step size by which values are changed when pressing the spin buttons
|
||||
/** \param step: stepsize used for value changes when pressing spin buttons */
|
||||
virtual void setStepSize(f32 step=1.f);
|
||||
|
||||
//! returns the step size
|
||||
virtual f32 getStepSize() const;
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! Draws the element and its children.
|
||||
virtual void draw();
|
||||
|
||||
//! Sets the new caption of the element
|
||||
virtual void setText(const core::stringw& text);
|
||||
|
||||
//! Returns caption of this element.
|
||||
virtual const wchar_t* getText() const;
|
||||
|
||||
//! Sets the number of decimal places to display.
|
||||
//! Note that this also rounds the range to the same number of decimal places.
|
||||
/** \param places: The number of decimal places to display, use -1 to reset */
|
||||
virtual void setDecimalPlaces(s32 places);
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
protected:
|
||||
virtual void verifyValueRange();
|
||||
void refreshSprites();
|
||||
|
||||
IGUIEditBox * EditBox;
|
||||
IGUIButton * ButtonSpinUp;
|
||||
IGUIButton * ButtonSpinDown;
|
||||
video::SColor CurrentIconColor;
|
||||
f32 StepSize;
|
||||
f32 RangeMin;
|
||||
f32 RangeMax;
|
||||
|
||||
core::stringw FormatString;
|
||||
s32 DecimalPlaces;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_SPIN_BOX_H_INCLUDED__
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUISpriteBank.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ITexture.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
CGUISpriteBank::CGUISpriteBank(IGUIEnvironment* env) :
|
||||
Environment(env), Driver(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUISpriteBank");
|
||||
#endif
|
||||
|
||||
if (Environment)
|
||||
{
|
||||
Driver = Environment->getVideoDriver();
|
||||
if (Driver)
|
||||
Driver->grab();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CGUISpriteBank::~CGUISpriteBank()
|
||||
{
|
||||
// drop textures
|
||||
for (u32 i=0; i<Textures.size(); ++i)
|
||||
if (Textures[i])
|
||||
Textures[i]->drop();
|
||||
|
||||
// drop video driver
|
||||
if (Driver)
|
||||
Driver->drop();
|
||||
}
|
||||
|
||||
|
||||
core::array< core::rect<s32> >& CGUISpriteBank::getPositions()
|
||||
{
|
||||
return Rectangles;
|
||||
}
|
||||
|
||||
|
||||
core::array< SGUISprite >& CGUISpriteBank::getSprites()
|
||||
{
|
||||
return Sprites;
|
||||
}
|
||||
|
||||
|
||||
u32 CGUISpriteBank::getTextureCount() const
|
||||
{
|
||||
return Textures.size();
|
||||
}
|
||||
|
||||
|
||||
video::ITexture* CGUISpriteBank::getTexture(u32 index) const
|
||||
{
|
||||
if (index < Textures.size())
|
||||
return Textures[index];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CGUISpriteBank::addTexture(video::ITexture* texture)
|
||||
{
|
||||
if (texture)
|
||||
texture->grab();
|
||||
|
||||
Textures.push_back(texture);
|
||||
}
|
||||
|
||||
|
||||
void CGUISpriteBank::setTexture(u32 index, video::ITexture* texture)
|
||||
{
|
||||
while (index >= Textures.size())
|
||||
Textures.push_back(0);
|
||||
|
||||
if (texture)
|
||||
texture->grab();
|
||||
|
||||
if (Textures[index])
|
||||
Textures[index]->drop();
|
||||
|
||||
Textures[index] = texture;
|
||||
}
|
||||
|
||||
|
||||
//! clear everything
|
||||
void CGUISpriteBank::clear()
|
||||
{
|
||||
// drop textures
|
||||
for (u32 i=0; i<Textures.size(); ++i)
|
||||
if (Textures[i])
|
||||
Textures[i]->drop();
|
||||
Textures.clear();
|
||||
Sprites.clear();
|
||||
Rectangles.clear();
|
||||
}
|
||||
|
||||
//! Add the texture and use it for a single non-animated sprite.
|
||||
s32 CGUISpriteBank::addTextureAsSprite(video::ITexture* texture)
|
||||
{
|
||||
if ( !texture )
|
||||
return -1;
|
||||
|
||||
addTexture(texture);
|
||||
u32 textureIndex = getTextureCount() - 1;
|
||||
|
||||
u32 rectangleIndex = Rectangles.size();
|
||||
Rectangles.push_back( core::rect<s32>(0,0, texture->getOriginalSize().Width, texture->getOriginalSize().Height) );
|
||||
|
||||
SGUISprite sprite;
|
||||
sprite.frameTime = 0;
|
||||
|
||||
SGUISpriteFrame frame;
|
||||
frame.textureNumber = textureIndex;
|
||||
frame.rectNumber = rectangleIndex;
|
||||
sprite.Frames.push_back( frame );
|
||||
|
||||
Sprites.push_back( sprite );
|
||||
|
||||
return Sprites.size() - 1;
|
||||
}
|
||||
|
||||
//! draws a sprite in 2d with scale and color
|
||||
void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos,
|
||||
const core::rect<s32>* clip, const video::SColor& color,
|
||||
u32 starttime, u32 currenttime, bool loop, bool center)
|
||||
{
|
||||
if (index >= Sprites.size() || Sprites[index].Frames.empty() )
|
||||
return;
|
||||
|
||||
// work out frame number
|
||||
u32 frame = 0;
|
||||
if (Sprites[index].frameTime)
|
||||
{
|
||||
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 video::ITexture* tex = Textures[Sprites[index].Frames[frame].textureNumber];
|
||||
if (!tex)
|
||||
return;
|
||||
|
||||
const u32 rn = Sprites[index].Frames[frame].rectNumber;
|
||||
if (rn >= Rectangles.size())
|
||||
return;
|
||||
|
||||
const core::rect<s32>& r = Rectangles[rn];
|
||||
|
||||
if (center)
|
||||
{
|
||||
core::position2di p = pos;
|
||||
p -= r.getSize() / 2;
|
||||
Driver->draw2DImage(tex, p, r, clip, color, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Driver->draw2DImage(tex, pos, r, clip, color, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGUISpriteBank::draw2DSpriteBatch( const core::array<u32>& indices,
|
||||
const core::array<core::position2di>& pos,
|
||||
const core::rect<s32>* clip,
|
||||
const video::SColor& color,
|
||||
u32 starttime, u32 currenttime,
|
||||
bool loop, bool center)
|
||||
{
|
||||
const irr::u32 drawCount = core::min_<u32>(indices.size(), pos.size());
|
||||
|
||||
if( Textures.empty() )
|
||||
return;
|
||||
core::array<SDrawBatch> drawBatches(Textures.size());
|
||||
for(u32 i = 0;i < Textures.size();i++)
|
||||
{
|
||||
drawBatches.push_back(SDrawBatch());
|
||||
drawBatches[i].positions.reallocate(drawCount);
|
||||
drawBatches[i].sourceRects.reallocate(drawCount);
|
||||
}
|
||||
|
||||
for(u32 i = 0;i < drawCount;i++)
|
||||
{
|
||||
const u32 index = indices[i];
|
||||
|
||||
if (index >= Sprites.size() || Sprites[index].Frames.empty() )
|
||||
continue;
|
||||
|
||||
// work out frame number
|
||||
u32 frame = 0;
|
||||
if (Sprites[index].frameTime)
|
||||
{
|
||||
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;
|
||||
|
||||
SDrawBatch& currentBatch = drawBatches[texNum];
|
||||
|
||||
const u32 rn = Sprites[index].Frames[frame].rectNumber;
|
||||
if (rn >= Rectangles.size())
|
||||
return;
|
||||
|
||||
const core::rect<s32>& r = Rectangles[rn];
|
||||
|
||||
if (center)
|
||||
{
|
||||
core::position2di p = pos[i];
|
||||
p -= r.getSize() / 2;
|
||||
|
||||
currentBatch.positions.push_back(p);
|
||||
currentBatch.sourceRects.push_back(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentBatch.positions.push_back(pos[i]);
|
||||
currentBatch.sourceRects.push_back(r);
|
||||
}
|
||||
}
|
||||
|
||||
for(u32 i = 0;i < drawBatches.size();i++)
|
||||
{
|
||||
if(!drawBatches[i].positions.empty() && !drawBatches[i].sourceRects.empty())
|
||||
Driver->draw2DImageBatch(Textures[i], drawBatches[i].positions,
|
||||
drawBatches[i].sourceRects, clip, color, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_SPRITE_BANK_H_INCLUDED__
|
||||
#define __C_GUI_SPRITE_BANK_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISpriteBank.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace video
|
||||
{
|
||||
class IVideoDriver;
|
||||
class ITexture;
|
||||
}
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class IGUIEnvironment;
|
||||
|
||||
//! Sprite bank interface.
|
||||
class CGUISpriteBank : public IGUISpriteBank
|
||||
{
|
||||
public:
|
||||
|
||||
CGUISpriteBank(IGUIEnvironment* env);
|
||||
virtual ~CGUISpriteBank();
|
||||
|
||||
virtual core::array< core::rect<s32> >& getPositions();
|
||||
virtual core::array< SGUISprite >& getSprites();
|
||||
|
||||
virtual u32 getTextureCount() const;
|
||||
virtual video::ITexture* getTexture(u32 index) const;
|
||||
virtual void addTexture(video::ITexture* texture);
|
||||
virtual void setTexture(u32 index, video::ITexture* texture);
|
||||
|
||||
//! Add the texture and use it for a single non-animated sprite.
|
||||
virtual s32 addTextureAsSprite(video::ITexture* texture);
|
||||
|
||||
//! clears sprites, rectangles and textures
|
||||
virtual void clear();
|
||||
|
||||
//! Draws a sprite in 2d with position and color
|
||||
virtual void draw2DSprite(u32 index, const core::position2di& pos, const core::rect<s32>* clip=0,
|
||||
const video::SColor& color= video::SColor(255,255,255,255),
|
||||
u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false);
|
||||
|
||||
//! Draws a sprite batch in 2d using an array of positions and a color
|
||||
virtual void draw2DSpriteBatch(const core::array<u32>& indices, const core::array<core::position2di>& pos,
|
||||
const core::rect<s32>* clip=0,
|
||||
const video::SColor& color= video::SColor(255,255,255,255),
|
||||
u32 starttime=0, u32 currenttime=0,
|
||||
bool loop=true, bool center=false);
|
||||
|
||||
protected:
|
||||
|
||||
struct SDrawBatch
|
||||
{
|
||||
core::array<core::position2di> positions;
|
||||
core::array<core::recti> sourceRects;
|
||||
u32 textureNumber;
|
||||
};
|
||||
|
||||
core::array<SGUISprite> Sprites;
|
||||
core::array< core::rect<s32> > Rectangles;
|
||||
core::array<video::ITexture*> Textures;
|
||||
IGUIEnvironment* Environment;
|
||||
video::IVideoDriver* Driver;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_SPRITE_BANK_H_INCLUDED__
|
||||
|
||||
@@ -0,0 +1,517 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIStaticText.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "rect.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIStaticText::CGUIStaticText(const core::stringw& text, bool border,
|
||||
IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, const core::rect<s32>& rectangle,
|
||||
bool background)
|
||||
: IGUIStaticText(environment, parent, id, rectangle),
|
||||
HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT),
|
||||
Border(border), OverrideColorEnabled(false), OverrideBGColorEnabled(false), WordWrap(false), Background(background),
|
||||
RestrainTextInside(true),
|
||||
OverrideColor(video::SColor(101,255,255,255)), BGColor(video::SColor(101,210,210,210)),
|
||||
OverrideFont(0), LastBreakFont(0), m_use_glyph_layouts_only(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIStaticText");
|
||||
#endif
|
||||
|
||||
Text = text;
|
||||
if (environment && environment->getSkin())
|
||||
{
|
||||
BGColor = environment->getSkin()->getColor(gui::EGDC_3D_FACE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIStaticText::~CGUIStaticText()
|
||||
{
|
||||
if (OverrideFont)
|
||||
OverrideFont->drop();
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIStaticText::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
core::rect<s32> frameRect(AbsoluteRect);
|
||||
|
||||
// draw background
|
||||
|
||||
if (Background)
|
||||
{
|
||||
if ( !OverrideBGColorEnabled ) // skin-colors can change
|
||||
BGColor = skin->getColor(gui::EGDC_3D_FACE);
|
||||
|
||||
driver->draw2DRectangle(BGColor, frameRect, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
// draw the border
|
||||
|
||||
if (Border)
|
||||
{
|
||||
skin->draw3DSunkenPane(this, 0, true, false, frameRect, &AbsoluteClippingRect);
|
||||
frameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X);
|
||||
}
|
||||
|
||||
// draw the text layout
|
||||
if (!m_glyph_layouts.empty())
|
||||
{
|
||||
IGUIFont* font = getActiveFont();
|
||||
|
||||
if (font)
|
||||
{
|
||||
if (font != LastBreakFont)
|
||||
breakText();
|
||||
|
||||
core::rect<s32> r = frameRect;
|
||||
bool hcenter;
|
||||
const core::rect<s32>* clip;
|
||||
getDrawPosition(&r, &hcenter, &clip);
|
||||
|
||||
font->draw(m_glyph_layouts, r,
|
||||
OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
|
||||
hcenter, false, clip);
|
||||
}
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! Sets another skin independent font.
|
||||
void CGUIStaticText::setOverrideFont(IGUIFont* font)
|
||||
{
|
||||
if (OverrideFont == font)
|
||||
return;
|
||||
|
||||
if (OverrideFont)
|
||||
OverrideFont->drop();
|
||||
|
||||
OverrideFont = font;
|
||||
|
||||
if (OverrideFont)
|
||||
OverrideFont->grab();
|
||||
|
||||
breakText();
|
||||
}
|
||||
|
||||
//! Gets the override font (if any)
|
||||
IGUIFont * CGUIStaticText::getOverrideFont() const
|
||||
{
|
||||
return OverrideFont;
|
||||
}
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
IGUIFont* CGUIStaticText::getActiveFont() const
|
||||
{
|
||||
if ( OverrideFont )
|
||||
return OverrideFont;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
return skin->getFont();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets another color for the text.
|
||||
void CGUIStaticText::setOverrideColor(video::SColor color)
|
||||
{
|
||||
OverrideColor = color;
|
||||
OverrideColorEnabled = true;
|
||||
}
|
||||
|
||||
|
||||
//! Sets another color for the text.
|
||||
void CGUIStaticText::setBackgroundColor(video::SColor color)
|
||||
{
|
||||
BGColor = color;
|
||||
OverrideBGColorEnabled = true;
|
||||
Background = true;
|
||||
}
|
||||
|
||||
|
||||
//! Sets whether to draw the background
|
||||
void CGUIStaticText::setDrawBackground(bool draw)
|
||||
{
|
||||
Background = draw;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the background color
|
||||
video::SColor CGUIStaticText::getBackgroundColor() const
|
||||
{
|
||||
return BGColor;
|
||||
}
|
||||
|
||||
|
||||
//! Checks if background drawing is enabled
|
||||
bool CGUIStaticText::isDrawBackgroundEnabled() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Background;
|
||||
}
|
||||
|
||||
|
||||
//! Sets whether to draw the border
|
||||
void CGUIStaticText::setDrawBorder(bool draw)
|
||||
{
|
||||
Border = draw;
|
||||
}
|
||||
|
||||
|
||||
//! Checks if border drawing is enabled
|
||||
bool CGUIStaticText::isDrawBorderEnabled() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Border;
|
||||
}
|
||||
|
||||
|
||||
void CGUIStaticText::setTextRestrainedInside(bool restrainTextInside)
|
||||
{
|
||||
RestrainTextInside = restrainTextInside;
|
||||
}
|
||||
|
||||
|
||||
bool CGUIStaticText::isTextRestrainedInside() const
|
||||
{
|
||||
return RestrainTextInside;
|
||||
}
|
||||
|
||||
|
||||
void CGUIStaticText::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
|
||||
{
|
||||
HAlign = horizontal;
|
||||
VAlign = vertical;
|
||||
}
|
||||
|
||||
|
||||
video::SColor CGUIStaticText::getOverrideColor() const
|
||||
{
|
||||
return OverrideColor;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the static text should use the overide color or the
|
||||
//! color in the gui skin.
|
||||
void CGUIStaticText::enableOverrideColor(bool enable)
|
||||
{
|
||||
OverrideColorEnabled = enable;
|
||||
}
|
||||
|
||||
|
||||
bool CGUIStaticText::isOverrideColorEnabled() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return OverrideColorEnabled;
|
||||
}
|
||||
|
||||
|
||||
//! Enables or disables word wrap for using the static text as
|
||||
//! multiline text control.
|
||||
void CGUIStaticText::setWordWrap(bool enable)
|
||||
{
|
||||
WordWrap = enable;
|
||||
breakText();
|
||||
}
|
||||
|
||||
|
||||
bool CGUIStaticText::isWordWrapEnabled() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return WordWrap;
|
||||
}
|
||||
|
||||
|
||||
//! Breaks the single text line.
|
||||
void CGUIStaticText::breakText()
|
||||
{
|
||||
m_glyph_layouts.clear();
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
IGUIFont* font = getActiveFont();
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
LastBreakFont = font;
|
||||
|
||||
f32 elWidth = (f32)RelativeRect.getWidth();
|
||||
if (Border)
|
||||
elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X);
|
||||
if (!m_use_glyph_layouts_only)
|
||||
font->initGlyphLayouts(Text, m_glyph_layouts);
|
||||
if (WordWrap)
|
||||
breakGlyphLayouts(m_glyph_layouts, elWidth, font->getInverseShaping(), font->getScale());
|
||||
}
|
||||
|
||||
|
||||
//! Sets the new caption of this element.
|
||||
void CGUIStaticText::setText(const core::stringw& text)
|
||||
{
|
||||
if (text == Text)
|
||||
return;
|
||||
IGUIElement::setText(text);
|
||||
breakText();
|
||||
}
|
||||
|
||||
|
||||
void CGUIStaticText::updateAbsolutePosition()
|
||||
{
|
||||
IGUIElement::updateAbsolutePosition();
|
||||
// If use glyph layouts only there is no way at the moment to re-break the
|
||||
// text
|
||||
if (!m_use_glyph_layouts_only)
|
||||
breakText();
|
||||
}
|
||||
|
||||
|
||||
//! Returns the height of the text in pixels when it is drawn.
|
||||
s32 CGUIStaticText::getTextHeight() const
|
||||
{
|
||||
IGUIFont* font = getActiveFont();
|
||||
if (!font)
|
||||
return 0;
|
||||
|
||||
auto dim = getGlyphLayoutsDimension(m_glyph_layouts,
|
||||
font->getHeightPerLine(), font->getInverseShaping(), font->getScale());
|
||||
|
||||
return dim.Height;
|
||||
}
|
||||
|
||||
|
||||
s32 CGUIStaticText::getTextWidth() const
|
||||
{
|
||||
IGUIFont * font = getActiveFont();
|
||||
if (!font)
|
||||
return 0;
|
||||
|
||||
auto dim = getGlyphLayoutsDimension(m_glyph_layouts,
|
||||
font->getHeightPerLine(), font->getInverseShaping(), font->getScale());
|
||||
|
||||
return dim.Width;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
//! Implement this to expose the attributes of your element for
|
||||
//! scripting languages, editors, debuggers or xml serialization purposes.
|
||||
void CGUIStaticText::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIStaticText::serializeAttributes(out,options);
|
||||
|
||||
out->addBool ("Border", Border);
|
||||
out->addBool ("OverrideColorEnabled",OverrideColorEnabled);
|
||||
out->addBool ("OverrideBGColorEnabled",OverrideBGColorEnabled);
|
||||
out->addBool ("WordWrap", WordWrap);
|
||||
out->addBool ("Background", Background);
|
||||
out->addBool ("RestrainTextInside", RestrainTextInside);
|
||||
out->addColor ("OverrideColor", OverrideColor);
|
||||
out->addColor ("BGColor", BGColor);
|
||||
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
|
||||
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
|
||||
|
||||
// out->addFont ("OverrideFont", OverrideFont);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIStaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIStaticText::deserializeAttributes(in,options);
|
||||
|
||||
Border = in->getAttributeAsBool("Border");
|
||||
enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled"));
|
||||
OverrideBGColorEnabled = in->getAttributeAsBool("OverrideBGColorEnabled");
|
||||
setWordWrap(in->getAttributeAsBool("WordWrap"));
|
||||
Background = in->getAttributeAsBool("Background");
|
||||
RestrainTextInside = in->getAttributeAsBool("RestrainTextInside");
|
||||
OverrideColor = in->getAttributeAsColor("OverrideColor");
|
||||
BGColor = in->getAttributeAsColor("BGColor");
|
||||
|
||||
setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
|
||||
(EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
|
||||
|
||||
// OverrideFont = in->getAttributeAsFont("OverrideFont");
|
||||
}
|
||||
|
||||
|
||||
bool CGUIStaticText::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (IsEnabled)
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
{
|
||||
if (m_callback && m_callback(this, event.MouseInput))
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
s32 CGUIStaticText::getCluster(int x, int y, std::shared_ptr<std::u32string>* out_orig_str, int* out_glyph_idx)
|
||||
{
|
||||
core::position2di p;
|
||||
p.X = x;
|
||||
p.Y = y;
|
||||
if (p.X < 0 || p.Y < 0)
|
||||
return -1;
|
||||
|
||||
if (m_glyph_layouts.empty())
|
||||
return -1;
|
||||
|
||||
core::rect<s32> draw_pos = AbsoluteRect;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return -1;
|
||||
if (Border)
|
||||
draw_pos.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X);
|
||||
|
||||
IGUIFont* font = getActiveFont();
|
||||
bool hcenter;
|
||||
const core::rect<s32>* clip;
|
||||
getDrawPosition(&draw_pos, &hcenter, &clip);
|
||||
|
||||
core::position2d<float> offset;
|
||||
f32 next_line_height = 0.0f;
|
||||
std::vector<f32> width_per_line;
|
||||
if (!gui::getDrawOffset(draw_pos, hcenter, false, m_glyph_layouts,
|
||||
font->getInverseShaping(), font->getFaceFontMaxHeight(),
|
||||
font->getFaceGlyphMaxHeight(), font->getScale(), clip, &offset,
|
||||
&next_line_height, &width_per_line))
|
||||
return -1;
|
||||
|
||||
// Check if the line is RTL
|
||||
bool rtl = (m_glyph_layouts[0].flags & gui::GLF_RTL_LINE) != 0;
|
||||
if (!hcenter && rtl)
|
||||
offset.X += (s32)(draw_pos.getWidth() - width_per_line[0]);
|
||||
|
||||
unsigned cur_line = 0;
|
||||
bool line_changed = false;
|
||||
|
||||
int idx = -1;
|
||||
core::recti test_rect;
|
||||
test_rect.UpperLeftCorner.X = test_rect.LowerRightCorner.X = (s32)offset.X;
|
||||
test_rect.UpperLeftCorner.Y = (s32)offset.Y;
|
||||
test_rect.LowerRightCorner.Y = (s32)offset.Y + (s32)next_line_height;
|
||||
|
||||
for (unsigned i = 0; i < m_glyph_layouts.size(); i++)
|
||||
{
|
||||
const GlyphLayout& glyph_layout = m_glyph_layouts[i];
|
||||
// Newline handling (from font with face render)
|
||||
if ((glyph_layout.flags & GLF_NEWLINE) != 0)
|
||||
{
|
||||
test_rect.UpperLeftCorner.Y += (int)next_line_height;
|
||||
test_rect.LowerRightCorner.Y += (int)next_line_height;
|
||||
cur_line++;
|
||||
line_changed = true;
|
||||
continue;
|
||||
}
|
||||
if (line_changed)
|
||||
{
|
||||
line_changed = false;
|
||||
rtl = (glyph_layout.flags & gui::GLF_RTL_LINE) != 0;
|
||||
offset.X = float(draw_pos.UpperLeftCorner.X);
|
||||
if (hcenter)
|
||||
{
|
||||
offset.X += (s32)(
|
||||
(draw_pos.getWidth() - width_per_line.at(cur_line)) / 2.f);
|
||||
}
|
||||
else if (rtl)
|
||||
{
|
||||
offset.X +=
|
||||
(s32)(draw_pos.getWidth() - width_per_line.at(cur_line));
|
||||
}
|
||||
test_rect.UpperLeftCorner.X = test_rect.LowerRightCorner.X =
|
||||
(s32)offset.X;
|
||||
}
|
||||
test_rect.LowerRightCorner.X += s32(
|
||||
(f32)glyph_layout.x_advance * font->getInverseShaping() *
|
||||
font->getScale());
|
||||
|
||||
if (test_rect.isPointInside(p))
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == -1)
|
||||
return -1;
|
||||
|
||||
std::shared_ptr<std::u32string> s = m_glyph_layouts[idx].orig_string;
|
||||
if (!s)
|
||||
return -1;
|
||||
unsigned cluster = m_glyph_layouts[idx].cluster.front();
|
||||
if (cluster > s->size())
|
||||
return -1;
|
||||
*out_orig_str = s;
|
||||
if (out_glyph_idx)
|
||||
*out_glyph_idx = idx;
|
||||
return cluster;
|
||||
}
|
||||
|
||||
|
||||
void CGUIStaticText::getDrawPosition(core::rect<s32>* draw_pos, bool* hcenter, const core::rect<s32>** clip)
|
||||
{
|
||||
core::rect<s32> r = *draw_pos;
|
||||
IGUIFont* font = getActiveFont();
|
||||
auto dim = getGlyphLayoutsDimension(m_glyph_layouts,
|
||||
font->getHeightPerLine(), font->getInverseShaping(), font->getScale());
|
||||
|
||||
s32 totalHeight = dim.Height;
|
||||
if (VAlign == EGUIA_CENTER)
|
||||
{
|
||||
r.UpperLeftCorner.Y = r.getCenter().Y - (totalHeight / 2);
|
||||
}
|
||||
else if (VAlign == EGUIA_LOWERRIGHT)
|
||||
{
|
||||
r.UpperLeftCorner.Y = r.LowerRightCorner.Y - totalHeight;
|
||||
}
|
||||
|
||||
if (HAlign == EGUIA_LOWERRIGHT)
|
||||
{
|
||||
r.UpperLeftCorner.X = AbsoluteRect.LowerRightCorner.X - dim.Width;
|
||||
}
|
||||
|
||||
*draw_pos = r;
|
||||
*hcenter = (HAlign == EGUIA_CENTER);
|
||||
*clip = (RestrainTextInside ? &AbsoluteClippingRect : NULL);
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_STATIC_TEXT_H_INCLUDED__
|
||||
#define __C_GUI_STATIC_TEXT_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIStaticText.h"
|
||||
#include "irrArray.h"
|
||||
#include "GlyphLayout.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class CGUIStaticText : public IGUIStaticText
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIStaticText(const core::stringw& text, bool border, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle,
|
||||
bool background = false);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIStaticText();
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Sets another skin independent font.
|
||||
virtual void setOverrideFont(IGUIFont* font=0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets another color for the text.
|
||||
virtual void setOverrideColor(video::SColor color);
|
||||
|
||||
//! Sets another color for the background.
|
||||
virtual void setBackgroundColor(video::SColor color);
|
||||
|
||||
//! Sets whether to draw the background
|
||||
virtual void setDrawBackground(bool draw);
|
||||
|
||||
//! Gets the background color
|
||||
virtual video::SColor getBackgroundColor() const;
|
||||
|
||||
//! Checks if background drawing is enabled
|
||||
virtual bool isDrawBackgroundEnabled() const;
|
||||
|
||||
//! Sets whether to draw the border
|
||||
virtual void setDrawBorder(bool draw);
|
||||
|
||||
//! Checks if border drawing is enabled
|
||||
virtual bool isDrawBorderEnabled() const;
|
||||
|
||||
//! Sets alignment mode for text
|
||||
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical);
|
||||
|
||||
//! Gets the override color
|
||||
virtual video::SColor getOverrideColor() const;
|
||||
|
||||
//! Sets if the static text should use the overide color or the
|
||||
//! color in the gui skin.
|
||||
virtual void enableOverrideColor(bool enable);
|
||||
|
||||
//! Checks if an override color is enabled
|
||||
virtual bool isOverrideColorEnabled() const;
|
||||
|
||||
//! Set whether the text in this label should be clipped if it goes outside bounds
|
||||
virtual void setTextRestrainedInside(bool restrainedInside);
|
||||
|
||||
//! Checks if the text in this label should be clipped if it goes outside bounds
|
||||
virtual bool isTextRestrainedInside() const;
|
||||
|
||||
//! Enables or disables word wrap for using the static text as
|
||||
//! multiline text control.
|
||||
virtual void setWordWrap(bool enable);
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
virtual bool isWordWrapEnabled() const;
|
||||
|
||||
//! Sets the new caption of this element.
|
||||
virtual void setText(const core::stringw& text);
|
||||
|
||||
//! Returns the height of the text in pixels when it is drawn.
|
||||
virtual s32 getTextHeight() const;
|
||||
|
||||
//! Returns the width of the current text, in the current font
|
||||
virtual s32 getTextWidth() const;
|
||||
|
||||
//! Updates the absolute position, splits text if word wrap is enabled
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
virtual const std::vector<GlyphLayout>& getGlyphLayouts() const { return m_glyph_layouts; }
|
||||
virtual void setGlyphLayouts(std::vector<GlyphLayout>& gls) { m_glyph_layouts = gls; }
|
||||
virtual void clearGlyphLayouts() { m_glyph_layouts.clear(); }
|
||||
virtual void setUseGlyphLayoutsOnly(bool gls_only) { m_use_glyph_layouts_only = gls_only; }
|
||||
virtual bool useGlyphLayoutsOnly() const { return m_use_glyph_layouts_only; }
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
virtual void setMouseCallback(std::function<bool(IGUIStaticText* text, SEvent::SMouseInput)> cb) { m_callback = cb; }
|
||||
virtual s32 getCluster(int x, int y, std::shared_ptr<std::u32string>* out_orig_str, int* out_glyph_idx = NULL);
|
||||
private:
|
||||
|
||||
//! Breaks the single text line.
|
||||
void breakText();
|
||||
void getDrawPosition(core::rect<s32>* draw_pos, bool* hcenter, const core::rect<s32>** clip);
|
||||
|
||||
EGUI_ALIGNMENT HAlign, VAlign;
|
||||
bool Border;
|
||||
bool OverrideColorEnabled;
|
||||
bool OverrideBGColorEnabled;
|
||||
bool WordWrap;
|
||||
bool Background;
|
||||
bool RestrainTextInside;
|
||||
|
||||
video::SColor OverrideColor, BGColor;
|
||||
gui::IGUIFont* OverrideFont;
|
||||
gui::IGUIFont* LastBreakFont; // stored because: if skin changes, line break must be recalculated.
|
||||
|
||||
//! If true, setText / updating this element will not reshape with Text object
|
||||
bool m_use_glyph_layouts_only;
|
||||
std::vector<GlyphLayout> m_glyph_layouts;
|
||||
std::function<bool(IGUIStaticText* text, irr::SEvent::SMouseInput)> m_callback;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,202 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_TAB_CONTROL_H_INCLUDED__
|
||||
#define __C_GUI_TAB_CONTROL_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUITabControl.h"
|
||||
#include "irrArray.h"
|
||||
#include "IGUISkin.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class CGUITabControl;
|
||||
class IGUIButton;
|
||||
|
||||
// A tab, onto which other gui elements could be added.
|
||||
class CGUITab : public IGUITab
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUITab(s32 number, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, const core::rect<s32>& rectangle,
|
||||
s32 id);
|
||||
|
||||
//! destructor
|
||||
//virtual ~CGUITab();
|
||||
|
||||
//! Returns number of this tab in tabcontrol. Can be accessed
|
||||
//! later IGUITabControl::getTab() by this number.
|
||||
virtual s32 getNumber() const;
|
||||
|
||||
//! Sets the number
|
||||
virtual void setNumber(s32 n);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! sets if the tab should draw its background
|
||||
virtual void setDrawBackground(bool draw=true);
|
||||
|
||||
//! sets the color of the background, if it should be drawn.
|
||||
virtual void setBackgroundColor(video::SColor c);
|
||||
|
||||
//! sets the color of the text
|
||||
virtual void setTextColor(video::SColor c);
|
||||
|
||||
//! returns true if the tab is drawing its background, false if not
|
||||
virtual bool isDrawingBackground() const;
|
||||
|
||||
//! returns the color of the background
|
||||
virtual video::SColor getBackgroundColor() const;
|
||||
|
||||
virtual video::SColor getTextColor() const;
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
//! only for internal use by CGUITabControl
|
||||
void refreshSkinColors();
|
||||
|
||||
private:
|
||||
|
||||
s32 Number;
|
||||
video::SColor BackColor;
|
||||
bool OverrideTextColorEnabled;
|
||||
video::SColor TextColor;
|
||||
bool DrawBackground;
|
||||
};
|
||||
|
||||
|
||||
//! A standard tab control
|
||||
class CGUITabControl : public IGUITabControl
|
||||
{
|
||||
public:
|
||||
|
||||
//! destructor
|
||||
CGUITabControl(IGUIEnvironment* environment,
|
||||
IGUIElement* parent, const core::rect<s32>& rectangle,
|
||||
bool fillbackground=true, bool border=true, s32 id=-1);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUITabControl();
|
||||
|
||||
//! Adds a tab
|
||||
virtual IGUITab* addTab(const wchar_t* caption, s32 id=-1);
|
||||
|
||||
//! Adds a tab that has already been created
|
||||
virtual void addTab(CGUITab* tab);
|
||||
|
||||
//! Insert the tab at the given index
|
||||
virtual IGUITab* insertTab(s32 idx, const wchar_t* caption, s32 id=-1);
|
||||
|
||||
//! Removes a tab from the tabcontrol
|
||||
virtual void removeTab(s32 idx);
|
||||
|
||||
//! Clears the tabcontrol removing all tabs
|
||||
virtual void clear();
|
||||
|
||||
//! Returns amount of tabs in the tabcontrol
|
||||
virtual s32 getTabCount() const;
|
||||
|
||||
//! Returns a tab based on zero based index
|
||||
virtual IGUITab* getTab(s32 idx) const;
|
||||
|
||||
//! Brings a tab to front.
|
||||
virtual bool setActiveTab(s32 idx);
|
||||
|
||||
//! Brings a tab to front.
|
||||
virtual bool setActiveTab(IGUITab *tab);
|
||||
|
||||
//! Returns which tab is currently active
|
||||
virtual s32 getActiveTab() const;
|
||||
|
||||
//! get the the id of the tab at the given absolute coordinates
|
||||
virtual s32 getTabAt(s32 xpos, s32 ypos) const;
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Removes a child.
|
||||
virtual void removeChild(IGUIElement* child);
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
//! Set the height of the tabs
|
||||
virtual void setTabHeight( s32 height );
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
//! Get the height of the tabs
|
||||
virtual s32 getTabHeight() const;
|
||||
|
||||
//! set the maximal width of a tab. Per default width is 0 which means "no width restriction".
|
||||
virtual void setTabMaxWidth(s32 width );
|
||||
|
||||
//! get the maximal width of a tab
|
||||
virtual s32 getTabMaxWidth() const;
|
||||
|
||||
//! Set the alignment of the tabs
|
||||
//! note: EGUIA_CENTER is not an option
|
||||
virtual void setTabVerticalAlignment( gui::EGUI_ALIGNMENT alignment );
|
||||
|
||||
//! Get the alignment of the tabs
|
||||
virtual gui::EGUI_ALIGNMENT getTabVerticalAlignment() const;
|
||||
|
||||
//! Set the extra width added to tabs on each side of the text
|
||||
virtual void setTabExtraWidth( s32 extraWidth );
|
||||
|
||||
//! Get the extra width added to tabs on each side of the text
|
||||
virtual s32 getTabExtraWidth() const;
|
||||
|
||||
//! Update the position of the element, decides scroll button status
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
private:
|
||||
|
||||
void scrollLeft();
|
||||
void scrollRight();
|
||||
bool needScrollControl( s32 startIndex=0, bool withScrollControl=false );
|
||||
s32 calcTabWidth(s32 pos, IGUIFont* font, const wchar_t* text, bool withScrollControl ) const;
|
||||
core::rect<s32> calcTabPos();
|
||||
|
||||
void recalculateScrollButtonPlacement();
|
||||
void recalculateScrollBar();
|
||||
void refreshSprites();
|
||||
|
||||
core::array<CGUITab*> Tabs; // CGUITab* because we need setNumber (which is certainly not nice)
|
||||
s32 ActiveTab;
|
||||
bool Border;
|
||||
bool FillBackground;
|
||||
bool ScrollControl;
|
||||
s32 TabHeight;
|
||||
gui::EGUI_ALIGNMENT VerticalAlignment;
|
||||
IGUIButton* UpButton;
|
||||
IGUIButton* DownButton;
|
||||
s32 TabMaxWidth;
|
||||
s32 CurrentScrollTabIndex;
|
||||
s32 TabExtraWidth;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,224 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
// 07.10.2005 - Multicolor-Listbox addet by A. Buschhueter (Acki)
|
||||
// A_Buschhueter@gmx.de
|
||||
|
||||
#ifndef __C_GUI_TABLE_BAR_H_INCLUDED__
|
||||
#define __C_GUI_TABLE_BAR_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUITable.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class IGUIFont;
|
||||
class IGUIScrollBar;
|
||||
|
||||
class CGUITable : public IGUITable
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CGUITable(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, const core::rect<s32>& rectangle, bool clip=true,
|
||||
bool drawBack=false, bool moveOverSelect=true);
|
||||
|
||||
//! destructor
|
||||
~CGUITable();
|
||||
|
||||
//! Adds a column
|
||||
//! If columnIndex is outside the current range, do push new colum at the end
|
||||
virtual void addColumn(const wchar_t* caption, s32 columnIndex=-1);
|
||||
|
||||
//! remove a column from the table
|
||||
virtual void removeColumn(u32 columnIndex);
|
||||
|
||||
//! Returns the number of columns in the table control
|
||||
virtual s32 getColumnCount() const;
|
||||
|
||||
//! Makes a column active. This will trigger an ordering process.
|
||||
/** \param idx: The id of the column to make active.
|
||||
\return True if successful. */
|
||||
virtual bool setActiveColumn(s32 columnIndex, bool doOrder=false);
|
||||
|
||||
//! Returns which header is currently active
|
||||
virtual s32 getActiveColumn() const;
|
||||
|
||||
//! Returns the ordering used by the currently active column
|
||||
virtual EGUI_ORDERING_MODE getActiveColumnOrdering() const;
|
||||
|
||||
//! set a column width
|
||||
virtual void setColumnWidth(u32 columnIndex, u32 width);
|
||||
|
||||
//! Get the width of a column
|
||||
virtual u32 getColumnWidth(u32 columnIndex) const;
|
||||
|
||||
//! columns can be resized by drag 'n drop
|
||||
virtual void setResizableColumns(bool resizable);
|
||||
|
||||
//! can columns be resized by dran 'n drop?
|
||||
virtual bool hasResizableColumns() const;
|
||||
|
||||
//! This tells the table control which ordering mode should be used when
|
||||
//! a column header is clicked.
|
||||
/** \param columnIndex: The index of the column header.
|
||||
\param state: If true, a EGET_TABLE_HEADER_CHANGED message will be sent and you can order the table data as you whish.*/
|
||||
//! \param mode: One of the modes defined in EGUI_COLUMN_ORDERING
|
||||
virtual void setColumnOrdering(u32 columnIndex, EGUI_COLUMN_ORDERING mode);
|
||||
|
||||
//! Returns which row is currently selected
|
||||
virtual s32 getSelected() const;
|
||||
|
||||
//! set wich row is currently selected
|
||||
virtual void setSelected( s32 index );
|
||||
|
||||
//! Returns amount of rows in the tabcontrol
|
||||
virtual s32 getRowCount() const;
|
||||
|
||||
//! adds a row to the table
|
||||
/** \param rowIndex: zero based index of rows. The row will be
|
||||
inserted at this position. If a row already exists
|
||||
there, it will be placed after it. If the row is larger
|
||||
than the actual number of rows by more than one, it
|
||||
won't be created. Note that if you create a row that is
|
||||
not at the end, there might be performance issues*/
|
||||
virtual u32 addRow(u32 rowIndex);
|
||||
|
||||
//! Remove a row from the table
|
||||
virtual void removeRow(u32 rowIndex);
|
||||
|
||||
//! clear the table rows, but keep the columns intact
|
||||
virtual void clearRows();
|
||||
|
||||
//! Swap two row positions. This is useful for a custom ordering algo.
|
||||
virtual void swapRows(u32 rowIndexA, u32 rowIndexB);
|
||||
|
||||
//! This tells the table to start ordering all the rows. You
|
||||
//! need to explicitly tell the table to reorder the rows when
|
||||
//! a new row is added or the cells data is changed. This makes
|
||||
//! the system more flexible and doesn't make you pay the cost
|
||||
//! of ordering when adding a lot of rows.
|
||||
//! \param columnIndex: When set to -1 the active column is used.
|
||||
virtual void orderRows(s32 columnIndex=-1, EGUI_ORDERING_MODE mode=EGOM_NONE);
|
||||
|
||||
|
||||
//! Set the text of a cell
|
||||
virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text);
|
||||
|
||||
//! Set the text of a cell, and set a color of this cell.
|
||||
virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color);
|
||||
|
||||
//! Set the data of a cell
|
||||
//! data will not be serialized.
|
||||
virtual void setCellData(u32 rowIndex, u32 columnIndex, void *data);
|
||||
|
||||
//! Set the color of a cell text
|
||||
virtual void setCellColor(u32 rowIndex, u32 columnIndex, video::SColor color);
|
||||
|
||||
//! Get the text of a cell
|
||||
virtual const wchar_t* getCellText(u32 rowIndex, u32 columnIndex ) const;
|
||||
|
||||
//! Get the data of a cell
|
||||
virtual void* getCellData(u32 rowIndex, u32 columnIndex ) const;
|
||||
|
||||
//! clears the table, deletes all items in the table
|
||||
virtual void clear();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent &event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Set flags, as defined in EGUI_TABLE_DRAW_FLAGS, which influence the layout
|
||||
virtual void setDrawFlags(s32 flags);
|
||||
|
||||
//! Get the flags, as defined in EGUI_TABLE_DRAW_FLAGS, which influence the layout
|
||||
virtual s32 getDrawFlags() const;
|
||||
|
||||
//! Writes attributes of the object.
|
||||
//! Implement this to expose the attributes of your scene node animator for
|
||||
//! scripting languages, editors, debuggers or xml serialization purposes.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the object.
|
||||
//! Implement this to set the attributes of your scene node animator for
|
||||
//! scripting languages, editors, debuggers or xml deserialization purposes.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
protected:
|
||||
virtual void refreshControls();
|
||||
virtual void checkScrollbars();
|
||||
|
||||
private:
|
||||
|
||||
struct Cell
|
||||
{
|
||||
Cell() : IsOverrideColor(false), Data(0) {}
|
||||
core::stringw Text;
|
||||
core::stringw BrokenText;
|
||||
bool IsOverrideColor;
|
||||
video::SColor Color;
|
||||
void *Data;
|
||||
};
|
||||
|
||||
struct Row
|
||||
{
|
||||
Row() {}
|
||||
core::array<Cell> Items;
|
||||
};
|
||||
|
||||
struct Column
|
||||
{
|
||||
Column() : Width(0), OrderingMode(EGCO_NONE) {}
|
||||
core::stringw Name;
|
||||
u32 Width;
|
||||
EGUI_COLUMN_ORDERING OrderingMode;
|
||||
};
|
||||
|
||||
void breakText(const core::stringw &text, core::stringw & brokenText, u32 cellWidth);
|
||||
void selectNew(s32 ypos, bool onlyHover=false);
|
||||
bool selectColumnHeader(s32 xpos, s32 ypos);
|
||||
bool dragColumnStart(s32 xpos, s32 ypos);
|
||||
bool dragColumnUpdate(s32 xpos);
|
||||
void recalculateHeights();
|
||||
void recalculateWidths();
|
||||
|
||||
core::array< Column > Columns;
|
||||
core::array< Row > Rows;
|
||||
gui::IGUIFont* Font;
|
||||
gui::IGUIScrollBar* VerticalScrollBar;
|
||||
gui::IGUIScrollBar* HorizontalScrollBar;
|
||||
bool Clip;
|
||||
bool DrawBack;
|
||||
bool MoveOverSelect;
|
||||
bool Selecting;
|
||||
s32 CurrentResizedColumn;
|
||||
s32 ResizeStart;
|
||||
bool ResizableColumns;
|
||||
|
||||
s32 ItemHeight;
|
||||
s32 TotalItemHeight;
|
||||
s32 TotalItemWidth;
|
||||
s32 Selected;
|
||||
s32 CellHeightPadding;
|
||||
s32 CellWidthPadding;
|
||||
s32 ActiveTab;
|
||||
EGUI_ORDERING_MODE CurrentOrdering;
|
||||
s32 DrawFlags;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIToolBar.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "CGUIButton.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIToolBar::CGUIToolBar(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
|
||||
:IGUIToolBar(environment, parent, id, rectangle), ButtonX(5)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIToolBar");
|
||||
#endif
|
||||
|
||||
// calculate position and find other menubars
|
||||
s32 y = 0;
|
||||
s32 parentwidth = 100;
|
||||
|
||||
if (parent)
|
||||
{
|
||||
parentwidth = Parent->getAbsolutePosition().getWidth();
|
||||
|
||||
const core::list<IGUIElement*>& children = parent->getChildren();
|
||||
core::list<IGUIElement*>::ConstIterator it = children.begin();
|
||||
for (; it != children.end(); ++it)
|
||||
{
|
||||
core::rect<s32> r = (*it)->getAbsolutePosition();
|
||||
if (r.UpperLeftCorner.X == 0 && r.UpperLeftCorner.Y <= y &&
|
||||
r.LowerRightCorner.X == parentwidth)
|
||||
y = r.LowerRightCorner.Y;
|
||||
}
|
||||
}
|
||||
|
||||
core::rect<s32> rr;
|
||||
rr.UpperLeftCorner.X = 0;
|
||||
rr.UpperLeftCorner.Y = y;
|
||||
s32 height = Environment->getSkin()->getSize ( EGDS_MENU_HEIGHT );
|
||||
|
||||
/*IGUISkin* skin = Environment->getSkin();
|
||||
IGUIFont* font = skin->getFont();
|
||||
if (font)
|
||||
{
|
||||
s32 t = font->getDimension(L"A").Height + 5;
|
||||
if (t > height)
|
||||
height = t;
|
||||
}*/
|
||||
|
||||
rr.LowerRightCorner.X = parentwidth;
|
||||
rr.LowerRightCorner.Y = rr.UpperLeftCorner.Y + height;
|
||||
setRelativePosition(rr);
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIToolBar::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
if (event.EventType == EET_MOUSE_INPUT_EVENT &&
|
||||
event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
|
||||
{
|
||||
if (AbsoluteClippingRect.isPointInside(core::position2di(event.MouseInput.X, event.MouseInput.Y)))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIToolBar::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
core::rect<s32>* clip = &AbsoluteClippingRect;
|
||||
|
||||
// draw frame
|
||||
skin->draw3DToolBar(this, rect, clip);
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! Updates the absolute position.
|
||||
void CGUIToolBar::updateAbsolutePosition()
|
||||
{
|
||||
if (Parent)
|
||||
{
|
||||
DesiredRect.UpperLeftCorner.X = 0;
|
||||
DesiredRect.LowerRightCorner.X = Parent->getAbsolutePosition().getWidth();
|
||||
}
|
||||
|
||||
IGUIElement::updateAbsolutePosition();
|
||||
}
|
||||
|
||||
|
||||
//! Adds a button to the tool bar
|
||||
IGUIButton* CGUIToolBar::addButton(s32 id, const wchar_t* text,const wchar_t* tooltiptext,
|
||||
video::ITexture* img, video::ITexture* pressed, bool isPushButton,
|
||||
bool useAlphaChannel)
|
||||
{
|
||||
ButtonX += 3;
|
||||
|
||||
core::rect<s32> rectangle(ButtonX,2,ButtonX+1,3);
|
||||
if ( img )
|
||||
{
|
||||
const core::dimension2du &size = img->getOriginalSize();
|
||||
rectangle.LowerRightCorner.X = rectangle.UpperLeftCorner.X + size.Width + 8;
|
||||
rectangle.LowerRightCorner.Y = rectangle.UpperLeftCorner.Y + size.Height + 6;
|
||||
}
|
||||
|
||||
if ( text )
|
||||
{
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
IGUIFont * font = skin->getFont(EGDF_BUTTON);
|
||||
if ( font )
|
||||
{
|
||||
core::dimension2d<u32> dim = font->getDimension(text);
|
||||
if ( (s32)dim.Width > rectangle.getWidth() )
|
||||
rectangle.LowerRightCorner.X = rectangle.UpperLeftCorner.X + dim.Width + 8;
|
||||
if ( (s32)dim.Height > rectangle.getHeight() )
|
||||
rectangle.LowerRightCorner.Y = rectangle.UpperLeftCorner.Y + dim.Height + 6;
|
||||
}
|
||||
}
|
||||
|
||||
ButtonX += rectangle.getWidth();
|
||||
|
||||
IGUIButton* button = new CGUIButton(Environment, this, id, rectangle);
|
||||
button->drop();
|
||||
|
||||
if (text)
|
||||
button->setText(text);
|
||||
|
||||
if (tooltiptext)
|
||||
button->setToolTipText(tooltiptext);
|
||||
|
||||
if (img)
|
||||
button->setImage(img);
|
||||
|
||||
if (pressed)
|
||||
button->setPressedImage(pressed);
|
||||
|
||||
if (isPushButton)
|
||||
button->setIsPushButton(isPushButton);
|
||||
|
||||
if (useAlphaChannel)
|
||||
button->setUseAlphaChannel(useAlphaChannel);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_TOOL_BAR_H_INCLUDED__
|
||||
#define __C_GUI_TOOL_BAR_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIToolbar.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! Stays at the top of its parent like the menu bar and contains tool buttons
|
||||
class CGUIToolBar : public IGUIToolBar
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIToolBar(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Updates the absolute position.
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
//! Adds a button to the tool bar
|
||||
virtual IGUIButton* addButton(s32 id=-1, const wchar_t* text=0,const wchar_t* tooltiptext=0,
|
||||
video::ITexture* img=0, video::ITexture* pressed=0,
|
||||
bool isPushButton=false, bool useAlphaChannel=false);
|
||||
|
||||
private:
|
||||
|
||||
s32 ButtonX;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,331 @@
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de
|
||||
|
||||
#ifndef __C_GUI_TREE_VIEW_H_INCLUDED__
|
||||
#define __C_GUI_TREE_VIEW_H_INCLUDED__
|
||||
|
||||
#include "IGUITreeView.h"
|
||||
#include "irrList.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
// forward declarations
|
||||
class IGUIFont;
|
||||
class IGUIScrollBar;
|
||||
class CGUITreeView;
|
||||
|
||||
//! Node for gui tree view
|
||||
class CGUITreeViewNode : public IGUITreeViewNode
|
||||
{
|
||||
friend class CGUITreeView;
|
||||
|
||||
public:
|
||||
//! constructor
|
||||
CGUITreeViewNode( CGUITreeView* owner, CGUITreeViewNode* parent );
|
||||
|
||||
//! destructor
|
||||
~CGUITreeViewNode();
|
||||
|
||||
//! returns the owner (tree view) of this node
|
||||
virtual IGUITreeView* getOwner() const;
|
||||
|
||||
//! Returns the parent node of this node.
|
||||
virtual IGUITreeViewNode* getParent() const;
|
||||
|
||||
//! returns the text of the node
|
||||
virtual const wchar_t* getText() const
|
||||
{ return Text.c_str(); }
|
||||
|
||||
//! sets the text of the node
|
||||
virtual void setText( const wchar_t* text );
|
||||
|
||||
//! returns the icon text of the node
|
||||
virtual const wchar_t* getIcon() const
|
||||
{ return Icon.c_str(); }
|
||||
|
||||
//! sets the icon text of the node
|
||||
virtual void setIcon( const wchar_t* icon );
|
||||
|
||||
//! returns the image index of the node
|
||||
virtual u32 getImageIndex() const
|
||||
{ return ImageIndex; }
|
||||
|
||||
//! sets the image index of the node
|
||||
virtual void setImageIndex( u32 imageIndex )
|
||||
{ ImageIndex = imageIndex; }
|
||||
|
||||
//! returns the image index of the node
|
||||
virtual u32 getSelectedImageIndex() const
|
||||
{ return SelectedImageIndex; }
|
||||
|
||||
//! sets the image index of the node
|
||||
virtual void setSelectedImageIndex( u32 imageIndex )
|
||||
{ SelectedImageIndex = imageIndex; }
|
||||
|
||||
//! returns the user data (void*) of this node
|
||||
virtual void* getData() const
|
||||
{ return Data; }
|
||||
|
||||
//! sets the user data (void*) of this node
|
||||
virtual void setData( void* data )
|
||||
{ Data = data; }
|
||||
|
||||
//! returns the user data2 (IReferenceCounted) of this node
|
||||
virtual IReferenceCounted* getData2() const
|
||||
{ return Data2; }
|
||||
|
||||
//! sets the user data2 (IReferenceCounted) of this node
|
||||
virtual void setData2( IReferenceCounted* data )
|
||||
{
|
||||
if( Data2 )
|
||||
{
|
||||
Data2->drop();
|
||||
}
|
||||
Data2 = data;
|
||||
if( Data2 )
|
||||
{
|
||||
Data2->grab();
|
||||
}
|
||||
}
|
||||
|
||||
//! returns the child item count
|
||||
virtual u32 getChildCount() const
|
||||
{ return Children.getSize(); }
|
||||
|
||||
//! removes all children (recursive) from this node
|
||||
virtual void clearChildren();
|
||||
|
||||
//! returns true if this node has child nodes
|
||||
virtual bool hasChildren() const
|
||||
{ return !Children.empty(); }
|
||||
|
||||
//! Adds a new node behind the last child node.
|
||||
//! \param text text of the new node
|
||||
//! \param icon icon text of the new node
|
||||
//! \param imageIndex index of the image for the new node (-1 = none)
|
||||
//! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex)
|
||||
//! \param data user data (void*) of the new node
|
||||
//! \param data2 user data2 (IReferenceCounted*) of the new node
|
||||
//! \return
|
||||
//! returns the new node
|
||||
virtual IGUITreeViewNode* addChildBack(
|
||||
const wchar_t* text,
|
||||
const wchar_t* icon = 0,
|
||||
s32 imageIndex = -1,
|
||||
s32 selectedImageIndex = -1,
|
||||
void* data = 0,
|
||||
IReferenceCounted* data2 = 0);
|
||||
|
||||
//! Adds a new node before the first child node.
|
||||
//! \param text text of the new node
|
||||
//! \param icon icon text of the new node
|
||||
//! \param imageIndex index of the image for the new node (-1 = none)
|
||||
//! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex)
|
||||
//! \param data user data (void*) of the new node
|
||||
//! \param data2 user data2 (IReferenceCounted*) of the new node
|
||||
//! \return
|
||||
//! returns the new node
|
||||
virtual IGUITreeViewNode* addChildFront(
|
||||
const wchar_t* text,
|
||||
const wchar_t* icon = 0,
|
||||
s32 imageIndex = -1,
|
||||
s32 selectedImageIndex = -1,
|
||||
void* data = 0,
|
||||
IReferenceCounted* data2 = 0 );
|
||||
|
||||
//! Adds a new node behind the other node.
|
||||
//! The other node has also te be a child node from this node.
|
||||
//! \param text text of the new node
|
||||
//! \param icon icon text of the new node
|
||||
//! \param imageIndex index of the image for the new node (-1 = none)
|
||||
//! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex)
|
||||
//! \param data user data (void*) of the new node
|
||||
//! \param data2 user data2 (IReferenceCounted*) of the new node
|
||||
//! \return
|
||||
//! returns the new node or 0 if other is no child node from this
|
||||
virtual IGUITreeViewNode* insertChildAfter(
|
||||
IGUITreeViewNode* other,
|
||||
const wchar_t* text,
|
||||
const wchar_t* icon = 0,
|
||||
s32 imageIndex = -1,
|
||||
s32 selectedImageIndex = -1,
|
||||
void* data = 0,
|
||||
IReferenceCounted* data2 = 0 );
|
||||
|
||||
//! Adds a new node before the other node.
|
||||
//! The other node has also te be a child node from this node.
|
||||
//! \param text text of the new node
|
||||
//! \param icon icon text of the new node
|
||||
//! \param imageIndex index of the image for the new node (-1 = none)
|
||||
//! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex)
|
||||
//! \param data user data (void*) of the new node
|
||||
//! \param data2 user data2 (IReferenceCounted*) of the new node
|
||||
//! \return
|
||||
//! returns the new node or 0 if other is no child node from this
|
||||
virtual IGUITreeViewNode* insertChildBefore(
|
||||
IGUITreeViewNode* other,
|
||||
const wchar_t* text,
|
||||
const wchar_t* icon = 0,
|
||||
s32 imageIndex = -1,
|
||||
s32 selectedImageIndex = -1,
|
||||
void* data = 0,
|
||||
IReferenceCounted* data2 = 0 );
|
||||
|
||||
//! Return the first child note from this node.
|
||||
virtual IGUITreeViewNode* getFirstChild() const;
|
||||
|
||||
//! Return the last child note from this node.
|
||||
virtual IGUITreeViewNode* getLastChild() const;
|
||||
|
||||
//! Returns the preverse sibling node from this node.
|
||||
virtual IGUITreeViewNode* getPrevSibling() const;
|
||||
|
||||
//! Returns the next sibling node from this node.
|
||||
virtual IGUITreeViewNode* getNextSibling() const;
|
||||
|
||||
//! Returns the next visible (expanded, may be out of scrolling) node from this node.
|
||||
virtual IGUITreeViewNode* getNextVisible() const;
|
||||
|
||||
//! Deletes a child node.
|
||||
virtual bool deleteChild( IGUITreeViewNode* child );
|
||||
|
||||
//! Moves a child node one position up.
|
||||
virtual bool moveChildUp( IGUITreeViewNode* child );
|
||||
|
||||
//! Moves a child node one position down.
|
||||
virtual bool moveChildDown( IGUITreeViewNode* child );
|
||||
|
||||
//! Returns true if the node is expanded (children are visible).
|
||||
virtual bool getExpanded() const
|
||||
{ return Expanded; }
|
||||
|
||||
//! Sets if the node is expanded.
|
||||
virtual void setExpanded( bool expanded );
|
||||
|
||||
//! Returns true if the node is currently selected.
|
||||
virtual bool getSelected() const;
|
||||
|
||||
//! Sets this node as selected.
|
||||
virtual void setSelected( bool selected );
|
||||
|
||||
//! Returns true if this node is the root node.
|
||||
virtual bool isRoot() const;
|
||||
|
||||
//! Returns the level of this node.
|
||||
virtual s32 getLevel() const;
|
||||
|
||||
//! Returns true if this node is visible (all parents are expanded).
|
||||
virtual bool isVisible() const;
|
||||
|
||||
private:
|
||||
|
||||
CGUITreeView* Owner;
|
||||
CGUITreeViewNode* Parent;
|
||||
core::stringw Text;
|
||||
core::stringw Icon;
|
||||
s32 ImageIndex;
|
||||
s32 SelectedImageIndex;
|
||||
void* Data;
|
||||
IReferenceCounted* Data2;
|
||||
bool Expanded;
|
||||
core::list<CGUITreeViewNode*> Children;
|
||||
};
|
||||
|
||||
|
||||
//! Default tree view GUI element.
|
||||
class CGUITreeView : public IGUITreeView
|
||||
{
|
||||
friend class CGUITreeViewNode;
|
||||
|
||||
public:
|
||||
//! constructor
|
||||
CGUITreeView( IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle, bool clip = true,
|
||||
bool drawBack = false, bool scrollBarVertical = true, bool scrollBarHorizontal = true );
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUITreeView();
|
||||
|
||||
//! returns the root node (not visible) from the tree.
|
||||
virtual IGUITreeViewNode* getRoot() const
|
||||
{ return Root; }
|
||||
|
||||
//! returns the selected node of the tree or 0 if none is selected
|
||||
virtual IGUITreeViewNode* getSelected() const
|
||||
{ return Selected; }
|
||||
|
||||
//! returns true if the tree lines are visible
|
||||
virtual bool getLinesVisible() const
|
||||
{ return LinesVisible; }
|
||||
|
||||
//! sets if the tree lines are visible
|
||||
virtual void setLinesVisible( bool visible )
|
||||
{ LinesVisible = visible; }
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent( const SEvent &event );
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Sets the font which should be used as icon font. This font is set to the Irrlicht engine
|
||||
//! built-in-font by default. Icons can be displayed in front of every list item.
|
||||
//! An icon is a string, displayed with the icon font. When using the build-in-font of the
|
||||
//! Irrlicht engine as icon font, the icon strings defined in GUIIcons.h can be used.
|
||||
virtual void setIconFont( IGUIFont* font );
|
||||
|
||||
//! Sets the image list which should be used for the image and selected image of every node.
|
||||
//! The default is 0 (no images).
|
||||
virtual void setImageList( IGUIImageList* imageList );
|
||||
|
||||
//! Returns the image list which is used for the nodes.
|
||||
virtual IGUIImageList* getImageList() const
|
||||
{ return ImageList; }
|
||||
|
||||
//! Sets if the image is left of the icon. Default is true.
|
||||
virtual void setImageLeftOfIcon( bool bLeftOf )
|
||||
{ ImageLeftOfIcon = bLeftOf; }
|
||||
|
||||
//! Returns if the Image is left of the icon. Default is true.
|
||||
virtual bool getImageLeftOfIcon() const
|
||||
{ return ImageLeftOfIcon; }
|
||||
|
||||
//! Returns the node which is associated to the last event.
|
||||
virtual IGUITreeViewNode* getLastEventNode() const
|
||||
{ return LastEventNode; }
|
||||
|
||||
private:
|
||||
//! calculates the heigth of an node and of all visible nodes.
|
||||
void recalculateItemHeight();
|
||||
|
||||
//! executes an mouse action (like selectNew of CGUIListBox)
|
||||
void mouseAction( s32 xpos, s32 ypos, bool onlyHover = false );
|
||||
|
||||
CGUITreeViewNode* Root;
|
||||
IGUITreeViewNode* Selected;
|
||||
s32 ItemHeight;
|
||||
s32 IndentWidth;
|
||||
s32 TotalItemHeight;
|
||||
s32 TotalItemWidth;
|
||||
IGUIFont* Font;
|
||||
IGUIFont* IconFont;
|
||||
IGUIScrollBar* ScrollBarH;
|
||||
IGUIScrollBar* ScrollBarV;
|
||||
IGUIImageList* ImageList;
|
||||
IGUITreeViewNode* LastEventNode;
|
||||
bool LinesVisible;
|
||||
bool Selecting;
|
||||
bool Clip;
|
||||
bool DrawBack;
|
||||
bool ImageLeftOfIcon;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,404 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIWindow.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUIFontBitmap.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIWindow::CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
|
||||
: IGUIWindow(environment, parent, id, rectangle), Dragging(false), IsDraggable(true), DrawBackground(true), DrawTitlebar(true), IsActive(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIWindow");
|
||||
#endif
|
||||
|
||||
IGUISkin* skin = 0;
|
||||
if (environment)
|
||||
skin = environment->getSkin();
|
||||
|
||||
CurrentIconColor = video::SColor(255,255,255,255);
|
||||
|
||||
s32 buttonw = 15;
|
||||
if (skin)
|
||||
{
|
||||
buttonw = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
|
||||
}
|
||||
s32 posx = RelativeRect.getWidth() - buttonw - 4;
|
||||
|
||||
CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
|
||||
L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close" );
|
||||
CloseButton->setSubElement(true);
|
||||
CloseButton->setTabStop(false);
|
||||
CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
posx -= buttonw + 2;
|
||||
|
||||
RestoreButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
|
||||
L"", skin ? skin->getDefaultText(EGDT_WINDOW_RESTORE) : L"Restore" );
|
||||
RestoreButton->setVisible(false);
|
||||
RestoreButton->setSubElement(true);
|
||||
RestoreButton->setTabStop(false);
|
||||
RestoreButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
posx -= buttonw + 2;
|
||||
|
||||
MinButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
|
||||
L"", skin ? skin->getDefaultText(EGDT_WINDOW_MINIMIZE) : L"Minimize" );
|
||||
MinButton->setVisible(false);
|
||||
MinButton->setSubElement(true);
|
||||
MinButton->setTabStop(false);
|
||||
MinButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
|
||||
MinButton->grab();
|
||||
RestoreButton->grab();
|
||||
CloseButton->grab();
|
||||
|
||||
// this element is a tab group
|
||||
setTabGroup(true);
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
|
||||
refreshSprites();
|
||||
updateClientRect();
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIWindow::~CGUIWindow()
|
||||
{
|
||||
if (MinButton)
|
||||
MinButton->drop();
|
||||
|
||||
if (RestoreButton)
|
||||
RestoreButton->drop();
|
||||
|
||||
if (CloseButton)
|
||||
CloseButton->drop();
|
||||
}
|
||||
|
||||
void CGUIWindow::refreshSprites()
|
||||
{
|
||||
if (!Environment)
|
||||
return;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if ( !skin )
|
||||
return;
|
||||
|
||||
IGUISpriteBank* sprites = skin->getSpriteBank();
|
||||
if ( !sprites )
|
||||
return;
|
||||
|
||||
CurrentIconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
|
||||
|
||||
if (sprites)
|
||||
{
|
||||
CloseButton->setSpriteBank(sprites);
|
||||
CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), CurrentIconColor);
|
||||
CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), CurrentIconColor);
|
||||
|
||||
RestoreButton->setSpriteBank(sprites);
|
||||
RestoreButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_RESTORE), CurrentIconColor);
|
||||
RestoreButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_RESTORE), CurrentIconColor);
|
||||
|
||||
MinButton->setSpriteBank(sprites);
|
||||
MinButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_MINIMIZE), CurrentIconColor);
|
||||
MinButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_MINIMIZE), CurrentIconColor);
|
||||
}
|
||||
}
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIWindow::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
|
||||
{
|
||||
Dragging = false;
|
||||
IsActive = false;
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
|
||||
{
|
||||
if (Parent && ((event.GUIEvent.Caller == this) || isMyChild(event.GUIEvent.Caller)))
|
||||
{
|
||||
Parent->bringToFront(this);
|
||||
IsActive = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsActive = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
|
||||
{
|
||||
if (event.GUIEvent.Caller == CloseButton)
|
||||
{
|
||||
if (Parent)
|
||||
{
|
||||
// send close event to parent
|
||||
SEvent e;
|
||||
e.EventType = EET_GUI_EVENT;
|
||||
e.GUIEvent.Caller = this;
|
||||
e.GUIEvent.Element = 0;
|
||||
e.GUIEvent.EventType = EGET_ELEMENT_CLOSED;
|
||||
|
||||
// if the event was not absorbed
|
||||
if (!Parent->OnEvent(e))
|
||||
remove();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
Dragging = IsDraggable;
|
||||
if (Parent)
|
||||
Parent->bringToFront(this);
|
||||
return true;
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
Dragging = false;
|
||||
return true;
|
||||
case EMIE_MOUSE_MOVED:
|
||||
if (!event.MouseInput.isLeftPressed())
|
||||
Dragging = false;
|
||||
|
||||
if (Dragging)
|
||||
{
|
||||
// gui window should not be dragged outside its parent
|
||||
if (Parent &&
|
||||
(event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||
|
||||
event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||
|
||||
event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||
|
||||
event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1))
|
||||
return true;
|
||||
|
||||
move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! Updates the absolute position.
|
||||
void CGUIWindow::updateAbsolutePosition()
|
||||
{
|
||||
IGUIElement::updateAbsolutePosition();
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIWindow::draw()
|
||||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
|
||||
// update each time because the skin is allowed to change this always.
|
||||
updateClientRect();
|
||||
|
||||
if ( CurrentIconColor != skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL) )
|
||||
refreshSprites();
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
|
||||
// draw body fast
|
||||
if (DrawBackground)
|
||||
{
|
||||
rect = skin->draw3DWindowBackground(this, DrawTitlebar,
|
||||
skin->getColor(IsActive ? EGDC_ACTIVE_BORDER : EGDC_INACTIVE_BORDER),
|
||||
AbsoluteRect, &AbsoluteClippingRect);
|
||||
|
||||
if (DrawTitlebar && Text.size())
|
||||
{
|
||||
rect.UpperLeftCorner.X += skin->getSize(EGDS_TITLEBARTEXT_DISTANCE_X);
|
||||
rect.UpperLeftCorner.Y += skin->getSize(EGDS_TITLEBARTEXT_DISTANCE_Y);
|
||||
rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;
|
||||
|
||||
IGUIFont* font = skin->getFont(EGDF_WINDOW);
|
||||
if (font)
|
||||
{
|
||||
font->draw(Text.c_str(), rect,
|
||||
skin->getColor(IsActive ? EGDC_ACTIVE_CAPTION:EGDC_INACTIVE_CAPTION),
|
||||
false, true, &AbsoluteClippingRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! Returns pointer to the close button
|
||||
IGUIButton* CGUIWindow::getCloseButton() const
|
||||
{
|
||||
return CloseButton;
|
||||
}
|
||||
|
||||
|
||||
//! Returns pointer to the minimize button
|
||||
IGUIButton* CGUIWindow::getMinimizeButton() const
|
||||
{
|
||||
return MinButton;
|
||||
}
|
||||
|
||||
|
||||
//! Returns pointer to the maximize button
|
||||
IGUIButton* CGUIWindow::getMaximizeButton() const
|
||||
{
|
||||
return RestoreButton;
|
||||
}
|
||||
|
||||
|
||||
//! Returns true if the window is draggable, false if not
|
||||
bool CGUIWindow::isDraggable() const
|
||||
{
|
||||
return IsDraggable;
|
||||
}
|
||||
|
||||
|
||||
//! Sets whether the window is draggable
|
||||
void CGUIWindow::setDraggable(bool draggable)
|
||||
{
|
||||
IsDraggable = draggable;
|
||||
|
||||
if (Dragging && !IsDraggable)
|
||||
Dragging = false;
|
||||
}
|
||||
|
||||
|
||||
//! Set if the window background will be drawn
|
||||
void CGUIWindow::setDrawBackground(bool draw)
|
||||
{
|
||||
DrawBackground = draw;
|
||||
}
|
||||
|
||||
|
||||
//! Get if the window background will be drawn
|
||||
bool CGUIWindow::getDrawBackground() const
|
||||
{
|
||||
return DrawBackground;
|
||||
}
|
||||
|
||||
|
||||
//! Set if the window titlebar will be drawn
|
||||
void CGUIWindow::setDrawTitlebar(bool draw)
|
||||
{
|
||||
DrawTitlebar = draw;
|
||||
}
|
||||
|
||||
|
||||
//! Get if the window titlebar will be drawn
|
||||
bool CGUIWindow::getDrawTitlebar() const
|
||||
{
|
||||
return DrawTitlebar;
|
||||
}
|
||||
|
||||
|
||||
void CGUIWindow::updateClientRect()
|
||||
{
|
||||
if (! DrawBackground )
|
||||
{
|
||||
ClientRect = core::rect<s32>(0,0, AbsoluteRect.getWidth(), AbsoluteRect.getHeight());
|
||||
return;
|
||||
}
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
skin->draw3DWindowBackground(this, DrawTitlebar,
|
||||
skin->getColor(IsActive ? EGDC_ACTIVE_BORDER : EGDC_INACTIVE_BORDER),
|
||||
AbsoluteRect, &AbsoluteClippingRect, &ClientRect);
|
||||
ClientRect -= AbsoluteRect.UpperLeftCorner;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the rectangle of the drawable area (without border, without titlebar and without scrollbars)
|
||||
core::rect<s32> CGUIWindow::getClientRect() const
|
||||
{
|
||||
return ClientRect;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIWindow::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIWindow::serializeAttributes(out,options);
|
||||
|
||||
out->addBool("IsDraggable", IsDraggable);
|
||||
out->addBool("DrawBackground", DrawBackground);
|
||||
out->addBool("DrawTitlebar", DrawTitlebar);
|
||||
|
||||
// Currently we can't just serialize attributes of sub-elements.
|
||||
// To do this we either
|
||||
// a) allow further serialization after attribute serialiation (second function, callback or event)
|
||||
// b) add an IGUIElement attribute
|
||||
// c) extend the attribute system to allow attributes to have sub-attributes
|
||||
// We just serialize the most important info for now until we can do one of the above solutions.
|
||||
out->addBool("IsCloseVisible", CloseButton->isVisible());
|
||||
out->addBool("IsMinVisible", MinButton->isVisible());
|
||||
out->addBool("IsRestoreVisible", RestoreButton->isVisible());
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIWindow::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIWindow::deserializeAttributes(in,options);
|
||||
|
||||
Dragging = false;
|
||||
IsActive = false;
|
||||
IsDraggable = in->getAttributeAsBool("IsDraggable");
|
||||
DrawBackground = in->getAttributeAsBool("DrawBackground");
|
||||
DrawTitlebar = in->getAttributeAsBool("DrawTitlebar");
|
||||
|
||||
CloseButton->setVisible(in->getAttributeAsBool("IsCloseVisible"));
|
||||
MinButton->setVisible(in->getAttributeAsBool("IsMinVisible"));
|
||||
RestoreButton->setVisible(in->getAttributeAsBool("IsRestoreVisible"));
|
||||
|
||||
updateClientRect();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user