The reason you don't get back any scene node is that the
IGUIFont* that is being passed to
addTextSceneNode() is NULL. A small tweak to
CSceneManager::addTextSceneNode() or
CDefaultSceneNodeFactory::addSceneNode() could be used to set a default font, but that isn't really the right way to fix it. Something needs to be added to Irrlicht to allow for the font to be serialized. This is something the Irrlicht dev guys will need to decide how to handle.
In the meantime, I have a workaround, provided that you only need to use one font for all of your billboard text scene nodes.
First, to get the scene nodes to serialize their attributes properly, you would need to add code to and recompile the library, but that is easy enough...
Code: Select all
// add the serizeAttributes() and deserializeAttributes() declarations to the types in CTextSceneNode.h
class CTextSceneNode : public ITextSceneNode
{
public:
//...
//! 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);
//...
};
class CBillboardTextSceneNode : public ITextSceneNode
{
public:
//...
//! 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);
//...
};
Code: Select all
// add the serizeAttributes() and deserializeAttributes() definitions to CTextSceneNode.cpp
//! Writes attributes of the scene node.
void CTextSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
{
ITextSceneNode::serializeAttributes(out, options);
out->addString("Text", Text.c_str());
out->addColor ("Color", Color );
// we have no way to serialize the font at this time
}
//! Reads attributes of the scene node.
void CTextSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
ITextSceneNode::deserializeAttributes(in, options);
Text = in->getAttributeAsStringW( "Text" );
Color = in->getAttributeAsColor ( "Color" );
// we have no way to deserialize the font at this time
}
//! Writes attributes of the scene node.
void CBillboardTextSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
{
ITextSceneNode::serializeAttributes(out, options);
out->addString("Text", Text.c_str());
out->addColor ("Color", Color );
out->addColor ("Shade_top", Shade_top);
out->addColor ("Shade_bottom", Shade_bottom);
out->addFloat("Width", Size.Width);
out->addFloat("Height", Size.Height);
// we have no way to serialize the font at this time
}
//! Reads attributes of the scene node.
void CBillboardTextSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
ITextSceneNode::deserializeAttributes(in, options);
Text = in->getAttributeAsStringW( "Text" );
Color = in->getAttributeAsColor ( "Color" );
Shade_top = in->getAttributeAsColor ( "Shade_top" );
Shade_bottom = in->getAttributeAsColor ("Shade_bottom" );
Size.Width = in->getAttributeAsFloat("Width");
Size.Height = in->getAttributeAsFloat("Height");
setSize(Size);
setText(Text.c_str());
// we have no way to deserialize the font correctly at this time
}
Then rebuild the library. Once you've done that, you just need to write your own scene node factory that can be used to create scene nodes of the appropriate type with the appropriate font.
Code: Select all
class MySceneNodeFactory : public scene::ISceneNodeFactory
{
public:
MySceneNodeFactory(scene::ISceneManager* mgr, gui::IGUIFont* font)
: Manager(mgr), Font(font)
{
if (Font)
Font->grab();
}
virtual ~MySceneNodeFactory()
{
if (Font)
Font->drop();
}
void setDefaultFont(gui::IGUIFont* font)
{
if (Font != font) {
if (Font != 0)
Font->drop();
Font = font;
if (Font != 0)
Font->grab();
}
}
gui::IGUIFont* getDefaultFont() const
{
return Font;
}
//! adds a scene node to the scene graph based on its type id
virtual scene::ISceneNode* addSceneNode(scene::ESCENE_NODE_TYPE type, scene::ISceneNode* parent = 0)
{
if (scene::ESNT_TEXT == type) {
return Manager->addBillboardTextSceneNode(Font, L"", parent);
}
return 0;
}
//! adds a scene node to the scene graph based on its type name
virtual scene::ISceneNode* addSceneNode(const c8* typeName, scene::ISceneNode* parent = 0)
{
if (!strcmp (typeName, "text")) {
return Manager->addBillboardTextSceneNode(Font, L"", parent);
}
return 0;
}
//! returns amount of scene node types this factory is able to create
virtual u32 getCreatableSceneNodeTypeCount() const
{
return 1;
}
//! returns type name of a createable scene node type by index
virtual const c8* getCreateableSceneNodeTypeName(u32 idx) const
{
_IRR_DEBUG_BREAK_IF(idx != 0)
return "text";
}
//! returns type of a createable scene node type
virtual scene::ESCENE_NODE_TYPE getCreateableSceneNodeType(u32 idx) const
{
_IRR_DEBUG_BREAK_IF(idx != 0)
return scene::ESNT_TEXT;
}
//! returns type name of a createable scene node type
virtual const c8* getCreateableSceneNodeTypeName(scene::ESCENE_NODE_TYPE type) const
{
if (scene::ESNT_TEXT == type)
return "text";
return 0;
}
private:
scene::ISceneManager* Manager;
gui::IGUIFont* Font;
};
Now just create an instance of the factory, and register it with the scene manager...
Code: Select all
MySceneNodeFactory factory(smgr, gui->getBuiltInFont());
smgr->registerSceneNodeFactory(&factory);
Now you should be able to serialize the billboard text scene nodes without any trouble.
Travis