commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
189
include/engine/scene3d/group.cpp
Normal file
189
include/engine/scene3d/group.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/group.h"
|
||||
#include "scene3d/mitem.h"
|
||||
#include "motion/motion_automation_source.h"
|
||||
#include "automation/automation_source_group.h"
|
||||
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Group::AppendGroup(const Group &group)
|
||||
{
|
||||
ListForeachPtr(MItem *, i, group.item_list)
|
||||
if (!Add(i))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Group::SetInvisible(bool v)
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
i->GetBaseItem()->item_flags.Raise(ItemFlagInvisible, v);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Group::IsMember(const MItem *i) const
|
||||
{
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item == i)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool Group::IsMember(const Group *g) const
|
||||
{
|
||||
ListForeachPtr(Group *, group, group_list)
|
||||
if (group == g)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
void Group::SetRootItem(MItem *i)
|
||||
{
|
||||
if (root)
|
||||
if (Core::Item *base_root = root->GetBaseItem())
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (Core::Item *b = item->GetBaseItem())
|
||||
if (b->GetParent() == base_root)
|
||||
b->SetParent(NULL);
|
||||
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (Core::Item *b = item->GetBaseItem())
|
||||
if (!b->GetParent())
|
||||
b->SetParent(i ? i->GetBaseItem() : NULL);
|
||||
|
||||
root = i;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Group::Offset(const GS::Matrix4 &m)
|
||||
{
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (Core::Item *b = item->GetBaseItem())
|
||||
if (!b->GetParent())
|
||||
b->SnapshotTransformation(m * b->GetMatrix());
|
||||
}
|
||||
void Group::Translate(float x, float y, float z)
|
||||
{
|
||||
Vector4 translation(x, y, z);
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (Core::Item *b = item->GetBaseItem())
|
||||
if (!b->GetParent())
|
||||
b->SetPosition(b->GetPosition() + translation);
|
||||
}
|
||||
void Group::Rotate(float x, float y, float z)
|
||||
{
|
||||
Vector4 rotation(x, y, z);
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (Core::Item *b = item->GetBaseItem())
|
||||
if (!b->GetParent())
|
||||
b->SetRotation(b->GetRotation() + rotation);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MItem *Group::Item(const char *item_id) const
|
||||
{
|
||||
String seek(item_id);
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->name == seek)
|
||||
return item;
|
||||
__ERR__(__LOG_W__ << "No item '" << item_id << "' in group '" << name << "'.\n", NULL)
|
||||
}
|
||||
MItem *Group::ItemFromUid(uint uid) const
|
||||
{
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->GetUid() == uid)
|
||||
return item;
|
||||
__ERR__(__LOG_W__ << "No item with uid '" << uid << "' in group '" << name << "'.\n", NULL)
|
||||
}
|
||||
Group *Group::GetGroup(const char *_name) const
|
||||
{
|
||||
ListForeachPtr(Group *, group, group_list)
|
||||
if (group->name == _name)
|
||||
return group;
|
||||
__ERR__(__LOG_W__ << "Could not find group '" << _name << "' in group '" << name << "'.\n", NULL)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MItem *Group::Add(MItem *i, bool block_duplicate)
|
||||
{
|
||||
if (!i || (block_duplicate && IsMember(i)))
|
||||
return NULL;
|
||||
|
||||
item_list.Add(i);
|
||||
return i;
|
||||
}
|
||||
bool Group::Remove(MItem *i)
|
||||
{
|
||||
return item_list.Remove(i);
|
||||
}
|
||||
Group *Group::Add(Group *g, bool block_duplicate)
|
||||
{
|
||||
if (!g || (block_duplicate && IsMember(g)))
|
||||
return NULL;
|
||||
|
||||
group_list.Add(g);
|
||||
return g;
|
||||
}
|
||||
bool Group::Remove(Group *g)
|
||||
{ return group_list.Remove(g); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Group::RenderSetup(GS::Core::ResourceFactories *f)
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (Core::Item *b = i->GetBaseItem())
|
||||
b->RenderSetup(f);
|
||||
}
|
||||
void Group::Setup()
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
i->Setup(NULL);
|
||||
}
|
||||
void Group::Reset()
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
i->Reset();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Group::SetMotion(const char *name, GS::Automation::SourceGroup **group, float blend, GS::Automation::Player::AddSourceMode mode, float weight)
|
||||
{
|
||||
if (group)
|
||||
*group = new Automation::SourceGroup;
|
||||
|
||||
SceneMotion *scene_motion = NULL;
|
||||
|
||||
ListForeachPtr(SceneMotion *, m, motion.motions)
|
||||
if (m->name == name)
|
||||
{
|
||||
scene_motion = m;
|
||||
break;
|
||||
}
|
||||
|
||||
if (scene_motion)
|
||||
{
|
||||
// Start item motions.
|
||||
ListForeachPtr(SceneMotion::ItemMotion *, m, scene_motion->item_motions)
|
||||
if (MItem *i = ItemFromUid(m->uid))
|
||||
i->automation_player->StartAutomation(new Automation::MotionSource(m->motion, group ? *group : NULL), blend, mode, weight);
|
||||
}
|
||||
else
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (Motion *motion = i->automation_player->GetMotion(name))
|
||||
i->automation_player->StartAutomation(new Automation::MotionSource(motion, *group), blend, mode, weight);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
97
include/engine/scene3d/instance.cpp
Normal file
97
include/engine/scene3d/instance.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/instance.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/group.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "script/scripted_object.h"
|
||||
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Instance::RenderSetup(ResourceFactories *f)
|
||||
{
|
||||
if (instance_group)
|
||||
instance_group->RenderSetup(f);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Instance::ComputeMinMax(GS::MinMax &minmax) const
|
||||
{
|
||||
if (!instance_group)
|
||||
return;
|
||||
|
||||
MinMax l_minmax;
|
||||
const SharedList <MItem *> &items = instance_group->GetItemList();
|
||||
|
||||
bool first = true;
|
||||
ListForeachPtr(MItem *, i, items)
|
||||
if (i->GetItemType() == Type_Object)
|
||||
{
|
||||
MObject *o = (MObject *)i;
|
||||
o->ComputeLocalMinMax(l_minmax);
|
||||
|
||||
if (first)
|
||||
minmax = l_minmax;
|
||||
else minmax.Grow(l_minmax);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Instance::Instantiate(Scene *owner)
|
||||
{
|
||||
if (instance_group)
|
||||
return true;
|
||||
if (!owner || template_path.IsEmpty() || !isActive())
|
||||
return false;
|
||||
|
||||
using namespace NML;
|
||||
File file;
|
||||
if (Parser::Load(template_path, file))
|
||||
{
|
||||
// Load scene scripted object on this instance.
|
||||
if (Tag *script_tag = file.GetTag("Scene:ScriptedObject;"))
|
||||
scripted_object->FromMetaTag(*script_tag);
|
||||
|
||||
// Append template scene to this scene.
|
||||
owner->FromMetaFileStoreGroup(template_path, &instance_group, SceneIOAll & ~(SceneIOGlobals | SceneIOSettings | SceneIOHelper | SceneIOScript));
|
||||
}
|
||||
|
||||
if (instance_group)
|
||||
{
|
||||
instance_group->name = template_path;
|
||||
|
||||
if (do_not_parent)
|
||||
instance_group->Offset(GetMatrix());
|
||||
else instance_group->SetRootItem(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void Instance::FreeEditorInstance()
|
||||
{
|
||||
instance_scene = NULL;
|
||||
instance_group = NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Instance::Instance()
|
||||
{
|
||||
item_type = Type_Instance;
|
||||
mitem = (void *)((MItem *)this);
|
||||
|
||||
instance_group = NULL;
|
||||
do_not_parent = false;
|
||||
}
|
||||
Instance::~Instance()
|
||||
{
|
||||
// group is deleted by the scene it belongs to.
|
||||
}
|
||||
53
include/engine/scene3d/instance_nml.cpp
Normal file
53
include/engine/scene3d/instance_nml.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/instance.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::NML;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Instance::FromMetaTag(Tag &tag)
|
||||
{
|
||||
if (tag.name != "Instance")
|
||||
__ERR__(__LOG_E__ << "Could not parse instance, incorrect root tag (" << tag.name << ").\n", false)
|
||||
|
||||
do_not_parent = false;
|
||||
|
||||
NMLTagForeach(pt, tag)
|
||||
{
|
||||
if (pt->name == "MItem")
|
||||
MItem::FromMetaTag(*pt);
|
||||
else if (pt->name == "Item")
|
||||
Item::FromMetaTag(*pt);
|
||||
|
||||
else if (pt->name == "Template")
|
||||
template_path = pt->GetString();
|
||||
else if (pt->name == "DoNotParent")
|
||||
do_not_parent = pt->GetBool();
|
||||
|
||||
else __LOG_W__ << "Unknown tag '" << pt->name << "' in <Instance>.\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Tag *Instance::AsMetaTag()
|
||||
{
|
||||
Tag *root = new Tag("Instance");
|
||||
if (!root)
|
||||
__ERR__(__LOG_E__ << "Could not create root tag to serialize.\n", NULL)
|
||||
|
||||
root->AddChild(MItem::AsMetaTag());
|
||||
root->AddChild(Item::AsMetaTag());
|
||||
|
||||
root->AddChild("Template", template_path);
|
||||
if (do_not_parent)
|
||||
root->AddChild("DoNotParent", do_not_parent);
|
||||
|
||||
return root;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
59
include/engine/scene3d/item_automated_property_provider.cpp
Normal file
59
include/engine/scene3d/item_automated_property_provider.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/item_automated_property_provider.h"
|
||||
#include "core/item.h"
|
||||
|
||||
using GS::Quaternion;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D::Automation;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ItemPropertyProvider::GetProperty(MotionChannel::Type type, float &v)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MotionChannel::XPos: v = item->GetPosition().x; return true;
|
||||
case MotionChannel::YPos: v = item->GetPosition().y; return true;
|
||||
case MotionChannel::ZPos: v = item->GetPosition().z; return true;
|
||||
case MotionChannel::XRot: v = item->GetRotation().x; return true;
|
||||
case MotionChannel::YRot: v = item->GetRotation().y; return true;
|
||||
case MotionChannel::ZRot: v = item->GetRotation().z; return true;
|
||||
case MotionChannel::XScl: v = item->GetScale().x; return true;
|
||||
case MotionChannel::YScl: v = item->GetScale().y; return true;
|
||||
case MotionChannel::ZScl: v = item->GetScale().z; return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool ItemPropertyProvider::SetProperty(MotionChannel::Type type, float v)
|
||||
{
|
||||
Vector4 t;
|
||||
switch (type)
|
||||
{
|
||||
case MotionChannel::XPos: t = item->GetPosition(); t.x = v; item->SetPosition(t); return true;
|
||||
case MotionChannel::YPos: t = item->GetPosition(); t.y = v; item->SetPosition(t); return true;
|
||||
case MotionChannel::ZPos: t = item->GetPosition(); t.z = v; item->SetPosition(t); return true;
|
||||
case MotionChannel::XRot: t = item->GetRotation(); t.x = v; item->SetRotation(t); return true;
|
||||
case MotionChannel::YRot: t = item->GetRotation(); t.y = v; item->SetRotation(t); return true;
|
||||
case MotionChannel::ZRot: t = item->GetRotation(); t.z = v; item->SetRotation(t); return true;
|
||||
case MotionChannel::XScl: t = item->GetScale(); t.x = v; item->SetScale(t); return true;
|
||||
case MotionChannel::YScl: t = item->GetScale(); t.y = v; item->SetScale(t); return true;
|
||||
case MotionChannel::ZScl: t = item->GetScale(); t.z = v; item->SetScale(t); return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Quaternion ItemPropertyProvider::GetRotation() const
|
||||
{
|
||||
const Vector4 &e = item->GetRotation();
|
||||
return Quaternion::FromEuler(e.x, e.y, e.z, item->GetRotationOrder());
|
||||
}
|
||||
bool ItemPropertyProvider::SetRotation(const Quaternion &q)
|
||||
{
|
||||
item->SetRotation(q);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
19
include/engine/scene3d/mcamera.cpp
Normal file
19
include/engine/scene3d/mcamera.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "scene3d/scene_message.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MCamera::MCamera()
|
||||
{
|
||||
item_type = Type_Camera;
|
||||
mitem = (void *)((MItem *)this);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
41
include/engine/scene3d/mcamera_nml.cpp
Normal file
41
include/engine/scene3d/mcamera_nml.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::NML;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MCamera::FromMetaTag(Tag &tag)
|
||||
{
|
||||
if (tag.name != "MCamera")
|
||||
__ERR__(__LOG_E__ << "Could not parse managed camera, incorrect root tag (" << tag.name << ").\n", false)
|
||||
|
||||
NMLTagForeach(pt, tag)
|
||||
{
|
||||
if (pt->name == "MItem")
|
||||
MItem::FromMetaTag(*pt);
|
||||
else if (pt->name == "Camera")
|
||||
Camera::FromMetaTag(*pt);
|
||||
else
|
||||
__LOG_W__ << "Unknown tag '" << pt->name << "' in <MCamera>.\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Tag *MCamera::AsMetaTag()
|
||||
{
|
||||
Tag *root = new Tag("MCamera");
|
||||
if (!root)
|
||||
__ERR__(__LOG_E__ << "Could not create root tag to serialize.\n", NULL)
|
||||
|
||||
root->AddChild(MItem::AsMetaTag());
|
||||
root->AddChild(Camera::AsMetaTag());
|
||||
return root;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
59
include/engine/scene3d/mconstraint.cpp
Normal file
59
include/engine/scene3d/mconstraint.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mconstraint.h"
|
||||
#include "physic/physic_constraint.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::NML;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void MConstraint::Setup(PhysicWorld *world)
|
||||
{
|
||||
if (world)
|
||||
{
|
||||
physic_data = world->NewConstraint();
|
||||
physic_data->SetupConstraint(desc);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MConstraint::FromMetaTag(Tag &tag)
|
||||
{
|
||||
if (tag.name != "MConstraint")
|
||||
__ERR__(__LOG_E__ << "Could not parse managed constraint, incorrect root tag (" << tag.name << ").\n", false)
|
||||
|
||||
NMLTagForeach(pt, tag)
|
||||
{
|
||||
if (pt->name == "MItem")
|
||||
MItem::FromMetaTag(*pt);
|
||||
else if (pt->name == "Constraint")
|
||||
desc.FromMetaTag(*pt);
|
||||
else __LOG_W__ << "Unknown tag '" << pt->name << "' in <nMConstraint>.\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Tag *MConstraint::AsMetaTag()
|
||||
{
|
||||
Tag *root = new Tag("MConstraint");
|
||||
if (!root)
|
||||
__ERR__(__LOG_E__ << "Could not create managed constraint tag to serialize.\n", NULL)
|
||||
|
||||
root->AddChild(MItem::AsMetaTag());
|
||||
root->AddChild(desc.AsMetaTag());
|
||||
|
||||
return root;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
MConstraint::MConstraint(PhysicConstraint *c) : physic_data(c)
|
||||
{
|
||||
item_type = Type_Constraint;
|
||||
}
|
||||
31
include/engine/scene3d/memitter.cpp
Normal file
31
include/engine/scene3d/memitter.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/memitter.h"
|
||||
#include "scene3d/scene_message.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void MEmitter::Update(const GS::Time &dt)
|
||||
{
|
||||
Emitter::Update(dt);
|
||||
MItem::Update(dt);
|
||||
}
|
||||
void MEmitter::Setup(PhysicWorld *)
|
||||
{
|
||||
Emitter::Setup();
|
||||
MItem::Setup(NULL);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
MEmitter::MEmitter()
|
||||
{
|
||||
item_type = Type_Emitter;
|
||||
mitem = (void *)((MItem *)this);
|
||||
priority = 1;
|
||||
}
|
||||
39
include/engine/scene3d/memitter_nml.cpp
Normal file
39
include/engine/scene3d/memitter_nml.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/memitter.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::NML;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MEmitter::FromMetaTag(Tag &tag)
|
||||
{
|
||||
if (tag.name != "MEmitter")
|
||||
__ERR__(__LOG_E__ << "could not parse managed emitter, incorrect root tag (" << tag.name << ").\n", false)
|
||||
|
||||
// Parse root tags.
|
||||
NMLTagForeach(pt, tag)
|
||||
{
|
||||
if (pt->name == "MItem") MItem::FromMetaTag(*pt);
|
||||
else if (pt->name == "Emitter") Emitter::FromMetaTag(*pt);
|
||||
else __LOG_W__ << "Unknown tag '" << pt->name << "' in <MEmitter>.\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Tag *MEmitter::AsMetaTag()
|
||||
{
|
||||
Tag *root = new Tag("MEmitter");
|
||||
if (!root)
|
||||
__ERR__(__LOG_E__ << "Could not create root tag to serialize.\n", NULL)
|
||||
|
||||
root->AddChild(MItem::AsMetaTag());
|
||||
root->AddChild(Emitter::AsMetaTag());
|
||||
return root;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
150
include/engine/scene3d/mitem.cpp
Normal file
150
include/engine/scene3d/mitem.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mitem.h"
|
||||
#include "scene3d/mterrain.h"
|
||||
#include "scene3d/scene_ace_manager.h"
|
||||
#include "scene3d/item_automated_property_provider.h"
|
||||
#include "scene3d/mitem_event_interface.h"
|
||||
#include "scene3d/mitem_scripted_object.h"
|
||||
#include "scene3d/scene_message.h"
|
||||
#include "automation/automation_player.h"
|
||||
#include "script/script_engine_types.h"
|
||||
#include "rand/rand.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MItem::ExecCommand(GS::ACE::Command *cmd, float dt)
|
||||
{
|
||||
float k = dt / cmd->duration_left;
|
||||
Core::Item *i = GetBaseItem();
|
||||
|
||||
switch (cmd->code)
|
||||
{
|
||||
case ACESN_toposition:
|
||||
i->SetPosition(i->GetPosition() + (Vector4(cmd->parm[0], cmd->parm[1], cmd->parm[2]) - i->GetPosition()) * k);
|
||||
return true;
|
||||
|
||||
case ACESN_tooffset:
|
||||
{
|
||||
Matrix4 offset = i->GetPivot();
|
||||
offset.m[0][3] += (cmd->parm[0] - offset.m[0][3]) * k;
|
||||
offset.m[1][3] += (cmd->parm[1] - offset.m[1][3]) * k;
|
||||
offset.m[2][3] += (cmd->parm[2] - offset.m[2][3]) * k;
|
||||
i->SetPivot(offset);
|
||||
}
|
||||
return true;
|
||||
|
||||
case ACESN_offsetposition:
|
||||
k = dt / cmd->duration;
|
||||
i->SetPosition(i->GetPosition() + Vector4(cmd->parm[0], cmd->parm[1], cmd->parm[2]) * k);
|
||||
return true;
|
||||
|
||||
case ACESN_toscale:
|
||||
i->SetScale(i->GetScale() + (Vector4(cmd->parm[0], cmd->parm[1], cmd->parm[2]) - i->GetScale()) * k);
|
||||
return true;
|
||||
|
||||
case ACESN_torotation:
|
||||
i->SetRotation(i->GetRotation() + (Vector4(Units::Deg(cmd->parm[0]), Units::Deg(cmd->parm[1]), Units::Deg(cmd->parm[2])) - i->GetRotation()) * k);
|
||||
return true;
|
||||
|
||||
case ACESN_toalpha:
|
||||
i->opacity = Types::Clamp(i->opacity + Types::Clamp(i->opacity + (cmd->parm[0] - i->opacity) * k));
|
||||
return true;
|
||||
}
|
||||
return ACE::Unit::ExecCommand(cmd, dt);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void MItem::SetInitialTransformation()
|
||||
{
|
||||
// Note: We do not want to snapshot the pivot here.
|
||||
initial_matrix = GetBaseItem()->GetPivot().InversedFast() * GetBaseItem()->GetLocalMatrix();
|
||||
initial_state_set = true;
|
||||
}
|
||||
void MItem::ResetToInitialTransformation()
|
||||
{
|
||||
if (initial_state_set)
|
||||
GetBaseItem()->SnapshotTransformation(initial_matrix, true);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void MItem::Update(const GS::Time &dt)
|
||||
{
|
||||
automation_player->Evaluate(dt);
|
||||
ACEManager::Get()->UpdateACEUnit(this, dt.toSec());
|
||||
}
|
||||
void MItem::Setup(PhysicWorld *physic_world)
|
||||
{
|
||||
item_event->OnSetup(this);
|
||||
|
||||
// [EJ] must be done here for the time being as MItem base class cannot resolve the Item class.
|
||||
if (automation_player->property_provider.IsNull())
|
||||
automation_player->property_provider = new Automation::ItemPropertyProvider(GetBaseItem());
|
||||
|
||||
// Setup physics.
|
||||
if (physic_world && physic_item)
|
||||
{
|
||||
if (GetItemType() == MTerrain::GetMItemClassType())
|
||||
if (MTerrain *t = (MTerrain *)this)
|
||||
{
|
||||
// If the terrain physic item has an heightmap shape, link it to our heightmap.
|
||||
ListForeachPtr(PhysicShape *, shape, physic_item_desc.shape_list)
|
||||
if (shape->GetType() == PhysicShape::TypeHeightmap)
|
||||
shape->Set(t->GetHeightmap(), t->GetHeightmapPitch(), t->GetHeightmapHeight(), t->GetUnit());
|
||||
}
|
||||
|
||||
physic_item->SetScale(GetBaseItem()->GetScale());
|
||||
physic_item->SetupBody(physic_item_desc, physic_world);
|
||||
}
|
||||
|
||||
item_event->OnSetupDone(this);
|
||||
}
|
||||
|
||||
void MItem::ForceUpdateMassShapePhysic(PhysicWorld *physic_world)
|
||||
{
|
||||
// update mass physics.
|
||||
if (physic_world && physic_item)
|
||||
{
|
||||
physic_item->ForceUpdateMassShapePhysic(physic_item_desc, physic_world);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MItem::Reset()
|
||||
{
|
||||
item_event->OnReset(this);
|
||||
|
||||
// Update matrix.
|
||||
if (physic_item)
|
||||
{
|
||||
physic_item->ResetBody();
|
||||
physic_item->SetMatrix(GetBaseItem()->GetMatrix());
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MItem::MItem()
|
||||
{
|
||||
uid = uint(~0);
|
||||
|
||||
global_alpha = 1.f;
|
||||
mitem_flags.Set(Flag_IsActive);
|
||||
|
||||
initial_state_set = false;
|
||||
initial_matrix = Matrix4::IdentityMatrix();
|
||||
|
||||
priority = 0.5;
|
||||
|
||||
item_event = new IItemEvent;
|
||||
automation_player = new GS::Automation::Player;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
195
include/engine/scene3d/mitem_event_script_interface.cpp
Normal file
195
include/engine/scene3d/mitem_event_script_interface.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mitem_event_script_interface.h"
|
||||
#include "scene3d/mitem_scripted_object.h"
|
||||
#include "scene3d/mitem_script_unit.h"
|
||||
#include "scene3d/mtrigger.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "script/script_engine_types.h"
|
||||
#include "script/script_variant.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void MItemScriptEvent::OnSetup(MItem *item)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnSetup"))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void MItemScriptEvent::OnSetupDone(MItem *item)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnSetupDone"))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void MItemScriptEvent::OnReset(MItem *item)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnReset"))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void MItemScriptEvent::OnActivate(MItem *item, bool activate)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (((MItemScriptUnit *)unit)->activation_callback && unit->SetupFunctionCall("OnActivate", ((MItemScriptUnit *)unit)->activation_callback))
|
||||
{
|
||||
unit->PushFunctionCallArgument(activate);
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
void MItemScriptEvent::OnUpdate(MItem *item)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (((MItemScriptUnit *)unit)->update_callback && unit->SetupFunctionCall("OnUpdate", ((MItemScriptUnit *)unit)->update_callback))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void MItemScriptEvent::OnPhysicStep(MItem *item, bool step_taken)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (((MItemScriptUnit *)unit)->physic_callback && unit->SetupFunctionCall("OnPhysicStep", ((MItemScriptUnit *)unit)->physic_callback))
|
||||
{
|
||||
unit->PushFunctionCallArgument(step_taken);
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
void MItemScriptEvent::OnCollision(MItem *item, MItem *with, const CollisionPair &pair)
|
||||
{
|
||||
if (!item->isActive())
|
||||
return;
|
||||
|
||||
IVM *vm = item->scripted_object->GetVM();
|
||||
|
||||
// Check if the contact informations will be needed.
|
||||
bool contact_info_required = false;
|
||||
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (((MItemScriptUnit *)unit)->collisionex_callback.IsValid())
|
||||
{ contact_info_required = true; break; }
|
||||
|
||||
if (contact_info_required)
|
||||
{
|
||||
AutoPtr <Object> table_object(vm->CreateTable());
|
||||
table_object->Set("count", pair.contact_count);
|
||||
|
||||
// Contact point.
|
||||
AutoPtr <Object> ctc_object(vm->CreateArray());
|
||||
for (uint n = 0; n < pair.contact_count; ++n)
|
||||
if (vm->SetupFunctionCall("Vector"))
|
||||
{
|
||||
vm->PushArgument(pair.contact[n].x);
|
||||
vm->PushArgument(pair.contact[n].y);
|
||||
vm->PushArgument(pair.contact[n].z);
|
||||
Script::Variant rv;
|
||||
vm->DoFunctionCall(&rv);
|
||||
ctc_object->Append(rv);
|
||||
}
|
||||
|
||||
table_object->Set("p", ctc_object.c_ptr());
|
||||
|
||||
// Contact normal.
|
||||
AutoPtr <Object> nrm_object(vm->CreateArray());
|
||||
for (uint n = 0; n < pair.contact_count; ++n)
|
||||
if (vm->SetupFunctionCall("Vector"))
|
||||
{
|
||||
vm->PushArgument(pair.normal[n].x);
|
||||
vm->PushArgument(pair.normal[n].y);
|
||||
vm->PushArgument(pair.normal[n].z);
|
||||
Script::Variant rv;
|
||||
vm->DoFunctionCall(&rv);
|
||||
nrm_object->Append(rv);
|
||||
}
|
||||
|
||||
table_object->Set("n", nrm_object.c_ptr());
|
||||
|
||||
// Call each unit.
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnCollisionEx", ((MItemScriptUnit *)unit)->collisionex_callback))
|
||||
{
|
||||
unit->PushUserObjectFunctionCallArgument(with, typetag_Item);
|
||||
unit->PushFunctionCallArgument(table_object.c_ptr());
|
||||
unit->PushFunctionCallArgument(true);
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (((MItemScriptUnit *)unit)->collision_callback && unit->SetupFunctionCall("OnCollision", ((MItemScriptUnit *)unit)->collision_callback))
|
||||
{
|
||||
unit->PushUserObjectFunctionCallArgument((void *)with, typetag_Item);
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
|
||||
void MItemScriptEvent::OnItemEnter(MTrigger *trigger, MItem *item)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnItemEnter"))
|
||||
{
|
||||
unit->PushUserObjectFunctionCallArgument((void *)item, typetag_Item);
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
void MItemScriptEvent::OnItemExit(MTrigger *trigger, MItem *item)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnItemExit"))
|
||||
{
|
||||
unit->PushUserObjectFunctionCallArgument((void *)item, typetag_Item);
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
|
||||
void MItemScriptEvent::OnEnterTrigger(MItem *item, MTrigger *trigger)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnEnterTrigger"))
|
||||
{
|
||||
unit->PushUserObjectFunctionCallArgument((void *)((MItem *)trigger), typetag_Item);
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
void MItemScriptEvent::OnTrigger(MItem *item, MTrigger *trigger)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnTrigger"))
|
||||
{
|
||||
unit->PushUserObjectFunctionCallArgument((void *)((MItem *)trigger), typetag_Item);
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
void MItemScriptEvent::OnExitTrigger(MItem *item, MTrigger *trigger)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnExitTrigger"))
|
||||
{
|
||||
unit->PushUserObjectFunctionCallArgument((void *)((MItem *)trigger), typetag_Item);
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
|
||||
void MItemScriptEvent::OnRenderDone(MItem *item)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnRenderDone"))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void MItemScriptEvent::OnRenderUser(MItem *item)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (((MItemScriptUnit *)unit)->render_user_callback && unit->SetupFunctionCall("OnRenderUser", ((MItemScriptUnit *)unit)->render_user_callback))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void MItemScriptEvent::OnDelete(MItem *item)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, item->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnDelete"))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
137
include/engine/scene3d/mitem_nml.cpp
Normal file
137
include/engine/scene3d/mitem_nml.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mitem.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "core/engine.h"
|
||||
#include "script/scripted_object.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using GS::NML::Tag;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MItem::FromMetaTag(Tag &tag)
|
||||
{
|
||||
if (tag.name != "MItem")
|
||||
__ERR__(__LOG_E__ << "Could not parse managed item, incorrect root tag (" << tag.name << ").\n", false)
|
||||
|
||||
// Set item default state.
|
||||
initial_state_set = false;
|
||||
initial_matrix = Matrix4::IdentityMatrix();
|
||||
|
||||
mitem_flags.Set(0);
|
||||
|
||||
uid = (uint)~0;
|
||||
|
||||
NMLTagForeach(pt, tag)
|
||||
{
|
||||
if (pt->name == "Id") name = pt->GetString();
|
||||
else if (pt->name == "UId") uid = pt->GetUnsigned();
|
||||
|
||||
else if (pt->name == "Inactive") mitem_flags.Raise(Flag_IsActive, false);
|
||||
else if (pt->name == "Static") mitem_flags.Set(Flag_IsStatic);
|
||||
else if (pt->name == "Helper") mitem_flags.Set(Flag_IsHelper);
|
||||
|
||||
else if (pt->name == "Billboard") mitem_flags.Set(Flag_Billboard);
|
||||
else if (pt->name == "SolveOverlap") mitem_flags.Set(Flag_SolveOverlap);
|
||||
else if (pt->name == "Ghost") mitem_flags.Set(Flag_Ghost);
|
||||
else if (pt->name == "TriggerDetected") mitem_flags.Set(Flag_TriggerDetected);
|
||||
|
||||
else if (pt->name == "InitialMatrix")
|
||||
{
|
||||
if (initial_matrix.FromMetaTag(*pt))
|
||||
initial_state_set = true;
|
||||
}
|
||||
|
||||
else if (pt->name == "Priority")
|
||||
priority = pt->GetReal();
|
||||
|
||||
// Components.
|
||||
else if (pt->name == "MotionPlayer")
|
||||
automation_player->FromMetaTag(*pt);
|
||||
else if (pt->name == "PhysicItem")
|
||||
physic_item_desc.FromMetaTag(*pt);
|
||||
else if (pt->name == "ScriptedObject")
|
||||
{
|
||||
if (scripted_object)
|
||||
scripted_object->FromMetaTag(*pt);
|
||||
}
|
||||
|
||||
#if 1
|
||||
else if (pt->name == "Active");
|
||||
|
||||
else if (pt->name == "ScriptLogicFq");
|
||||
else if (pt->name == "TauItem");
|
||||
else if (pt->name == "GColItem");
|
||||
else if (pt->name == "ScriptUnit");
|
||||
|
||||
else if (pt->name == "Proxy");
|
||||
else if (pt->name == "ProxyScene");
|
||||
else if (pt->name == "ProxyGroup");
|
||||
else if (pt->name == "ProxyFlag");
|
||||
else if (pt->name == "ProxyRootParamTo");
|
||||
|
||||
else if (pt->name == "ToolSpecific")
|
||||
mitem_flags.Set(Flag_IsHelper);
|
||||
#endif
|
||||
|
||||
else
|
||||
__LOG_W__ << "Unknown tag '" << pt->name << "' in <MItem>.\n";
|
||||
}
|
||||
if (uid == ~0)
|
||||
__ERR__(__LOG_E__ << "Managed item '" << name << "' Uid is invalid.\n", false)
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Tag *MItem::AsMetaTag()
|
||||
{
|
||||
Tag *root = new Tag("MItem");
|
||||
if (!root)
|
||||
__ERR__(__LOG_E__ << "Could not create root tag to serialize.\n", NULL)
|
||||
|
||||
// Id.
|
||||
root->AddChild("Id", name);
|
||||
root->AddChild("UId", uid);
|
||||
|
||||
// Flags.
|
||||
if (!mitem_flags.IsSet(Flag_IsActive))
|
||||
root->AddChild("Inactive");
|
||||
if (mitem_flags.IsSet(Flag_Billboard))
|
||||
root->AddChild("Billboard");
|
||||
if (mitem_flags.IsSet(Flag_SolveOverlap))
|
||||
root->AddChild("SolveOverlap");
|
||||
if (mitem_flags.IsSet(Flag_Ghost))
|
||||
root->AddChild("Ghost");
|
||||
if (mitem_flags.IsSet(Flag_TriggerDetected))
|
||||
root->AddChild("TriggerDetected");
|
||||
|
||||
if (mitem_flags.IsSet(Flag_IsActive))
|
||||
root->AddChild("Active");
|
||||
if (mitem_flags.IsSet(Flag_IsHelper))
|
||||
root->AddChild("Helper");
|
||||
if (mitem_flags.IsSet(Flag_IsStatic))
|
||||
root->AddChild("Static");
|
||||
|
||||
// Transformation.
|
||||
if (initial_state_set)
|
||||
root->AddChild(initial_matrix.AsMetaTag("InitialMatrix"));
|
||||
|
||||
root->AddChild("Priority", priority);
|
||||
|
||||
// Components.
|
||||
root->AddChild(automation_player->AsMetaTag());
|
||||
root->AddChild(scripted_object->AsMetaTag());
|
||||
root->AddChild(physic_item_desc.AsMetaTag());
|
||||
|
||||
return root;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
46
include/engine/scene3d/mitem_script_unit.cpp
Normal file
46
include/engine/scene3d/mitem_script_unit.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mitem_script_unit.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MItemScriptUnit::Open()
|
||||
{
|
||||
if (!Unit::Open())
|
||||
return false;
|
||||
|
||||
update_callback = vm->GetObjectFromName("OnUpdate", self);
|
||||
trigger_callback = vm->GetObjectFromName("OnTrigger", self);
|
||||
activation_callback = vm->GetObjectFromName("OnActivate", self);
|
||||
physic_callback = vm->GetObjectFromName("OnPhysicStep", self);
|
||||
collision_callback = vm->GetObjectFromName("OnCollision", self);
|
||||
collisionex_callback = vm->GetObjectFromName("OnCollisionEx", self);
|
||||
render_user_callback = vm->GetObjectFromName("OnRenderUser", self);
|
||||
return true;
|
||||
}
|
||||
void MItemScriptUnit::Close()
|
||||
{
|
||||
update_callback = NULL;
|
||||
trigger_callback = NULL;
|
||||
activation_callback = NULL;
|
||||
physic_callback = NULL;
|
||||
physic_sleep_callback = NULL;
|
||||
collision_callback = NULL;
|
||||
collisionex_callback = NULL;
|
||||
render_user_callback = NULL;
|
||||
|
||||
Unit::Close();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MItemScriptUnit::MItemScriptUnit(IVM *vm) : Unit(vm) {}
|
||||
MItemScriptUnit::~MItemScriptUnit() { Close(); }
|
||||
//------------------------------------------------------------------------------
|
||||
26
include/engine/scene3d/mitem_scripted_object.cpp
Normal file
26
include/engine/scene3d/mitem_scripted_object.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mitem_scripted_object.h"
|
||||
#include "scene3d/mitem_script_unit.h"
|
||||
#include "scene3d/mitem.h"
|
||||
#include "script/script_engine_types.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Unit *MItemScriptedObject::NewUnit() const
|
||||
{
|
||||
Unit *unit = new MItemScriptUnit(vm);
|
||||
if (!unit)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate new scene script unit.", NULL);
|
||||
unit->SetInterfaceObject(item, typetag_Item);
|
||||
return unit;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
27
include/engine/scene3d/mlight.cpp
Normal file
27
include/engine/scene3d/mlight.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/scene_message.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MLight::isActive() const
|
||||
{
|
||||
if ((diffuse_intensity <= 0.01f) && (specular_intensity <= 0.01f))
|
||||
return false;
|
||||
return MItem::isActive();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
MLight::MLight()
|
||||
{
|
||||
item_type = Type_Light;
|
||||
mitem = (void *)((MItem *)this);
|
||||
priority = 1.f;
|
||||
}
|
||||
39
include/engine/scene3d/mlight_nml.cpp
Normal file
39
include/engine/scene3d/mlight_nml.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mlight.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::NML;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MLight::FromMetaTag(Tag &tag)
|
||||
{
|
||||
if (tag.name != "MLight")
|
||||
__ERR__(__LOG_E__ << "Could not parse managed light, incorrect root tag (" << tag.name << ").\n", false)
|
||||
|
||||
// Parse root tags.
|
||||
NMLTagForeach(pt, tag)
|
||||
{
|
||||
if (pt->name == "MItem") MItem::FromMetaTag(*pt);
|
||||
else if (pt->name == "Light") Light::FromMetaTag(*pt);
|
||||
else __LOG_W__ << "Unknown tag '" << pt->name << "' in <MLight>.\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Tag *MLight::AsMetaTag()
|
||||
{
|
||||
Tag *root = new Tag("MLight");
|
||||
if (!root)
|
||||
__ERR__(__LOG_E__ << "Could not create root tag to serialize.\n", NULL)
|
||||
|
||||
root->AddChild(MItem::AsMetaTag());
|
||||
root->AddChild(Light::AsMetaTag());
|
||||
return root;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
19
include/engine/scene3d/mobject.cpp
Normal file
19
include/engine/scene3d/mobject.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/scene_message.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MObject::MObject()
|
||||
{
|
||||
item_type = Type_Object;
|
||||
mitem = (void *)((MItem *)this);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
42
include/engine/scene3d/mobject_nml.cpp
Normal file
42
include/engine/scene3d/mobject_nml.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mobject.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::NML;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MObject::FromMetaTag(Tag &tag)
|
||||
{
|
||||
if (tag.name != "MObject")
|
||||
__ERR__(__LOG_E__ << "Could not parse managed object, incorrect root tag (" << tag.name << ").\n", false);
|
||||
|
||||
NMLTagForeach(pt, tag)
|
||||
{
|
||||
if (pt->name == "MItem")
|
||||
MItem::FromMetaTag(*pt);
|
||||
else if (pt->name == "Object")
|
||||
Object::FromMetaTag(*pt);
|
||||
else
|
||||
__LOG_W__ << "Unknown tag '" << pt->name << "' in <MObject>.\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Tag *MObject::AsMetaTag()
|
||||
{
|
||||
Tag *root = new Tag("MObject");
|
||||
if (!root)
|
||||
__ERR__(__LOG_E__ << "Could not create root tag to serialize.\n", NULL);
|
||||
|
||||
root->AddChild(MItem::AsMetaTag());
|
||||
root->AddChild(Object::AsMetaTag());
|
||||
|
||||
return root;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
17
include/engine/scene3d/mterrain.cpp
Normal file
17
include/engine/scene3d/mterrain.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mterrain.h"
|
||||
#include "scene3d/scene_message.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
MTerrain::MTerrain()
|
||||
{
|
||||
item_type = Type_Terrain;
|
||||
mitem = (void *)((MItem *)this);
|
||||
}
|
||||
41
include/engine/scene3d/mterrain_nml.cpp
Normal file
41
include/engine/scene3d/mterrain_nml.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mterrain.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::NML;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MTerrain::FromMetaTag(Tag &tag)
|
||||
{
|
||||
if (tag.name != "MTerrain")
|
||||
__ERR__(__LOG_E__ << "could not parse managed terrain, incorrect root tag (" << tag.name << ").\n", false)
|
||||
|
||||
NMLTagForeach(pt, tag)
|
||||
{
|
||||
if (pt->name == "MItem")
|
||||
MItem::FromMetaTag(*pt);
|
||||
else if (pt->name == "Terrain")
|
||||
Terrain::FromMetaTag(*pt);
|
||||
else
|
||||
__LOG_W__ << "Unknown tag '" << pt->name << "' in <MEmitter>.\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Tag *MTerrain::AsMetaTag()
|
||||
{
|
||||
Tag *root = new Tag("MTerrain");
|
||||
if (!root)
|
||||
__ERR__(__LOG_E__ << "Could not create root tag to serialize.\n", NULL)
|
||||
|
||||
root->AddChild(MItem::AsMetaTag());
|
||||
root->AddChild(Terrain::AsMetaTag());
|
||||
return root;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
40
include/engine/scene3d/mtrigger.cpp
Normal file
40
include/engine/scene3d/mtrigger.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mtrigger.h"
|
||||
#include "scene3d/mitem_event_interface.h"
|
||||
#include "scene3d/scene_message.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void MTriggerProxy::MarkItem(GS::Core::Item *item)
|
||||
{
|
||||
MItem *mitem = (MItem *)item->mitem;
|
||||
mitem->item_event->OnTrigger(mitem, mtrigger);
|
||||
|
||||
Trigger::MarkItem(item);
|
||||
|
||||
mitem->item_event->OnEnterTrigger(mitem, mtrigger);
|
||||
mtrigger->item_event->OnItemEnter(mtrigger, mitem);
|
||||
}
|
||||
void MTriggerProxy::DropItem(GS::Core::Item *item)
|
||||
{
|
||||
MItem *mitem = (MItem *)item->mitem;
|
||||
|
||||
mitem->item_event->OnExitTrigger(mitem, mtrigger);
|
||||
mtrigger->item_event->OnItemExit(mtrigger, mitem);
|
||||
|
||||
Trigger::DropItem(item);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
MTrigger::MTrigger() : MTriggerProxy(this)
|
||||
{
|
||||
item_type = Type_Trigger;
|
||||
mitem = (void *)((MItem *)this);
|
||||
}
|
||||
42
include/engine/scene3d/mtrigger_nml.cpp
Normal file
42
include/engine/scene3d/mtrigger_nml.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mtrigger.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::NML;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MTrigger::FromMetaTag(Tag &tag)
|
||||
{
|
||||
if ((tag.name != "Trigger") && (tag.name != "MTrigger"))
|
||||
__ERR__(__LOG_E__ << "Could not parse trigger, incorrect root tag (" << tag.name << ").\n", false)
|
||||
|
||||
// Parse root tags.
|
||||
NMLTagForeach(pt, tag)
|
||||
{
|
||||
if (pt->name == "MItem")
|
||||
MItem::FromMetaTag(*pt);
|
||||
else if (pt->name == "Item")
|
||||
((Item *)this)->FromMetaTag(*pt);
|
||||
|
||||
else __LOG_W__ << "Unknown tag '" << pt->name << "' in <Trigger>.\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Tag *MTrigger::AsMetaTag()
|
||||
{
|
||||
Tag *root = new Tag("MTrigger");
|
||||
if (!root)
|
||||
__ERR__(__LOG_E__ << "Could not create root tag to serialize.\n", NULL)
|
||||
|
||||
root->AddChild(MItem::AsMetaTag());
|
||||
root->AddChild(((Item *)this)->AsMetaTag());
|
||||
return root;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
494
include/engine/scene3d/scene.cpp
Normal file
494
include/engine/scene3d/scene.cpp
Normal file
@ -0,0 +1,494 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "scene3d/mtrigger.h"
|
||||
#include "scene3d/memitter.h"
|
||||
#include "scene3d/mterrain.h"
|
||||
#include "scene3d/instance.h"
|
||||
#include "scene3d/mconstraint.h"
|
||||
#include "scene3d/mitem_scripted_object.h"
|
||||
#include "scene3d/scene_event_script_interface.h"
|
||||
#include "scene3d/scene_renderer_environment_interface.h"
|
||||
#include "scene3d/scene_physic_world_interface.h"
|
||||
#include "scene3d/scene_scripted_object.h"
|
||||
#include "scene3d/scene_script_unit.h"
|
||||
#include "scene3d/mitem_event_script_interface.h"
|
||||
#include "physic/physic_constraint.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::SetClock(Core::Clock *c, bool set_ui)
|
||||
{
|
||||
clock = c ? c : new Core::Clock;
|
||||
if (set_ui)
|
||||
ui->SetClock(c);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::GetMinMax(MinMax &minmax) const
|
||||
{
|
||||
bool initial = true;
|
||||
|
||||
ArrayListForeachPtr(MItem *, i, active_list)
|
||||
{
|
||||
if (i->GetItemType() != Type_Object)
|
||||
continue;
|
||||
|
||||
MObject *object = (MObject *)i;
|
||||
if (object->render_data.IsNull() || object->render_data->geometry.IsNull())
|
||||
continue;
|
||||
|
||||
MinMax local_minmax = object->render_data->geometry->minmax;
|
||||
|
||||
if (initial)
|
||||
minmax = local_minmax;
|
||||
else minmax.Grow(local_minmax);
|
||||
initial = false;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Group *Scene::AddGroup(Group *g)
|
||||
{
|
||||
group_list.Add(g);
|
||||
return g;
|
||||
}
|
||||
bool Scene::RemoveGroup(Group *g)
|
||||
{
|
||||
return group_list.Remove(g);
|
||||
}
|
||||
Group *Scene::FindGroup(const char *name) const
|
||||
{
|
||||
ListForeachPtr(Group *, g, group_list)
|
||||
if (g->name == name)
|
||||
return g;
|
||||
return NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint Scene::GetItemGroupList(const MItem *item, SharedList <Group *> &list) const
|
||||
{
|
||||
uint count = 0;
|
||||
ListForeachPtr(Group *, g, group_list)
|
||||
if (g->IsMember(item))
|
||||
{
|
||||
count++;
|
||||
list.Add(g);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
void Scene::UnregisterItemFromGroups(MItem *item) const
|
||||
{
|
||||
ListForeachPtr(Group *, g, group_list)
|
||||
g->Remove(item);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Scene::ActivateItem(MItem *i, bool v)
|
||||
{
|
||||
if (v)
|
||||
{
|
||||
if (active_list.IndexOf(i) == -1)
|
||||
active_list.Add(i);
|
||||
}
|
||||
else
|
||||
active_list.Remove(i);
|
||||
|
||||
if (i->physic_item)
|
||||
i->physic_item->SetActive(v);
|
||||
|
||||
i->mitem_flags.Raise(MItem::Flag_IsActive, v);
|
||||
return true;
|
||||
}
|
||||
void Scene::ProcessItemActivationQueue()
|
||||
{
|
||||
ListForeachPtr(MItem *, i, activation_queue)
|
||||
ActivateItem(i, true);
|
||||
ListForeachPtr(MItem *, i, deactivation_queue)
|
||||
ActivateItem(i, false);
|
||||
|
||||
activation_queue.Clear();
|
||||
deactivation_queue.Clear();
|
||||
}
|
||||
void Scene::QueueItemActivation(MItem *item, bool activate, bool propagate)
|
||||
{
|
||||
if (item->mitem_flags.IsSet(MItem::Flag_IsActive) != activate)
|
||||
{
|
||||
// Queue item.
|
||||
if (activate)
|
||||
{
|
||||
if (!activation_queue.Find(item))
|
||||
activation_queue.Add(item);
|
||||
deactivation_queue.Remove(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!deactivation_queue.Find(item))
|
||||
deactivation_queue.Add(item);
|
||||
activation_queue.Remove(item);
|
||||
}
|
||||
|
||||
// Script callback.
|
||||
item->item_event->OnActivate(item, activate);
|
||||
item->mitem_flags.Raise(MItem::Flag_IsActive, activate);
|
||||
}
|
||||
|
||||
if (propagate)
|
||||
ListForeachPtr(Core::Item *, child, item->GetBaseItem()->GetChildren())
|
||||
QueueItemActivation(LocateManagedItem(child), activate, true);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Scene::Create(PhysicWorld *w)
|
||||
{
|
||||
Clear();
|
||||
|
||||
if ((physic_world = w) != NULL)
|
||||
{
|
||||
if (!physic_world->Create())
|
||||
return false;
|
||||
|
||||
// bullet_world->CreateDebugger(GetEngine().GetRenderer());
|
||||
physic_world->SetWorldInterface(iphysic_world);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MTrigger *Scene::RaytraceTriggerList(Vector4 &s, Vector4 &d, float l, Vector4 *i)
|
||||
{
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->GetItemType() == Type_Trigger)
|
||||
{
|
||||
MTrigger *t = (MTrigger *)item;
|
||||
|
||||
// Move ray to trigger space.
|
||||
Vector4 local_s, local_d;
|
||||
t->GetInverseMatrix().Apply(&local_s, &s);
|
||||
t->GetInverseMatrix().ApplyRotation(&local_d, &d);
|
||||
|
||||
// Test ray against bbox normalized space.
|
||||
MinMax mm;
|
||||
mm.SetFromPositionSize(Vector4(0, 0, 0), Vector4(1, 1, 1));
|
||||
|
||||
// Raytrace against minmax.
|
||||
Vector4 local_i;
|
||||
if (l == -1 ? mm.ClassifyLine(local_s, local_d, local_i) : mm.ClassifySegment(local_s, local_s + local_d * l, local_i))
|
||||
{
|
||||
if (i)
|
||||
*i = local_i * t->GetMatrix();
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::RecordAllItemLocation()
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
i->SetInitialTransformation();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MItem *Scene::ItemFromUid(uint uid) const
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (i->GetUid() == uid)
|
||||
return i;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
MItemType Scene::LocateItem(const Core::Item *item, MItem **entity) const
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (i->GetBaseItem() == item)
|
||||
{
|
||||
if (entity)
|
||||
*entity = i;
|
||||
return i->GetItemType();
|
||||
}
|
||||
|
||||
return Type_None;
|
||||
}
|
||||
MItem *Scene::LocateManagedItem(Core::Item *i)
|
||||
{
|
||||
return i ? (MItem *)i->mitem : NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static bool FindItemByName(const MItem *i, const char *name) { return i->name == name; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MItem *Scene::Item(const char *item_name, MItem *parent) const
|
||||
{
|
||||
StringList node;
|
||||
String(item_name).Split("/", node);
|
||||
|
||||
MItem *item = NULL;
|
||||
|
||||
if (parent)
|
||||
ListForeachPtr(Core::Item *, child, parent->GetBaseItem()->GetChildren())
|
||||
{
|
||||
MItem *child_item = LocateManagedItem(child);
|
||||
if (child_item && (child_item->name == node[0]))
|
||||
{
|
||||
item = child_item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
item = ListFindEx(item_list, FindItemByName, node[0]);
|
||||
|
||||
if (!item)
|
||||
__ERR__(__LOG_W__ << "No item named '" << item_name << "' in scene '" << name << "'.\n", NULL)
|
||||
|
||||
// Solve additional path.
|
||||
if (node.GetCount() > 1)
|
||||
for (uint n = 1; n < node.GetCount(); ++n)
|
||||
{
|
||||
if (item->GetItemType() != Type_Instance)
|
||||
__ERR__(__LOG_W__ << "Cannot solve sub-path '" << node[n] << "' on item '" << item->name << "'.\n", NULL)
|
||||
|
||||
Instance *instance = (Instance *)item;
|
||||
if (!instance->instance_group)
|
||||
return NULL;
|
||||
|
||||
item = instance->instance_group->Item(node[n]);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::SetItemStatic(MItem *item, bool v)
|
||||
{
|
||||
item->mitem_flags.Raise(MItem::Flag_IsStatic, v);
|
||||
|
||||
if (Core::Renderable *r = item->GetRenderable())
|
||||
{
|
||||
RemoveRenderable(r);
|
||||
AddRenderable(r, v);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::AddRenderable(Core::Renderable *r, bool is_static)
|
||||
{
|
||||
if (is_static)
|
||||
octree_culling_system.AddRenderable(r);
|
||||
else simple_culling_system.AddRenderable(r);
|
||||
}
|
||||
void Scene::RemoveRenderable(Core::Renderable *r)
|
||||
{
|
||||
simple_culling_system.DeleteRenderable(r);
|
||||
octree_culling_system.DeleteRenderable(r);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::SetupItemComponents(MItem *i)
|
||||
{
|
||||
// Create scripted object and event handler.
|
||||
i->scripted_object = new MItemScriptedObject(i, vm);
|
||||
if (vm)
|
||||
i->item_event = new MItemScriptEvent;
|
||||
|
||||
// Create physic item.
|
||||
if (physic_world && i->GetBaseItem())
|
||||
{
|
||||
i->physic_item = physic_world->NewItem();
|
||||
i->physic_item->SetUserPointer((void *)i);
|
||||
}
|
||||
}
|
||||
void Scene::AddItem(MItem *i, bool setup_components)
|
||||
{
|
||||
i->uid = current_item_uid++;
|
||||
|
||||
if (setup_components)
|
||||
SetupItemComponents(i);
|
||||
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_AddingItem, this, i);
|
||||
|
||||
// Add to all lists.
|
||||
item_list.Add(i);
|
||||
active_list.Add(i);
|
||||
|
||||
switch (i->GetItemType())
|
||||
{
|
||||
case Type_Light: light_list.Add((MLight *)i); break;
|
||||
case Type_Trigger: trigger_list.Add((MTrigger *)i); break;
|
||||
}
|
||||
|
||||
// Add to culling systems.
|
||||
if (Core::Renderable *r = i->GetRenderable())
|
||||
AddRenderable(r, i->mitem_flags.IsSet(MItem::Flag_IsStatic));
|
||||
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_ItemAdded, this, i);
|
||||
}
|
||||
bool Scene::RemoveItem(MItem *i)
|
||||
{
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_DeletingItem, this, (void *)i);
|
||||
|
||||
i->item_event->OnDelete(i);
|
||||
|
||||
if (vm.IsValid())
|
||||
vm->InvalidateNativeReference(i);
|
||||
|
||||
// Remove from groups.
|
||||
UnregisterItemFromGroups(i);
|
||||
|
||||
if (Core::Renderable *r = i->GetRenderable())
|
||||
{
|
||||
// Remove from culling systems.
|
||||
simple_culling_system.DeleteRenderable(r);
|
||||
octree_culling_system.DeleteRenderable(r);
|
||||
}
|
||||
|
||||
if (Core::Item *b = i->GetBaseItem())
|
||||
{
|
||||
// Unset if current camera.
|
||||
if (current_camera == b)
|
||||
current_camera = NULL;
|
||||
|
||||
// Remove from triggers & skins.
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
switch (item->GetItemType())
|
||||
{
|
||||
case Type_Trigger:
|
||||
((MTrigger *)item)->DropItem(b);
|
||||
break;
|
||||
|
||||
case Type_Object:
|
||||
{
|
||||
MObject *o = (MObject *)item;
|
||||
for (uint n = 0; n < o->GetBoneCount(); ++n)
|
||||
if (o->GetBone(n) == b)
|
||||
o->BindBone(n, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from physic world.
|
||||
i->physic_item = NULL;
|
||||
|
||||
switch (i->GetItemType())
|
||||
{
|
||||
case Type_Light: light_list.Remove((MLight *)i); break;
|
||||
case Type_Trigger: trigger_list.Remove((MTrigger *)i); break;
|
||||
}
|
||||
|
||||
active_list.Remove(i);
|
||||
removal_queue.Remove(i);
|
||||
activation_queue.Remove(i);
|
||||
deactivation_queue.Remove(i);
|
||||
|
||||
item_list.Remove(i); // keep last
|
||||
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_ItemDeleted, this, i);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::QueueItemRemoval(MItem *i)
|
||||
{ removal_queue.Add(i); }
|
||||
void Scene::ProcessItemRemovalQueue()
|
||||
{
|
||||
while (List <MItem *> ::Item *r = removal_queue.GetRoot())
|
||||
RemoveItem(r->Object());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::Clear(bool keep_script)
|
||||
{
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_Clearing, this, 0);
|
||||
|
||||
scene_event->OnDelete(this);
|
||||
|
||||
// Remove all items (immediate/non-queued).
|
||||
while (List <MItem *> ::Item *i = item_list.GetRoot())
|
||||
RemoveItem(i->Object());
|
||||
|
||||
// Drop UI.
|
||||
ui->Clear();
|
||||
|
||||
// Close scripts.
|
||||
if (!keep_script)
|
||||
scripted_object->RemoveAllUnit();
|
||||
|
||||
fog_color.Set();
|
||||
fog_near = 0;
|
||||
fog_far = 0;
|
||||
|
||||
current_item_uid = 0;
|
||||
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_Cleared, this, 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Scene::Scene(Script::IVM *script_vm) : profiler(*this)
|
||||
{
|
||||
vm = script_vm;
|
||||
current_camera = NULL;
|
||||
|
||||
current_item_uid = 0;
|
||||
|
||||
ambient_intensity = 1;
|
||||
target_exposure = 0.25;
|
||||
|
||||
time_of_day = 0.5;
|
||||
|
||||
fog_near = 0;
|
||||
fog_far = 0;
|
||||
fog_color.Set(0, 0, 0);
|
||||
|
||||
background_color.Set(0, 0, 0);
|
||||
ambient_color.Set(0, 0, 0);
|
||||
|
||||
clock = new Core::Clock;
|
||||
|
||||
scene_event = vm ? new SceneScriptEvent : new ISceneEvent;
|
||||
scripted_object = new SceneScriptedObject(vm, this);
|
||||
|
||||
irenderer_environment = new IEnvironment(this);
|
||||
iphysic_world = new IScenePhysicWorld(this);
|
||||
|
||||
ui = new S2D::Scene(vm);
|
||||
}
|
||||
Scene::~Scene()
|
||||
{
|
||||
SetAsScriptGlobalScene();
|
||||
Clear();
|
||||
|
||||
if (vm)
|
||||
vm->InvalidateNativeReference((void *)this);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
32
include/engine/scene3d/scene_ace_manager.cpp
Normal file
32
include/engine/scene3d/scene_ace_manager.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene_ace_manager.h"
|
||||
#include "core/ace.h"
|
||||
#include "memory/nauto_ptr.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using GS::ACE::Manager;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Manager *ACEManager::Get()
|
||||
{
|
||||
static AutoPtr <Manager> scene_manager;
|
||||
|
||||
if (!scene_manager)
|
||||
{
|
||||
scene_manager = new Manager;
|
||||
scene_manager->DefineACECommand("toposition", ACESN_toposition, 3);
|
||||
scene_manager->DefineACECommand("offsetposition", ACESN_offsetposition, 3);
|
||||
scene_manager->DefineACECommand("tooffset", ACESN_tooffset, 3);
|
||||
scene_manager->DefineACECommand("toscale", ACESN_toscale, 3);
|
||||
scene_manager->DefineACECommand("torotation", ACESN_torotation, 3);
|
||||
scene_manager->DefineACECommand("toalpha", ACESN_toalpha, 1);
|
||||
}
|
||||
return scene_manager;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
595
include/engine/scene3d/scene_debug.cpp
Normal file
595
include/engine/scene3d/scene_debug.cpp
Normal file
@ -0,0 +1,595 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <cmath>
|
||||
#include "scene3d/scene_debug.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "scene3d/mtrigger.h"
|
||||
#include "scene3d/mconstraint.h"
|
||||
#include "scene3d/instance.h"
|
||||
#include "scene3d/group.h"
|
||||
#include "physic/physic_constraint.h"
|
||||
#include "core/renderer_toolbox.h"
|
||||
#include "metafile/nml_object.h"
|
||||
#include "core/path_kdtree.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Units;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SceneDebugger::DrawItemBoundingVolume(Renderer &render, MItem *i, uint display_flags)
|
||||
{
|
||||
if (i && (i->GetItemType() == Type_Object))
|
||||
{
|
||||
if (display_flags & SceneDebugDisplayBoundingVolumes)
|
||||
{
|
||||
MObject *mobj = (MObject *)i;
|
||||
|
||||
MinMax pinmax;
|
||||
mobj->ComputeLocalMinMax(pinmax);
|
||||
OBB obb = OBB::FromMinMax(pinmax);
|
||||
obb.Transform(i->GetBaseItem()->GetMatrix());
|
||||
|
||||
Color color(1, 1, 0, 0.35f);
|
||||
RendererToolbox::DrawOBB(render, obb, &color, Material::Blend_Alpha);
|
||||
}
|
||||
|
||||
if (display_flags & SceneDebugDisplayOctreeVolumes)
|
||||
{
|
||||
/// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
void SceneDebugger::DrawItem(Renderer &render, MItem *pitem, uint display_flags, Color *draw_color)
|
||||
{
|
||||
if (!pitem)
|
||||
return;
|
||||
|
||||
Color item_color = draw_color ? *draw_color : Color(0.75f, 0.75f, 0.75f);
|
||||
Color bone_color = item_color;
|
||||
bone_color.w = 0.5f;
|
||||
|
||||
render.SetWorldMatrix(Matrix4::IdentityMatrix(), &Matrix4::IdentityMatrix());
|
||||
|
||||
if (pitem->GetBaseItem()->item_flags.IsSet(ItemFlagBoneHint) && pitem->GetBaseItem()->GetParent())
|
||||
{
|
||||
if (display_flags & SceneDebugDisplayBones)
|
||||
{
|
||||
Item *link = pitem->GetBaseItem()->GetParent();
|
||||
Vector4 w = pitem->GetBaseItem()->GetMatrix().GetRow(3) - link->GetMatrix().GetRow(3);
|
||||
float k = w.Len();
|
||||
Vector4 row = link->GetMatrix().GetRow(1);
|
||||
Matrix4 m = Matrix4::FromMatrix3(Matrix3::FromOrthonormalBasis(w, &row));
|
||||
m.SetRow(3, link->GetMatrix().GetRow(3));
|
||||
|
||||
Vector4 p[6] =
|
||||
{
|
||||
Vector4(0, 0, 0),
|
||||
Vector4(-k * 0.1f, k * 0.1f, k * 0.2f),
|
||||
Vector4( k * 0.1f, k * 0.1f, k * 0.2f),
|
||||
Vector4( k * 0.1f, -k * 0.1f, k * 0.2f),
|
||||
Vector4(-k * 0.1f, -k * 0.1f, k * 0.2f),
|
||||
Vector4( 0, 0, k)
|
||||
}, wp[6];
|
||||
|
||||
m.Apply(wp, p, 6);
|
||||
|
||||
RendererToolbox::Line3D(render, wp[0], wp[1], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
RendererToolbox::Line3D(render, wp[0], wp[2], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
RendererToolbox::Line3D(render, wp[0], wp[3], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
RendererToolbox::Line3D(render, wp[0], wp[4], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
|
||||
RendererToolbox::Line3D(render, wp[1], wp[5], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
RendererToolbox::Line3D(render, wp[2], wp[5], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
RendererToolbox::Line3D(render, wp[3], wp[5], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
RendererToolbox::Line3D(render, wp[4], wp[5], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
|
||||
RendererToolbox::Line3D(render, wp[1], wp[2], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
RendererToolbox::Line3D(render, wp[2], wp[3], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
RendererToolbox::Line3D(render, wp[3], wp[4], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
RendererToolbox::Line3D(render, wp[4], wp[1], &bone_color, Material::Blend_Alpha, Material::RenderWord(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
}
|
||||
}
|
||||
|
||||
// Display item motions.
|
||||
if (display_flags & SceneDebugDisplayMotions)
|
||||
if (pitem->automation_player && pitem->automation_player->GetMotionList().GetCount() && pitem->GetBaseItem())
|
||||
{
|
||||
bool found = true;
|
||||
Matrix4 m = pitem->GetBaseItem()->GetMatrix();
|
||||
|
||||
for (int index=0; index< pitem->automation_player->GetMotionList().GetCount(); ++index)
|
||||
{
|
||||
Motion* motion = pitem->automation_player->GetMotionFromIndex(index);
|
||||
|
||||
// if(found)
|
||||
{
|
||||
found = false;
|
||||
if(render.GetCamera())
|
||||
{
|
||||
Vector4 view_position = render.GetCamera()->GetPosition();
|
||||
Vector4 view_position_closest_point(0, 0, 0);
|
||||
float closest_t;
|
||||
motion->GetClosestPoint(view_position * pitem->GetBaseItem()->GetInverseMatrix(), view_position_closest_point, &closest_t);
|
||||
|
||||
Vector4 sample(0, 0, 0);
|
||||
motion->EvaluatePosition(Time::fromSec(closest_t+1), sample, Curve::Constant);
|
||||
|
||||
Color color(1,1,0);
|
||||
if(sample == view_position_closest_point)
|
||||
RendererToolbox::DrawCross(render, view_position_closest_point * m, Units::Mtr(1), &color);
|
||||
else
|
||||
{
|
||||
Vector4 OrthoVec = ((view_position_closest_point - sample).Normalized()).Cross(Vector4(0.0,1.0,0.0));
|
||||
|
||||
RendererToolbox::Line3D(render, sample * m, (view_position_closest_point-OrthoVec) * m, &color);
|
||||
RendererToolbox::Line3D(render, sample * m, (view_position_closest_point+OrthoVec) * m, &color);
|
||||
}
|
||||
|
||||
// if(motion->quadtree.IsValid())
|
||||
// motion->quadtree->draw_scene_debug(render, m);
|
||||
}
|
||||
}
|
||||
|
||||
MotionChannel *c[3];
|
||||
motion->GetTransformationChannels(c, NULL, NULL);
|
||||
|
||||
// check all 3 channel has the same number of point, because it's a vector
|
||||
// if not just continue to the next
|
||||
if( c[0]->GetPoints().GetCount() != c[1]->GetPoints().GetCount()||
|
||||
c[0]->GetPoints().GetCount() != c[2]->GetPoints().GetCount()||
|
||||
c[1]->GetPoints().GetCount() != c[2]->GetPoints().GetCount()||
|
||||
c[1]->GetPoints().GetCount() <= 1)
|
||||
continue;
|
||||
|
||||
ArrayList <CurvePoint *> ::Iterator iteratorX(c[0]->GetPoints());
|
||||
ArrayList <CurvePoint *> ::Iterator iteratorY(c[1]->GetPoints());
|
||||
ArrayList <CurvePoint *> ::Iterator iteratorZ(c[2]->GetPoints());
|
||||
|
||||
Vector4 vec;
|
||||
|
||||
Array<Vector4> v;
|
||||
v.Allocate(c[0]->GetPointCount()*2);
|
||||
Vector4 prev_vec;
|
||||
int count = 0;
|
||||
|
||||
for ( ; iteratorX.ObjectPtr(); ) // need to test iterator validity prior to access in case the motion has no point
|
||||
{
|
||||
vec.x = iteratorX.ObjectPtr()->v;
|
||||
vec.y = iteratorY.ObjectPtr()->v;
|
||||
vec.z = iteratorZ.ObjectPtr()->v;
|
||||
|
||||
if(count != 0)
|
||||
{
|
||||
v[(count++)-1] = prev_vec;
|
||||
v[(count++)-1] = vec*m;
|
||||
}
|
||||
else
|
||||
++count;
|
||||
|
||||
prev_vec = vec*m;
|
||||
|
||||
++iteratorX;
|
||||
++iteratorY;
|
||||
++iteratorZ;
|
||||
}
|
||||
|
||||
render.DrawLine(c[0]->GetPointCount()-1, v);
|
||||
|
||||
// draw cross for the first and the last point
|
||||
if ((c[0]->GetPoints().GetCount() > 1) && (c[1]->GetPoints().GetCount() > 1) && (c[2]->GetPoints().GetCount() > 1))
|
||||
{
|
||||
RendererToolbox::DrawCross(render, Vector4(c[0]->GetPoints()[0]->v, c[1]->GetPoints()[0]->v, c[2]->GetPoints()[0]->v)*m, Mtr(1), &Color::Green);
|
||||
RendererToolbox::DrawCross(render, Vector4(c[0]->GetPoints()[c[0]->GetPointCount()-1]->v, c[1]->GetPoints()[c[1]->GetPointCount()-1]->v, c[2]->GetPoints()[c[2]->GetPointCount()-1]->v)*m, Mtr(1.1), &Color::Red);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Triangle2d(Renderer &renderer, Vector4 sv[3], Color *c)
|
||||
{
|
||||
Vector4 wv[3];
|
||||
for (int n = 0; n < 3; ++n)
|
||||
wv[n] = renderer.GetCamera()->ScreenToWorld(renderer.GetViewport(), sv[n].x, sv[n].y);
|
||||
Color cl[3];
|
||||
for (int n = 0; n < 3; ++n)
|
||||
cl[n] = *c;
|
||||
RendererToolbox::Triangle3D(renderer, wv, cl, 0, 0, Material::Blend_Alpha, (Material::RenderWord)(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
}
|
||||
void Cartouche(Renderer &render, Vector4 sp, float width, float height, Color *color)
|
||||
{
|
||||
float offset_y = 0.6f;
|
||||
|
||||
Vector4 v[3];
|
||||
v[0].Set(sp.x - width * 0.5f, sp.y + (offset_y - 1) * height * 0.5f);
|
||||
v[1].Set(sp.x + width * 0.5f, sp.y + (offset_y - 1) * height * 0.5f);
|
||||
v[2].Set(sp.x + width * 0.5f, sp.y + (offset_y + 1) * height * 0.5f);
|
||||
Triangle2d(render, v, color);
|
||||
v[0].Set(sp.x + width * 0.5f, sp.y + (offset_y + 1) * height * 0.5f);
|
||||
v[1].Set(sp.x - width * 0.5f, sp.y + (offset_y + 1) * height * 0.5f);
|
||||
v[2].Set(sp.x - width * 0.5f, sp.y + (offset_y - 1) * height * 0.5f);
|
||||
Triangle2d(render, v, color);
|
||||
|
||||
// Draw border.
|
||||
for (int n = 0; n < 16; ++n)
|
||||
{
|
||||
v[2].Set(sp.x - width * 0.5f, sp.y);
|
||||
float a = n * Deg(180.f / 16.f);
|
||||
v[1].Set(sp.x - width * 0.5f - sin(a) * height * 0.25f, sp.y + (offset_y - cos(a)) * height * 0.5f);
|
||||
a = (n + 1) * Deg(180.f / 16.f);
|
||||
v[0].Set(sp.x - width * 0.5f - sin(a) * height * 0.25f, sp.y + (offset_y - cos(a)) * height * 0.5f);
|
||||
Triangle2d(render, v, color);
|
||||
}
|
||||
for (int n = 0; n < 16; ++n)
|
||||
{
|
||||
v[0].Set(sp.x + width * 0.5f, sp.y);
|
||||
float a = n * Deg(180.f / 16.f);
|
||||
v[1].Set(sp.x + width * 0.5f + sin(a) * height * 0.25f, sp.y + (offset_y - cos(a)) * height * 0.5f);
|
||||
a = (n + 1) * Deg(180.f / 16.f);
|
||||
v[2].Set(sp.x + width * 0.5f + sin(a) * height * 0.25f, sp.y + (offset_y - cos(a)) * height * 0.5f);
|
||||
Triangle2d(render, v, color);
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SceneDebugger::DrawItemName(Renderer &renderer, MItem *pitem)
|
||||
{
|
||||
String label;
|
||||
switch (pitem->GetItemType())
|
||||
{
|
||||
case Type_Object: label = "Object: "; break;
|
||||
case Type_Camera: label = "Camera: "; break;
|
||||
case Type_Light: label = "Light: "; break;
|
||||
case Type_Trigger: label = "Trigger: "; break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
label += pitem->name;
|
||||
|
||||
Vector4 sp;
|
||||
if (!renderer.GetCamera()->WorldToScreen(renderer.GetViewport(), pitem->GetBaseItem()->GetMatrix().GetRow(3), sp))
|
||||
return;
|
||||
sp.y += 0.05f;
|
||||
|
||||
// Draw a background.
|
||||
// fRect viewport = renderer.GetViewport();
|
||||
// float width = profiler_font.ComputeLineWidth(label.c_str());
|
||||
Color bg_color(0.5f, 0.5f, 0.5f, 0.7f);
|
||||
// Cartouche(render, sp, k * width * 0.5f, k * 0.075f, &bg_color);
|
||||
// render.Write(profiler_font, label, sp.x, sp.y, k, true, Renderer::AlignMiddle);
|
||||
}
|
||||
void SceneDebugger::DrawFigure(Renderer &render, Geometry *figure, const Matrix4 &matrix, Color &color)
|
||||
{
|
||||
if (!figure)
|
||||
return;
|
||||
|
||||
uint line_count = 0;
|
||||
for (uint n = 0; n < figure->pol.GetCount(); ++n)
|
||||
line_count += figure->pol[n].vtx_count;
|
||||
|
||||
Array <Vector4> p_line(line_count * 2);
|
||||
Array <Color> c_line(line_count * 2);
|
||||
Vector4 *p_p = p_line;
|
||||
Color *p_c = c_line;
|
||||
|
||||
if (p_p && p_c)
|
||||
{
|
||||
for (uint n = 0; n < figure->pol.GetCount(); ++n)
|
||||
for (int v = 0; v < figure->pol[n].vtx_count; ++v)
|
||||
{
|
||||
int w = v + 1;
|
||||
if (w == figure->pol[n].vtx_count)
|
||||
w = 0;
|
||||
|
||||
*p_p++ = figure->vtx[figure->pol[n].binding[v]];
|
||||
*p_p++ = figure->vtx[figure->pol[n].binding[w]];
|
||||
*p_c++ = color;
|
||||
*p_c++ = color;
|
||||
}
|
||||
|
||||
render.SetWorldMatrix(matrix.AsOrthonormalBase() * Matrix4::ScaleMatrix(Vector4(scale, scale, scale)));
|
||||
render.DrawLine(line_count, p_line, c_line, Material::Blend_Alpha, (Material::RenderWord)(Material::Render_NoZTest | Material::Render_NoZWrite));
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void DrawLineHatched(const Vector4 &a, const Vector4 &b, Vector4 *p_p, Color *p_c)
|
||||
{
|
||||
(*p_c++).Set(0.8f, 0.8f, 0.8f, 0.75f);
|
||||
(*p_c++).Set(0.8f, 0.8f, 0.8f, 0.75f);
|
||||
(*p_c++).Set(0.8f, 0.8f, 0.8f, 0.75f);
|
||||
(*p_c++).Set(0.8f, 0.8f, 0.8f, 0.75f);
|
||||
|
||||
Vector4 dt = b - a;
|
||||
*p_p++ = a; *p_p++ = a + dt * 0.2f;
|
||||
*p_p++ = b; *p_p++ = b - dt * 0.2f;
|
||||
}
|
||||
static void DrawOBBCorners(Renderer &render, const OBB &obb, const Matrix4 &m)
|
||||
{
|
||||
Vector4 vtx[8];
|
||||
vtx[0].Set(-0.5, 0.5, 0.5);
|
||||
vtx[1].Set( 0.5, 0.5, 0.5);
|
||||
vtx[2].Set( 0.5, -0.5, 0.5);
|
||||
vtx[3].Set(-0.5, -0.5, 0.5);
|
||||
vtx[4].Set(-0.5, 0.5, -0.5);
|
||||
vtx[5].Set( 0.5, 0.5, -0.5);
|
||||
vtx[6].Set( 0.5, -0.5, -0.5);
|
||||
vtx[7].Set(-0.5, -0.5, -0.5);
|
||||
|
||||
render.SetWorldMatrix(m * Matrix4::TransformationMatrix(obb.bb_position, obb.bb_rotation, obb.bb_scale));
|
||||
|
||||
Array <Vector4> p_line(12 * 2 * 2);
|
||||
Array <Color> c_line(12 * 2 * 2);
|
||||
Vector4 *p_p = p_line;
|
||||
Color *p_c = c_line;
|
||||
|
||||
if (p_p && p_c)
|
||||
{
|
||||
DrawLineHatched(vtx[0], vtx[1], p_p + 0, p_c + 0);
|
||||
DrawLineHatched(vtx[1], vtx[2], p_p + 4, p_c + 4);
|
||||
DrawLineHatched(vtx[2], vtx[3], p_p + 8, p_c + 8);
|
||||
DrawLineHatched(vtx[3], vtx[0], p_p + 12, p_c + 12);
|
||||
|
||||
DrawLineHatched(vtx[4], vtx[5], p_p + 16, p_c + 16);
|
||||
DrawLineHatched(vtx[5], vtx[6], p_p + 20, p_c + 20);
|
||||
DrawLineHatched(vtx[6], vtx[7], p_p + 24, p_c + 24);
|
||||
DrawLineHatched(vtx[7], vtx[4], p_p + 28, p_c + 28);
|
||||
|
||||
DrawLineHatched(vtx[0], vtx[4], p_p + 32, p_c + 32);
|
||||
DrawLineHatched(vtx[1], vtx[5], p_p + 36, p_c + 36);
|
||||
DrawLineHatched(vtx[2], vtx[6], p_p + 40, p_c + 40);
|
||||
DrawLineHatched(vtx[3], vtx[7], p_p + 44, p_c + 44);
|
||||
|
||||
render.DrawLine(12 * 2, p_line, c_line, Material::Blend_Alpha, Material::Render_NoZTest);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SceneDebugger::DrawScene(Renderer &render, const List <MItem *> *selection, const List <MItem *> *blacklist, uint display_flags)
|
||||
{
|
||||
Color middle_grey(0.72f, 0.72f, 0.72f),
|
||||
selected_orange(1, 0.65f, 0.16f),
|
||||
draw_color;
|
||||
|
||||
// Display light schematics.
|
||||
ListForeachPtr(MItem *, i, scene->GetItemList())
|
||||
{
|
||||
if (blacklist && blacklist->Find(i))
|
||||
continue;
|
||||
|
||||
switch (i->GetItemType())
|
||||
{
|
||||
case Type_Light:
|
||||
if (MLight *l = (MLight *)i)
|
||||
{
|
||||
DrawItem(render, l, display_flags);
|
||||
|
||||
if (selection && selection->Find(l))
|
||||
draw_color = selected_orange;
|
||||
else draw_color = middle_grey;
|
||||
|
||||
switch (l->model)
|
||||
{
|
||||
case Light::Model_Point:
|
||||
DrawFigure(render, pointlight.c_ptr(), l->GetMatrix(), draw_color);
|
||||
break;
|
||||
case Light::Model_Linear:
|
||||
DrawFigure(render, linearlight.c_ptr(), l->GetMatrix(), draw_color);
|
||||
break;
|
||||
case Light::Model_Spot:
|
||||
DrawFigure(render, spotlight.c_ptr(), l->GetMatrix(), draw_color);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Object:
|
||||
if (MObject *o = (MObject *)i)
|
||||
{
|
||||
DrawItemBoundingVolume(render, o, display_flags);
|
||||
|
||||
bool display_item = false;
|
||||
if (!selection || selection->Find(o))
|
||||
{
|
||||
display_item = true;
|
||||
draw_color = selected_orange;
|
||||
}
|
||||
else
|
||||
draw_color = middle_grey;
|
||||
|
||||
if (display_item || o->geometry.IsEmpty())
|
||||
DrawItem(render, o, display_flags, &draw_color);
|
||||
|
||||
// DrawFigure(render, dbg_object, obj->GetMatrix(), draw_color);
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Camera:
|
||||
if (MCamera *c = (MCamera *)i)
|
||||
{
|
||||
DrawItem(render, c, display_flags);
|
||||
|
||||
if (!selection || selection->Find(c))
|
||||
draw_color = selected_orange;
|
||||
else draw_color = middle_grey;
|
||||
|
||||
DrawFigure(render, camera.c_ptr(), c->GetMatrix(), draw_color);
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Trigger:
|
||||
if (MTrigger *t = (MTrigger *)i)
|
||||
{
|
||||
OBB obb(t->GetMatrix().GetRow(3), t->GetScale(), &t->GetRotationMatrix());
|
||||
Color color(1, 0, 0);
|
||||
if (t->isActive())
|
||||
color.Set(0, 1, 0);
|
||||
RendererToolbox::DrawOBB(render, obb, &color);
|
||||
|
||||
if (!selection || selection->Find(t))
|
||||
draw_color = selected_orange;
|
||||
else draw_color = middle_grey;
|
||||
|
||||
DrawFigure(render, trigger.c_ptr(), t->GetMatrix(), draw_color);
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Constraint:
|
||||
if (MConstraint *c = (MConstraint *)i)
|
||||
{
|
||||
if (c->desc.item_a.IsNull() || c->desc.item_b.IsNull())
|
||||
continue;
|
||||
|
||||
Vector4 wp_a = c->desc.pivot_a.GetRow(3) * c->desc.item_a->GetBaseItem()->GetMatrix(),
|
||||
wp_b = c->desc.pivot_b.GetRow(3) * c->desc.item_b->GetBaseItem()->GetMatrix();
|
||||
|
||||
RendererToolbox::DrawCross(render, wp_a, Cm(20.f));
|
||||
RendererToolbox::DrawCross(render, wp_b, Cm(20.f));
|
||||
RendererToolbox::Line3D(render, wp_a, wp_b);
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Instance:
|
||||
{
|
||||
// the items draw debug inside this instance, only if this instance is selected
|
||||
if (selection && selection->Find(i))
|
||||
{
|
||||
if (Instance *instance = (Instance *)i)
|
||||
{
|
||||
if (instance->instance_scene)
|
||||
{
|
||||
// call the draw debug for the object inside this scene instance
|
||||
ListForeachPtr(MItem *, i_instance, instance->instance_scene->GetItemList())
|
||||
{
|
||||
if (i_instance->GetItemType() == Type_Object)
|
||||
{
|
||||
if (MObject *o = (MObject *)i_instance)
|
||||
{
|
||||
DrawItemBoundingVolume(render, o, display_flags);
|
||||
|
||||
bool display_item = false;
|
||||
if (selection->Find(o))
|
||||
{
|
||||
display_item = true;
|
||||
draw_color = selected_orange;
|
||||
}
|
||||
else
|
||||
draw_color = middle_grey;
|
||||
|
||||
if (display_item || o->geometry.IsEmpty())
|
||||
DrawItem(render, o, display_flags, &draw_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// Display bounding.
|
||||
MinMax minmax;
|
||||
ListForeachPtr(MItem *, i, *selection)
|
||||
switch (i->GetItemType())
|
||||
{
|
||||
case Type_Object:
|
||||
{
|
||||
((MObject *)i)->ComputeLocalMinMax(minmax);
|
||||
OBB obb(minmax);
|
||||
DrawOBBCorners(render, obb, i->GetBaseItem()->GetMatrix());
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Instance:
|
||||
{
|
||||
Instance *instance = (Instance *)i;
|
||||
if (instance->instance_scene)
|
||||
{
|
||||
instance->instance_scene->GetMinMax(minmax);
|
||||
OBB obb(minmax);
|
||||
DrawOBBCorners(render, obb, i->GetBaseItem()->GetMatrix());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool SceneDebugger::LoadSchematicFigures(const char *dbg_pointlight, const char *dbg_spotlight, const char *dbg_linearlight, const char *dbg_camera, const char *dbg_object, const char *dbg_trigger)
|
||||
{
|
||||
pointlight = new Geometry;
|
||||
pointlight->name = dbg_pointlight;
|
||||
NML::LoadFromFile(*pointlight, dbg_pointlight);
|
||||
spotlight = new Geometry;
|
||||
spotlight->name = dbg_spotlight;
|
||||
NML::LoadFromFile(*spotlight, dbg_spotlight);
|
||||
linearlight = new Geometry;
|
||||
linearlight->name = dbg_linearlight;
|
||||
NML::LoadFromFile(*linearlight, dbg_linearlight);
|
||||
|
||||
camera = new Geometry;
|
||||
camera->name = dbg_camera;
|
||||
NML::LoadFromFile(*camera, dbg_camera);
|
||||
object = new Geometry;
|
||||
object->name = dbg_object;
|
||||
NML::LoadFromFile(*object, dbg_object);
|
||||
trigger = new Geometry;
|
||||
trigger->name = dbg_trigger;
|
||||
NML::LoadFromFile(*trigger, dbg_trigger);
|
||||
return true;
|
||||
}
|
||||
void SceneDebugger::SetScene(Scene *s)
|
||||
{ scene = s; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SceneDebugger::SceneDebugger()
|
||||
{
|
||||
scene = NULL;
|
||||
scale = 1.f;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::DumpContentToLog() const
|
||||
{
|
||||
__LOG_V__ << "Dumping scene content\n\n";
|
||||
|
||||
__LOG_V__ << "Item list (" << GetActiveList().GetCount() << " entries):\n";
|
||||
ArrayListForeachPtr(MItem *, i, GetActiveList())
|
||||
{
|
||||
MItem *pi = NULL;
|
||||
if (i->GetBaseItem())
|
||||
LocateItem(i->GetBaseItem()->GetParent(), &pi);
|
||||
__LOG_V__ << " - '" << i->name << "' (" << i->GetUid() << ")";
|
||||
|
||||
if (pi)
|
||||
__LOG_V__ << "(Linked to '" << pi->name << "' (" << pi->GetUid() << ")), (Active: " << (i->isActive() ? "yes" : "no") << ", Invisible: " << (i->GetBaseItem()->item_flags.IsSet(ItemFlagInvisible) ? "yes" : "no") << ")\n";
|
||||
else __LOG_V__ << "\n";
|
||||
}
|
||||
__LOG_V__ << "\n";
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
89
include/engine/scene3d/scene_event_script_interface.cpp
Normal file
89
include/engine/scene3d/scene_event_script_interface.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene_event_script_interface.h"
|
||||
#include "scene3d/scene_script_unit.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mitem_event_interface.h"
|
||||
#include "scene3d/mitem.h"
|
||||
#include "script/scripted_object.h"
|
||||
#include "script/script_variant.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SceneScriptEvent::OnSetup(Scene *scene)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, scene->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnSetup"))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void SceneScriptEvent::OnSetupDone(Scene *scene)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, scene->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnSetupDone"))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void SceneScriptEvent::OnReset(Scene *scene)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, scene->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnReset"))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void SceneScriptEvent::OnRender(Scene *scene)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, scene->scripted_object->GetUnitList())
|
||||
if (((SceneScriptUnit *)unit)->render_callback && unit->SetupFunctionCall("OnRender", ((SceneScriptUnit *)unit)->render_callback))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void SceneScriptEvent::OnRenderDone(Scene *scene)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, scene->scripted_object->GetUnitList())
|
||||
if (((SceneScriptUnit *)unit)->render_done_callback && unit->SetupFunctionCall("OnRenderDone", ((SceneScriptUnit *)unit)->render_done_callback))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void SceneScriptEvent::OnRenderUser(Scene *scene)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, scene->scripted_object->GetUnitList())
|
||||
if (((SceneScriptUnit *)unit)->render_user_callback && unit->SetupFunctionCall("OnRenderUser", ((SceneScriptUnit *)unit)->render_user_callback))
|
||||
unit->DoFunctionCall();
|
||||
|
||||
ListForeachPtr(MItem *, item, scene->GetItemList())
|
||||
item->item_event->OnRenderUser(item);
|
||||
}
|
||||
void SceneScriptEvent::OnRenderUIDone(Scene *scene)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, scene->scripted_object->GetUnitList())
|
||||
if (((SceneScriptUnit *)unit)->render_ui_done_callback && unit->SetupFunctionCall("OnRenderUIDone", ((SceneScriptUnit *)unit)->render_ui_done_callback))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
void SceneScriptEvent::OnPhysicStep(Scene *scene, bool step_taken)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, scene->scripted_object->GetUnitList())
|
||||
if (((SceneScriptUnit *)unit)->physic_step_callback && unit->SetupFunctionCall("OnPhysicStep", ((SceneScriptUnit *)unit)->physic_step_callback))
|
||||
{
|
||||
unit->PushFunctionCallArgument(step_taken);
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
void SceneScriptEvent::OnUpdate(Scene *scene)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, scene->scripted_object->GetUnitList())
|
||||
{
|
||||
SceneScriptUnit *scene_unit = (SceneScriptUnit *)unit;
|
||||
if (scene_unit->update_callback && scene_unit->SetupFunctionCall("OnUpdate", scene_unit->update_callback))
|
||||
scene_unit->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
void SceneScriptEvent::OnDelete(Scene *scene)
|
||||
{
|
||||
ListForeachPtr(Unit *, unit, scene->scripted_object->GetUnitList())
|
||||
if (unit->SetupFunctionCall("OnDelete"))
|
||||
unit->DoFunctionCall();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
25
include/engine/scene3d/scene_group.cpp
Normal file
25
include/engine/scene3d/scene_group.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/group.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::GroupMembersSetActive(Group *group, bool v)
|
||||
{
|
||||
ListForeachPtr(MItem *, i, group->GetItemList())
|
||||
QueueItemActivation(i, v);
|
||||
}
|
||||
void Scene::DeleteGroupAndMembers(Group *group)
|
||||
{
|
||||
ListForeachPtr(MItem *, i, group->GetItemList())
|
||||
QueueItemRemoval(i);
|
||||
group_list.Remove(group);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
32
include/engine/scene3d/scene_info.cpp
Normal file
32
include/engine/scene3d/scene_info.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene_info.h"
|
||||
#include "automation/automation_player.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::Core;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GS::S3D::DumpMemoryLayout()
|
||||
{
|
||||
__LOG__ << "Scene memory layout:\n\n";
|
||||
__LOG__ << " sizeof(S3D::Scene) = " << (uint)sizeof(Scene) << "\n";
|
||||
__LOG__ << " sizeof(S3D::MItem) = " << (uint)sizeof(MItem) << "\n";
|
||||
__LOG__ << " sizeof(Core::MotionChannel) = " << (uint)sizeof(MotionChannel) << "\n";
|
||||
__LOG__ << " sizeof(Core::Motion) = " << (uint)sizeof(Motion) << "\n";
|
||||
__LOG__ << " sizeof(Automation::Player) = " << (uint)sizeof(GS::Automation::Player) << "\n";
|
||||
__LOG__ << " sizeof(S3D::MObject) = " << (uint)sizeof(MObject) << "\n";
|
||||
__LOG__ << " sizeof(S3D::MCamera) = " << (uint)sizeof(MCamera) << "\n";
|
||||
__LOG__ << " sizeof(S3D::MLight) = " << (uint)sizeof(MLight) << "\n";
|
||||
__LOG__ << "\n";
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
14
include/engine/scene3d/scene_message.cpp
Normal file
14
include/engine/scene3d/scene_message.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene_message.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace S3D {
|
||||
Messaging::Broadcaster <SceneMessage, SceneListener, Scene *> g_scene_messenger;
|
||||
}
|
||||
}
|
||||
83
include/engine/scene3d/scene_mitem.cpp
Normal file
83
include/engine/scene3d/scene_mitem.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "scene3d/mtrigger.h"
|
||||
#include "scene3d/instance.h"
|
||||
#include "scene3d/mconstraint.h"
|
||||
#include "scene3d/group.h"
|
||||
#include "scene3d/mitem_event_interface.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "physic/physic_constraint.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint Scene::GetItemCountByType(MItemType type) const
|
||||
{
|
||||
uint count = 0;
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (i->GetItemType() == type)
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <class T> T *DuplicateItemType(MItem *item, T *clone, Scene *scene)
|
||||
{
|
||||
if (clone)
|
||||
{
|
||||
GS::AutoPtr <GS::NML::Tag> tag(((T *)item)->AsMetaTag());
|
||||
scene->SetupItemComponents(clone);
|
||||
clone->FromMetaTag(*tag);
|
||||
scene->AddItem(clone, false);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MItem *Scene::DuplicateItem(MItem *item)
|
||||
{
|
||||
MItem *new_instance = NULL;
|
||||
|
||||
switch (item->GetItemType())
|
||||
{
|
||||
case Type_Camera: new_instance = DuplicateItemType <MCamera> (item, new MCamera, this); break;
|
||||
case Type_Object: new_instance = DuplicateItemType <MObject> (item, new MObject, this); break;
|
||||
case Type_Light: new_instance = DuplicateItemType <MLight> (item, new MLight, this); break;
|
||||
case Type_Trigger: new_instance = DuplicateItemType <MTrigger> (item, new MTrigger, this); break;
|
||||
case Type_Constraint: new_instance = DuplicateItemType <MConstraint> (item, new MConstraint(physic_world->NewConstraint()), this); break;
|
||||
|
||||
case Type_Instance:
|
||||
{
|
||||
Instance *i = (Instance *)(new_instance = DuplicateItemType <Instance> (item, new Instance, this));
|
||||
|
||||
if (((Instance *)item)->instance_group)
|
||||
i->Instantiate(this);
|
||||
|
||||
if (i->instance_group)
|
||||
i->instance_group->Setup();
|
||||
|
||||
i->Setup(physic_world);
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Duplicate hierarchy.
|
||||
if (new_instance)
|
||||
new_instance->GetBaseItem()->SetParent(item->GetBaseItem()->GetParent());
|
||||
|
||||
return new_instance;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
680
include/engine/scene3d/scene_nml.cpp
Normal file
680
include/engine/scene3d/scene_nml.cpp
Normal file
@ -0,0 +1,680 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "scene3d/mtrigger.h"
|
||||
#include "scene3d/instance.h"
|
||||
#include "scene3d/memitter.h"
|
||||
#include "scene3d/mterrain.h"
|
||||
#include "scene3d/mconstraint.h"
|
||||
#include "scene3d/group.h"
|
||||
#include "physic/physic_constraint.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "ui/ui.h"
|
||||
#include "script/scripted_object.h"
|
||||
#include "script/script_unit.h"
|
||||
#include "container/nmap.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace S3D;
|
||||
using NML::Tag;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static MItem *GetMappedItemFromTag(Scene &scene, Tag *pt, const char *tag, Map <uint, uint> &uid_map, MItemType type = Type_None)
|
||||
{
|
||||
Tag *muid = pt->GetTypedTag(tag, Variant::VariantInteger);
|
||||
if (!muid)
|
||||
__ERR__(__LOG_W__ << "Invalid UID tag.\n", NULL)
|
||||
|
||||
uint uid = muid->GetUnsigned();
|
||||
if (!uid_map.HasKey(uid))
|
||||
__ERR__(__LOG_W__ << "Invalid item UID.\n", NULL)
|
||||
|
||||
MItem *mitem = scene.ItemFromUid(uid_map[uid]);
|
||||
if (mitem && (type != Type_None) && (mitem->GetItemType() != type))
|
||||
__ERR__(__LOG_V__ << "Item type filtered out.\n", NULL)
|
||||
|
||||
return mitem;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static bool ShouldLoadItem(ToolMode mode, Tag *pt, uint flag, int load_level)
|
||||
{
|
||||
if (pt->GetTag("MItem:ToolSpecific;") || pt->GetTag("MItem:Helper;"))
|
||||
{
|
||||
if (!(flag & SceneIOHelper))
|
||||
return false;
|
||||
|
||||
// Do not load tool specific items in no tool or project preview modes.
|
||||
if ((mode == NoTool) || (mode == ToolProjectPreview))
|
||||
return false;
|
||||
|
||||
// Do not load tool specific items in no tool mode above the first load level.
|
||||
if (load_level > 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <class T> static T *LoadItemDerived(Scene *scene, T *i, Map <uint, uint> &uid_map, Tag *t, uint type_flag, const uint load_flag, int load_level, ToolMode tool_mode)
|
||||
{
|
||||
if (!(load_flag & type_flag) || !ShouldLoadItem(tool_mode, t, load_flag, load_level))
|
||||
{
|
||||
delete i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scene->SetupItemComponents(i);
|
||||
|
||||
if (i->FromMetaTag(*t))
|
||||
{
|
||||
uint olduid = i->GetUid(); // uid from source scene
|
||||
scene->AddItem(i, false); // add to live scene
|
||||
uid_map.Add(olduid, i->GetUid()); // store map from source to live scene
|
||||
}
|
||||
return i;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Scene::FromMetaTagStoreGroup(const Tag &tag, Group **group, uint load_flag, ToolMode tool_mode, int load_level)
|
||||
{
|
||||
if (tag.name != "Scene")
|
||||
__ERR__(__LOG_E__ << "Could not parse scene, incorrect root tag (" << tag.name << ").\n", false);
|
||||
|
||||
Benchmark bench(true);
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_Loading, this, 0);
|
||||
|
||||
ui->ResetCommandList();
|
||||
|
||||
// Create scene group.
|
||||
if (group && !group[0])
|
||||
{
|
||||
group[0] = new Group;
|
||||
group[0]->name = "SceneGroup";
|
||||
group_list.Add(group[0]);
|
||||
}
|
||||
|
||||
// Read items and setup uid remap array.
|
||||
Map <uint, uint> uid_map;
|
||||
|
||||
if (Tag *itag = tag.GetTag("Items"))
|
||||
{
|
||||
// Item count in scene.
|
||||
uint item_to_load = 0;
|
||||
NMLTagForeach(pt, *itag)
|
||||
if (Tag *item_tag = pt->GetTag("MItem;"))
|
||||
item_to_load++;
|
||||
|
||||
NMLTagForeach(pt, *itag)
|
||||
{
|
||||
MItem *citem = NULL;
|
||||
|
||||
if (pt->name == "MCamera")
|
||||
citem = LoadItemDerived(this, new MCamera, uid_map, pt, SceneIOCamera, load_flag, load_level, tool_mode);
|
||||
else if (pt->name == "MObject")
|
||||
citem = LoadItemDerived(this, new MObject, uid_map, pt, SceneIOObject, load_flag, load_level, tool_mode);
|
||||
else if (pt->name == "MLight")
|
||||
citem = LoadItemDerived(this, new MLight, uid_map, pt, SceneIOLight, load_flag, load_level, tool_mode);
|
||||
else if ((pt->name == "MTrigger") || (pt->name == "Trigger")) // Legacy
|
||||
citem = LoadItemDerived(this, new MTrigger, uid_map, pt, SceneIOTrigger, load_flag, load_level, tool_mode);
|
||||
else if (pt->name == "Instance")
|
||||
citem = LoadItemDerived(this, new Instance, uid_map, pt, SceneIOInstance, load_flag, load_level, tool_mode);
|
||||
else if (pt->name == "MEmitter")
|
||||
citem = LoadItemDerived(this, new MEmitter, uid_map, pt, SceneIOEmitter, load_flag, load_level, tool_mode);
|
||||
else if (pt->name == "MTerrain")
|
||||
citem = LoadItemDerived(this, new MTerrain, uid_map, pt, SceneIOTerrain, load_flag, load_level, tool_mode);
|
||||
else if (pt->name == "MConstraint")
|
||||
citem = LoadItemDerived(this, new MConstraint(physic_world ? physic_world->NewConstraint() : NULL), uid_map, pt, SceneIOConstraint, load_flag, load_level, tool_mode);
|
||||
else
|
||||
__LOG_W__ << "Unexpected <" << pt->name << "> sub-tag in <Items>.\n";
|
||||
|
||||
if (citem)
|
||||
{
|
||||
// Add item to the scene group.
|
||||
if (group && group[0])
|
||||
group[0]->Add(citem);
|
||||
|
||||
// Remove from active list if inactive.
|
||||
if (!citem->isActive())
|
||||
active_list.Remove(citem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Solve links.
|
||||
if (Tag *ltag = tag.GetTag("Links"))
|
||||
{
|
||||
NMLTagForeach(pt, *ltag)
|
||||
{
|
||||
if (pt->name == "Link")
|
||||
{
|
||||
int item = -1, link = -1;
|
||||
|
||||
NMLTagForeach(lt, *pt)
|
||||
{
|
||||
if (lt->name == "Item") item = lt->GetInteger();
|
||||
else if (lt->name == "Link") link = lt->GetInteger();
|
||||
}
|
||||
|
||||
MItem *sitem = NULL, *litem = NULL;
|
||||
|
||||
if ((item == -1) || (link == -1))
|
||||
__LOG_W__ << "Incomplete link tag.\n";
|
||||
else
|
||||
{
|
||||
// Some items might have been masked out from import.
|
||||
if (uid_map.HasKey(item) && uid_map.HasKey(link))
|
||||
{
|
||||
sitem = ItemFromUid(uid_map[item]);
|
||||
litem = ItemFromUid(uid_map[link]);
|
||||
if (sitem && litem)
|
||||
sitem->GetBaseItem()->SetParent(litem->GetBaseItem());
|
||||
|
||||
// __LOG__ << "Solving link: " << item << "(" << (sitem ? "OK" : "Failed") << ")->" << link << "(" << (litem ? "OK" : "Failed") << ").\n";
|
||||
}
|
||||
// else __LOG_W__ << "Link item masked out during import.\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
__LOG_W__ << "Unexpected <" << pt->name << "> sub-tag in <Links>.\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Solve constraints.
|
||||
if (Tag *ctag = tag.GetTag("Constraints"))
|
||||
{
|
||||
NMLTagForeach(pt, *ctag)
|
||||
if (pt->name == "Constraint")
|
||||
{
|
||||
MItem *mitem = GetMappedItemFromTag(*this, pt, "Uid;", uid_map, Type_Constraint);
|
||||
if (!mitem)
|
||||
continue;
|
||||
|
||||
// Get constraint.
|
||||
if (MConstraint *constraint = (MConstraint *)mitem)
|
||||
{
|
||||
MItem *mitem_a = GetMappedItemFromTag(*this, pt, "UidA;", uid_map),
|
||||
*mitem_b = GetMappedItemFromTag(*this, pt, "UidB;", uid_map);
|
||||
|
||||
constraint->desc.item_a = mitem_a;
|
||||
constraint->desc.item_b = mitem_b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Solve skins.
|
||||
if (Tag *btag = tag.GetTag("Skins"))
|
||||
{
|
||||
NMLTagForeach(pt, *btag)
|
||||
if (pt->name == "Skin")
|
||||
if (MItem *mitem = GetMappedItemFromTag(*this, pt, "UId;", uid_map, Type_Object))
|
||||
{
|
||||
// We can now safely cast to the managed and core objects.
|
||||
MObject *mobj = (MObject *)mitem;
|
||||
Core::Object *obj = (Core::Object *)mobj;
|
||||
|
||||
uint bone_count = 0;
|
||||
NMLTagForeach(st, *pt)
|
||||
if (st->name == "Bone")
|
||||
bone_count++;
|
||||
|
||||
if (!obj->AllocateSkin(bone_count))
|
||||
continue;
|
||||
|
||||
// Process skin binding.
|
||||
NMLTagForeach(st, *pt)
|
||||
if (st->name == "Bone")
|
||||
{
|
||||
// Grab mandatory bone tags.
|
||||
Tag *itag = st->GetTypedTag("Index", Variant::VariantInteger),
|
||||
*utag = st->GetTypedTag("UId", Variant::VariantInteger);
|
||||
|
||||
if (!itag || !utag)
|
||||
{ __LOG_E__ << "Invalid bone information, incomplete bone tag.\n"; continue; }
|
||||
|
||||
int index = itag->GetInteger();
|
||||
if ((index < 0) || (index >= (int)obj->GetBoneCount()))
|
||||
{ __LOG_E__ << "Invalid bone information, bone index out of bound.\n"; continue; }
|
||||
|
||||
// Locate bone item.
|
||||
uint uid = utag->GetUnsigned();
|
||||
if (!uid_map.HasKey(uid))
|
||||
{ __LOG_E__ << "Invalid bone information, item uid out of bound.\n"; continue; }
|
||||
|
||||
MItem *bone = ItemFromUid(uid_map[uid]);
|
||||
if (!bone)
|
||||
{ __LOG_E__ << "Invalid bone information, item not found.\n"; continue; }
|
||||
|
||||
obj->BindBone(index, bone->GetBaseItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read groups.
|
||||
if (load_flag & SceneIOGroup)
|
||||
if (Tag *gstag = tag.GetTag("Groups"))
|
||||
{
|
||||
String _item("Item");
|
||||
|
||||
NMLTagForeach(gtag, *gstag)
|
||||
{
|
||||
if (gtag->name == "Group")
|
||||
{
|
||||
if (Tag *tid = gtag->GetTag("Id"))
|
||||
{
|
||||
if (Group *new_group = new Group)
|
||||
{
|
||||
new_group->name = tid->GetString();
|
||||
group_list.Add(new_group);
|
||||
|
||||
NMLTagForeach(mtag, *gtag)
|
||||
{
|
||||
if (mtag->name == _item)
|
||||
{
|
||||
int uid = mtag->GetInteger();
|
||||
if (uid_map.HasKey(uid))
|
||||
new_group->Add(ItemFromUid(uid_map[uid]));
|
||||
// else
|
||||
// __LOG_W__ << "Group member masked out during import.\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Add as sub-group.
|
||||
if (group)
|
||||
group[0]->Add(new_group);
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate group '" << tid->GetString() << "'.\n";
|
||||
}
|
||||
else
|
||||
__LOG_W__ << "Could not read group, no identifier found.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Script unit.
|
||||
if (load_flag & SceneIOScript)
|
||||
{
|
||||
if (Tag *stag = tag.GetTag("ScriptedObject"))
|
||||
scripted_object->FromMetaTag(*stag);
|
||||
|
||||
#if 1 // Compatibility
|
||||
else
|
||||
if (Tag *stag = tag.GetTag("ScriptUnit"))
|
||||
if (Script::Unit *unit = scripted_object->AddUnit(scripted_object->NewUnit()))
|
||||
unit->FromMetaTag(*stag);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Motion sets.
|
||||
if (load_flag & SceneIOMotion)
|
||||
if (Tag *ctag = tag.GetTag("SceneMotionContainer"))
|
||||
{
|
||||
if (group)
|
||||
{
|
||||
if (*group)
|
||||
(*group)->motion.FromMetaTag(*ctag, &uid_map);
|
||||
}
|
||||
else
|
||||
motion.FromMetaTag(*ctag, &uid_map);
|
||||
}
|
||||
|
||||
// Scene properties.
|
||||
static String _bgc("BackgroundColor"), _abc("AmbientColor"), _abi("AmbientIntensity"), _tge("TargetExposure"),
|
||||
_feb("FogEnable"), _fgn("FogNear"), _fgf("FogFar"), _fgc("FogColor"), _rad("Radiance"), _ird("Irradiance");
|
||||
|
||||
if (!group || (load_flag & SceneIOGlobals))
|
||||
if (Tag *gtag = tag.GetTag("Globals"))
|
||||
NMLTagForeach(t, *gtag)
|
||||
{
|
||||
if (t->name == _bgc)
|
||||
background_color.FromMetaTag(*t);
|
||||
else if (t->name == _abc)
|
||||
ambient_color.FromMetaTag(*t);
|
||||
else if (t->name == _abi)
|
||||
ambient_intensity = t->GetReal();
|
||||
else if (t->name == _rad)
|
||||
radiance_probe = t->GetString();
|
||||
else if (t->name == _ird)
|
||||
irradiance_probe = t->GetString();
|
||||
else if (t->name == _tge)
|
||||
target_exposure = t->GetReal();
|
||||
|
||||
else if (t->name == _fgn)
|
||||
fog_near = t->GetReal();
|
||||
else if (t->name == _fgf)
|
||||
fog_far = t->GetReal();
|
||||
else if (t->name == _fgc)
|
||||
fog_color.FromMetaTag(*t);
|
||||
|
||||
else if (t->name == "SkyLayer0")
|
||||
skybox_layer[0] = t->GetString();
|
||||
else if (t->name == "SkyLayer1")
|
||||
skybox_layer[1] = t->GetString();
|
||||
else if (t->name == "SkyShader")
|
||||
skybox_shader = t->GetString();
|
||||
|
||||
else if (t->name == "TimeOfDay")
|
||||
time_of_day = t->GetReal();
|
||||
}
|
||||
|
||||
// Physic system.
|
||||
if ((load_flag & SceneIOPhysic) && physic_world)
|
||||
{
|
||||
Tag *ptag = tag.GetTag("Physics;");
|
||||
|
||||
if (!ptag)
|
||||
ptag = tag.GetTag("Tau;"); // Look for a legacy tag.
|
||||
|
||||
if (ptag)
|
||||
{
|
||||
NMLTagForeach(t, *ptag)
|
||||
if (t->name == "Frequency")
|
||||
physic_world->SetTimestep(1.f / t->GetReal());
|
||||
}
|
||||
}
|
||||
|
||||
// Group stats.
|
||||
if (group && group[0])
|
||||
__LOG__ << "Group '" << group[0]->name << "': " << group[0]->GetItemList().GetCount() << " item(s).\n";
|
||||
|
||||
// Load current camera.
|
||||
if ((load_flag & SceneIOSettings) && (load_flag & SceneIOCamera))
|
||||
if (Tag *cctag = tag.GetTag("CurrentCamera"))
|
||||
{
|
||||
MItem *i = Item(cctag->GetString());
|
||||
if (i && (i->GetItemType() == Type_Camera))
|
||||
current_camera = (Camera *)i->GetBaseItem();
|
||||
}
|
||||
|
||||
// Query the editor tag if no camera found.
|
||||
if (!current_camera && (tool_mode != ToolEdit))
|
||||
if (MCamera *camera = new MCamera)
|
||||
{
|
||||
camera->name = "Default";
|
||||
AddItem(camera, true);
|
||||
current_camera = camera;
|
||||
|
||||
if (Tag *pt = tag.GetTag("ViewMatrix;"))
|
||||
{
|
||||
Matrix4 m;
|
||||
if (m.FromMetaTag(*pt))
|
||||
camera->SetMatrix(m);
|
||||
}
|
||||
}
|
||||
|
||||
bench.Stop();
|
||||
__LOG__ << "Done loading scene in " << bench.GetMs() << "ms.\n";
|
||||
|
||||
g_scene_messenger.BroadcastMessage(SceneMsg_Loaded, this, 0);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Scene::FromMetaFileStoreGroup(const char *path, Group **group, uint flag, ToolMode tool_mode, int load_level)
|
||||
{
|
||||
NML::File file;
|
||||
if (!NML::Parser::Load(path, file))
|
||||
return false;
|
||||
|
||||
if (Tag *scene_tag = file.GetTag("Scene"))
|
||||
{
|
||||
if (FromMetaTagStoreGroup(*scene_tag, group, flag, tool_mode, load_level))
|
||||
name = path;
|
||||
}
|
||||
else
|
||||
__ERR__(__LOG_E__ << "No <Scene> tag in '" << path << "'.\n", false)
|
||||
|
||||
if (group && group[0])
|
||||
group[0]->name = path;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Scene::IsItemToBeSaved(MItem *i, const Group *group, uint flag) const
|
||||
{
|
||||
if (!i)
|
||||
return false;
|
||||
|
||||
// Filter out irrelevant items.
|
||||
if (group && !group->IsMember(i))
|
||||
return false;
|
||||
|
||||
switch (i->GetItemType())
|
||||
{
|
||||
case Type_Camera: if (!(flag & SceneIOCamera)) return false; break;
|
||||
case Type_Object: if (!(flag & SceneIOObject)) return false; break;
|
||||
case Type_Light: if (!(flag & SceneIOLight)) return false; break;
|
||||
case Type_Trigger: if (!(flag & SceneIOTrigger)) return false; break;
|
||||
case Type_Instance: if (!(flag & SceneIOInstance)) return false; break;
|
||||
case Type_Emitter: if (!(flag & SceneIOEmitter)) return false; break;
|
||||
case Type_Terrain: if (!(flag & SceneIOTerrain)) return false; break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Tag *Scene::LinkInfoAsMetaTag(MItem *i, const Group *group, uint flag) const
|
||||
{
|
||||
if (!IsItemToBeSaved(i, group, flag))
|
||||
return NULL;
|
||||
|
||||
// Grab link managed item.
|
||||
Core::Item *link = i->GetBaseItem() ? i->GetBaseItem()->GetParent() : NULL;
|
||||
MItem *mlink;
|
||||
if (!link || ((mlink = LocateManagedItem(link)) == NULL))
|
||||
return NULL;
|
||||
|
||||
if (!IsItemToBeSaved(mlink, group, flag))
|
||||
return NULL;
|
||||
|
||||
// Save link information.
|
||||
if (Tag *tag = new Tag("Link"))
|
||||
{
|
||||
tag->AddChild("Item", i->GetUid());
|
||||
tag->AddChild("Link", mlink->GetUid());
|
||||
return tag;
|
||||
}
|
||||
__ERR__(__LOG_E__ << "Failed to allocate link tag.\n", NULL)
|
||||
}
|
||||
Tag *Scene::SkinInfoAsMetaTag(MObject *mobj, const Group *group, uint flag) const
|
||||
{
|
||||
if (group && (!group->IsMember(mobj)))
|
||||
return NULL;
|
||||
|
||||
// Go to the low-level core object.
|
||||
Core::Object *obj = (Core::Object *)mobj;
|
||||
if (!obj->HasSkin())
|
||||
return NULL;
|
||||
|
||||
Tag *skin_tag = new Tag("Skin");
|
||||
if (!skin_tag)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate skin tag.\n", NULL);
|
||||
skin_tag->AddChild("UId", mobj->GetUid());
|
||||
|
||||
for (int n = 0; n < (int)obj->GetBoneCount(); ++n)
|
||||
{
|
||||
MItem *bone = Scene::LocateManagedItem(obj->GetBone(n));
|
||||
if (!bone || (group && (!group->IsMember(bone))))
|
||||
continue;
|
||||
|
||||
// Export bone informations.
|
||||
if (Tag *bone_tag = skin_tag->AddChild("Bone"))
|
||||
{
|
||||
bone_tag->AddChild("Index", n);
|
||||
bone_tag->AddChild("UId", bone->GetUid());
|
||||
Matrix4 m;
|
||||
if (obj->GetBindMatrix(n, m))
|
||||
bone_tag->AddChild(m.AsMetaTag("BindMatrix"));
|
||||
else
|
||||
__LOG_E__ << "Failed to serialize bone " << n << " bind matrix for object '" << mobj->name << "'.\n";
|
||||
}
|
||||
else __LOG_E__ << "Failed to allocate bone tag.\n";
|
||||
}
|
||||
return skin_tag;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Tag *Scene::AsMetaTag(const Group *group, uint save_flag, ToolMode tool_mode) const
|
||||
{
|
||||
Tag *root = new Tag("Scene");
|
||||
if (!root)
|
||||
__ERR__(__LOG_E__ << "Could not create scene root tag to serialize.\n", NULL);
|
||||
|
||||
// Write script object.
|
||||
if (scripted_object.IsValid() && !group)
|
||||
root->AddChild(scripted_object->AsMetaTag());
|
||||
|
||||
// Write motion sets.
|
||||
if (save_flag & SceneIOMotion)
|
||||
root->AddChild(motion.AsMetaTag());
|
||||
|
||||
// Write managed items.
|
||||
if (Tag *itag = root->AddChild("Items"))
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
{
|
||||
if (group && !group->IsMember(i))
|
||||
continue;
|
||||
|
||||
switch (i->GetItemType())
|
||||
{
|
||||
case Type_Camera: if (!(save_flag & SceneIOCamera)) continue; break;
|
||||
case Type_Object: if (!(save_flag & SceneIOObject)) continue; break;
|
||||
case Type_Light: if (!(save_flag & SceneIOLight)) continue; break;
|
||||
case Type_Trigger: if (!(save_flag & SceneIOTrigger)) continue; break;
|
||||
case Type_Instance: if (!(save_flag & SceneIOInstance)) continue; break;
|
||||
case Type_Emitter: if (!(save_flag & SceneIOEmitter)) continue; break;
|
||||
case Type_Terrain: if (!(save_flag & SceneIOTerrain)) continue; break;
|
||||
case Type_Constraint: if (!(save_flag & SceneIOConstraint)) continue; break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
itag->AddChild(i->AsMetaTag());
|
||||
}
|
||||
else
|
||||
__ERR__(__LOG_E__ << "Failed to allocate <Items> root tag.\n", NULL);
|
||||
|
||||
// Write link informations.
|
||||
if (Tag *ltag = root->AddChild("Links"))
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
ltag->AddChild(LinkInfoAsMetaTag(i, group, save_flag));
|
||||
else
|
||||
__ERR__(__LOG_E__ << "Failed to allocate <Links> root tag.\n", NULL)
|
||||
|
||||
// Write skin informations.
|
||||
if (Tag *stag = root->AddChild("Skins"))
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (i->GetItemType() == Type_Object)
|
||||
stag->AddChild(SkinInfoAsMetaTag((MObject *)i, group, save_flag));
|
||||
|
||||
if (stag->GetChildCount() == 0)
|
||||
{
|
||||
root->RemoveTag(stag);
|
||||
_safe_delete(stag);
|
||||
}
|
||||
}
|
||||
else
|
||||
__ERR__(__LOG_E__ << "Failed to allocate <Skins> root tag.\n", NULL);
|
||||
|
||||
// Write constraints.
|
||||
if (Tag *constraint_tag = root->AddChild("Constraints"))
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (i->GetItemType() == Type_Constraint)
|
||||
{
|
||||
if (group && !group->IsMember(i))
|
||||
continue;
|
||||
|
||||
MConstraint *c = (MConstraint *)i;
|
||||
if (Tag *ctag = constraint_tag->AddChild("Constraint"))
|
||||
{
|
||||
ctag->AddChild("Uid", c->GetUid());
|
||||
if (c->desc.item_a.IsValid())
|
||||
ctag->AddChild("UidA", c->desc.item_a->GetUid());
|
||||
if (c->desc.item_b.IsValid())
|
||||
ctag->AddChild("UidB", c->desc.item_b->GetUid());
|
||||
}
|
||||
}
|
||||
|
||||
// Write scene groups.
|
||||
if (!group)
|
||||
{
|
||||
if ((save_flag & SceneIOGroup) && group_list.GetCount())
|
||||
{
|
||||
if (Tag *gstag = root->AddChild("Groups"))
|
||||
{
|
||||
ListForeachPtr(Group *, group, group_list)
|
||||
if (Tag *gtag = gstag->AddChild("Group"))
|
||||
{
|
||||
gtag->AddChild("Id", group->name.c_str());
|
||||
ListForeachPtr(MItem *, item, group->GetItemList())
|
||||
gtag->AddChild("Item", item->GetUid());
|
||||
}
|
||||
}
|
||||
else
|
||||
__ERR__(__LOG_E__ << "Failed to allocate <Groups> root tag.\n", NULL);
|
||||
}
|
||||
|
||||
// Output scene properties.
|
||||
if (save_flag & SceneIOGlobals)
|
||||
{
|
||||
if (Tag *gtag = root->AddChild("Globals"))
|
||||
{
|
||||
gtag->AddChild(background_color.AsMetaTag("BackgroundColor"));
|
||||
gtag->AddChild(ambient_color.AsMetaTag("AmbientColor"));
|
||||
|
||||
if (!irradiance_probe.IsEmpty())
|
||||
gtag->AddChild("Irradiance", irradiance_probe.c_str());
|
||||
if (!radiance_probe.IsEmpty())
|
||||
gtag->AddChild("Radiance", radiance_probe.c_str());
|
||||
|
||||
if (!skybox_layer[0].IsEmpty())
|
||||
gtag->AddChild("SkyLayer0", skybox_layer[0].c_str());
|
||||
if (!skybox_layer[1].IsEmpty())
|
||||
gtag->AddChild("SkyLayer1", skybox_layer[1].c_str());
|
||||
if (!skybox_shader.IsEmpty())
|
||||
gtag->AddChild("SkyShader", skybox_shader.c_str());
|
||||
|
||||
gtag->AddChild("TimeOfDay", time_of_day);
|
||||
|
||||
gtag->AddChild("AmbientIntensity", ambient_intensity);
|
||||
gtag->AddChild("TargetExposure", target_exposure);
|
||||
|
||||
gtag->AddChild("FogNear", fog_near);
|
||||
gtag->AddChild("FogFar", fog_far);
|
||||
|
||||
gtag->AddChild(fog_color.AsMetaTag("FogColor"));
|
||||
}
|
||||
else
|
||||
__ERR__(__LOG_E__ << "Failed to allocate <Globals> root tag.\n", NULL);
|
||||
}
|
||||
|
||||
// Physics.
|
||||
if ((save_flag & SceneIOPhysic) && physic_world.IsValid())
|
||||
if (Tag *ptag = root->AddChild("Physics"))
|
||||
ptag->AddChild("Frequency", 1.f / physic_world->GetTimestep());
|
||||
|
||||
// Current camera.
|
||||
if (current_camera)
|
||||
if (MItem *ci = LocateManagedItem(current_camera))
|
||||
root->AddChild("CurrentCamera", ci->name);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
57
include/engine/scene3d/scene_physic_world_interface.cpp
Normal file
57
include/engine/scene3d/scene_physic_world_interface.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene_physic_world_interface.h"
|
||||
#include "scene3d/mitem_event_interface.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "physic/physic_world.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void IScenePhysicWorld::PhysicStep(float timestep, bool pre_tick)
|
||||
{
|
||||
if (pre_tick)
|
||||
{
|
||||
scene->SynchronizePhysics();
|
||||
|
||||
// Pre-tick, step physics.
|
||||
scene->scene_event->OnPhysicStep(scene, true);
|
||||
|
||||
ArrayListForeachPtr(MItem *, item, scene->GetActiveList())
|
||||
switch (item->GetItemType())
|
||||
{
|
||||
default:
|
||||
if (!item->physic_item || (item->physic_item_desc.physic_mode == PhysicItemDesc::Mode_None))
|
||||
break;
|
||||
|
||||
case Type_Instance:
|
||||
item->item_event->OnPhysicStep(item, true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// End of tick, dispatch collision events.
|
||||
for (uint n = 0; n < scene->physic_world->GetCollisionPairCount(); ++n)
|
||||
{
|
||||
CollisionPair pair;
|
||||
if (!scene->physic_world->GetCollisionPair(n, pair))
|
||||
continue;
|
||||
|
||||
MItem *item_a = (MItem *)pair.a->GetUserPointer(),
|
||||
*item_b = (MItem *)pair.b->GetUserPointer();
|
||||
if (item_a && item_a->item_event.IsValid() && item_b && item_b->item_event.IsValid()) {
|
||||
item_a->item_event->OnCollision(item_a, item_b, pair);
|
||||
item_b->item_event->OnCollision(item_b, item_a, pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
33
include/engine/scene3d/scene_preloader.cpp
Normal file
33
include/engine/scene3d/scene_preloader.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "core/render_resource_factory.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Scene::PreloadResources(GS::Render::ResourceFactory &rf, const char *uri)
|
||||
{
|
||||
__LOG_H__ << "Preloading scene '" << uri << "' resources.\n";
|
||||
|
||||
using namespace GS::NML;
|
||||
|
||||
File file;
|
||||
if (!Parser::Load(uri, file))
|
||||
return false;
|
||||
|
||||
if (Tag *items = file.GetTag("Scene:Items;"))
|
||||
{
|
||||
NMLTagForeach(t, *items)
|
||||
if (t->name == "MObject")
|
||||
if (Tag *g = t->GetTypedTag("Object:Geometry;", Variant::VariantString))
|
||||
rf.LoadGeometry(g->GetString());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
111
include/engine/scene3d/scene_profiler.cpp
Normal file
111
include/engine/scene3d/scene_profiler.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "core/renderer.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
//
|
||||
class ProfilerRenderer
|
||||
{
|
||||
Renderer &render;
|
||||
RasterFont **font;
|
||||
|
||||
float &x, &y;
|
||||
|
||||
Renderer::WriterConfig config;
|
||||
|
||||
Color title_color;
|
||||
|
||||
static const int indent_width = 16;
|
||||
static const int col_a_x = 180, col_b_x = 256;
|
||||
|
||||
void DisplaySystem(const char *label, const Benchmark &bench)
|
||||
{
|
||||
float x_h = x;
|
||||
render.Write(*font[0], label, x_h, y, config, 1, &title_color);
|
||||
|
||||
float x_a = x + col_a_x;
|
||||
render.Write(*font[0], String::Format("%0.02fms", bench.GetMs()), x_a, y, config, 1, &title_color);
|
||||
float x_b = x + col_b_x;
|
||||
render.Write(*font[0], bench.GetMs() ? String::Format("%.01ffps", 1000.f / bench.GetMs()) : "-", x_b, y, config, 1, &title_color);
|
||||
|
||||
render.Write(*font[0], "\n", x, y, config, 1, &title_color);
|
||||
}
|
||||
void DisplaySystem(const char *label, const Benchmark &bench, const Benchmark &parent)
|
||||
{
|
||||
float x_h = x;
|
||||
render.Write(*font[0], label, x_h, y, config, 1, &title_color);
|
||||
|
||||
float x_a = x + col_a_x;
|
||||
render.Write(*font[0], String::Format("%0.02fms", bench.GetMs()), x_a, y, config, 1, &title_color);
|
||||
float x_b = x + col_b_x;
|
||||
render.Write(*font[0], String::Format("%d%%", parent.GetMs() ? int(bench.GetMs() * 100.f / parent.GetMs()) : 0), x_b, y, config, 1, &title_color);
|
||||
|
||||
render.Write(*font[0], "\n", x, y, config, 1, &title_color);
|
||||
}
|
||||
void RenderSystem(const Profiler::System *sys, const Profiler::System *parent, int indent_level)
|
||||
{
|
||||
float x_s = x;
|
||||
x += indent_level * indent_width;
|
||||
|
||||
if (parent)
|
||||
DisplaySystem(sys->label, sys->profile, parent->profile);
|
||||
else DisplaySystem(sys->label, sys->profile);
|
||||
|
||||
x = x_s;
|
||||
|
||||
ListForeachPtr(Profiler::System *, sub, sys->sub_systems)
|
||||
RenderSystem(sub, sys, indent_level + 1);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void DisplayHeader(const char *header)
|
||||
{
|
||||
render.Write(*font[1], String(header) << "\n\n", x, y, config, 1, &title_color);
|
||||
}
|
||||
|
||||
void StartRender()
|
||||
{
|
||||
render.SetWorldMatrix(Matrix4::IdentityMatrix(), &Matrix4::IdentityMatrix());
|
||||
render.SetViewMatrix(Matrix4::IdentityMatrix(), &Matrix4::IdentityMatrix());
|
||||
render.SetProjectionMatrix(Matrix4::IdentityMatrix());
|
||||
}
|
||||
void Render(const Profiler &profiler)
|
||||
{
|
||||
ListForeachPtr(Profiler::System *, sys, profiler.root_systems)
|
||||
RenderSystem(sys, NULL, 0);
|
||||
}
|
||||
|
||||
ProfilerRenderer(Renderer &r, RasterFont *f[2], float &_x, float &_y) : render(r), font(f), x(_x), y(_y), config(false), title_color(1, 1, 1) {}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SceneProfiler::ResetProfiles()
|
||||
{
|
||||
Profiler::ResetProfiles();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::DrawProfilerText(Renderer &render, RasterFont *font[2], float &x, float &y)
|
||||
{
|
||||
ProfilerRenderer prof_render(render, font, x, y);
|
||||
|
||||
prof_render.StartRender();
|
||||
prof_render.DisplayHeader(String::Format("Scene: %d item, %d active (%d%%)", item_list.GetCount(), active_list.GetCount(), item_list.GetCount() ? (active_list.GetCount() * 100) / item_list.GetCount() : 100));
|
||||
prof_render.Render(profiler);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
105
include/engine/scene3d/scene_render.cpp
Normal file
105
include/engine/scene3d/scene_render.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/memitter.h"
|
||||
#include "scene3d/mterrain.h"
|
||||
#include "scene3d/mitem_event_interface.h"
|
||||
#include "ui/ui.h"
|
||||
#include "core/renderer.h"
|
||||
#include "core/camera.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::PushRenderable(Renderer &renderer)
|
||||
{
|
||||
ScopedSystemProfile(profiler.push_to_render);
|
||||
|
||||
{
|
||||
ScopedSystemProfile(profiler.push_active_list);
|
||||
|
||||
ArrayListForeachPtr(MItem *, ci, active_list)
|
||||
if (Core::Item *b = ci->GetBaseItem())
|
||||
{
|
||||
// Check exclusion.
|
||||
if (b->item_flags.IsSet(ItemFlagInvisible))
|
||||
continue;
|
||||
if (ci->mitem_flags.IsSet(MItem::Flag_EditorHidden))
|
||||
continue;
|
||||
|
||||
// Render objects and emitters.
|
||||
switch (ci->GetItemType())
|
||||
{
|
||||
case Type_Emitter:
|
||||
renderer.PushRenderable((Core::Emitter *)b);
|
||||
break;
|
||||
case Type_Terrain:
|
||||
renderer.PushRenderable((Core::Terrain *)b);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push culling systems.
|
||||
{
|
||||
ScopedSystemProfile(profiler.push_simple_culling);
|
||||
renderer.PushRenderable(&simple_culling_system);
|
||||
}
|
||||
{
|
||||
ScopedSystemProfile(profiler.push_octree_culling);
|
||||
renderer.PushRenderable(&octree_culling_system);
|
||||
}
|
||||
}
|
||||
void Scene::Render(Renderer &renderer)
|
||||
{
|
||||
renderer.SetEnvironmentInterface(irenderer_environment);
|
||||
|
||||
scene_event->OnRender(this);
|
||||
|
||||
if (!flags.IsSet(FlagRenderless))
|
||||
{
|
||||
PushRenderable(renderer);
|
||||
|
||||
renderer.BeginDrawList();
|
||||
renderer.RenderList();
|
||||
renderer.EndDrawList();
|
||||
|
||||
renderer.DeleteRenderableList();
|
||||
}
|
||||
|
||||
renderer.SetEnvironmentInterface(NULL);
|
||||
|
||||
scene_event->OnRenderDone(this);
|
||||
}
|
||||
void Scene::RenderUI(Renderer &renderer, GPU::TriangleBatch *batch)
|
||||
{
|
||||
if (renderer.ideal_render_system_vr_resolution.x != -1)
|
||||
{
|
||||
uint w, h;
|
||||
renderer.GetOutputWindow()->GetSize(w, h);
|
||||
renderer.dimensions.Set(w, h);
|
||||
renderer.SetViewport(fRect(0, 0, w, h));
|
||||
}
|
||||
|
||||
ui->Render(renderer, batch);
|
||||
|
||||
scene_event->OnRenderUIDone(this);
|
||||
|
||||
ui->RenderGlobalFade(renderer);
|
||||
|
||||
if(renderer.ideal_render_system_vr_resolution.x != -1)
|
||||
{
|
||||
renderer.dimensions.Set(renderer.ideal_render_system_vr_resolution.x, renderer.ideal_render_system_vr_resolution.y);
|
||||
renderer.ideal_render_system_vr_resolution.x = -1;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
161
include/engine/scene3d/scene_renderer_environment_interface.cpp
Normal file
161
include/engine/scene3d/scene_renderer_environment_interface.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene_renderer_environment_interface.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "core/renderer.h"
|
||||
#include "sort/sort.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
float IEnvironment::GetClock() const
|
||||
{ return scene->GetClock()->Getf(); }
|
||||
float IEnvironment::GetTimeOfDay() const
|
||||
{ return scene->time_of_day; }
|
||||
Render::Shader *IEnvironment::GetSkyboxShader() const
|
||||
{ return scene->render_data ? scene->render_data->skybox_shader.c_ptr() : NULL; }
|
||||
bool IEnvironment::GetSkyboxLayers(Render::sTexture layers[2]) const
|
||||
{
|
||||
if (scene->render_data.IsValid())
|
||||
for (uint n = 0; n < 2; ++n)
|
||||
layers[n] = scene->render_data->skybox_layer[n];
|
||||
|
||||
return layers[0].IsValid() && layers[1].IsValid();
|
||||
}
|
||||
void IEnvironment::GetEnvironmentProbe(Render::sTexture &radiance, Render::sTexture &irradiance) const
|
||||
{
|
||||
if (scene->render_data.IsValid())
|
||||
{
|
||||
radiance = scene->render_data->radiance_probe;
|
||||
irradiance = scene->render_data->irradiance_probe;
|
||||
}
|
||||
}
|
||||
bool IEnvironment::IsFogEnabled() const
|
||||
{ return scene->fog_far > 0.f; }
|
||||
bool IEnvironment::GetFogConfiguration(Color &color, float &fog_near, float &fog_far) const
|
||||
{
|
||||
if (scene->fog_far < 0.f)
|
||||
return false;
|
||||
|
||||
color = scene->fog_color;
|
||||
fog_near = scene->fog_near;
|
||||
fog_far = scene->fog_far;
|
||||
return true;
|
||||
}
|
||||
Color IEnvironment::GetClearColor() const
|
||||
{ return scene->background_color; }
|
||||
Color IEnvironment::GetAmbientColor() const
|
||||
{ return scene->ambient_color * scene->ambient_intensity; }
|
||||
static float CompareLightPriority(const MLight *a, const MLight *b) { return a->GetPriority() - b->GetPriority(); }
|
||||
void IEnvironment::GetLightsInFrustum(const Vector4 &world_pos, const Frustum &frustum, List <Light *> &list, uint limit) const
|
||||
{
|
||||
list.Clear();
|
||||
|
||||
// On very large scenes filtering items by type can become very slow.
|
||||
#if 0
|
||||
nSharedList <nMLight *> lights;
|
||||
if (!scene->GetItemListByType(lights))
|
||||
return;
|
||||
#else
|
||||
List <MLight *> lights;
|
||||
scene->GetLightList().Clone(lights);
|
||||
#endif
|
||||
lights.Sort(CompareLightPriority);
|
||||
|
||||
ListForeachPtr(MLight *, l, lights)
|
||||
{
|
||||
if (!l->isActive())
|
||||
continue;
|
||||
|
||||
// Check light range and clip distance.
|
||||
if (l->range)
|
||||
{
|
||||
if (Vector4::Dist(world_pos, l->GetMatrix().GetRow(3)) >= (l->clip_distance + l->range))
|
||||
continue;
|
||||
|
||||
// Check frustum intersection.
|
||||
switch (l->model)
|
||||
{
|
||||
case Light::Model_Point:
|
||||
if (frustum.ClassifySphere(l->GetMatrix().GetRow(3), l->range) == Frustum::Outside)
|
||||
continue;
|
||||
break;
|
||||
|
||||
case Light::Model_Spot:
|
||||
if (frustum.ClassifyFrustrum(l->frustum) == Frustum::Outside)
|
||||
continue;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
list.Add(l);
|
||||
if (list.GetCount() == limit)
|
||||
break;
|
||||
}
|
||||
}
|
||||
void IEnvironment::GetClosestLights(const Vector4 &world_pos, List <Light *> &list, uint limit) const
|
||||
{
|
||||
list.Clear();
|
||||
|
||||
#if 0
|
||||
nSharedList <nMLight *> lights;
|
||||
if (!scene->GetItemListByType(lights))
|
||||
return;
|
||||
#else
|
||||
List <MLight *> lights;
|
||||
scene->GetLightList().Clone(lights);
|
||||
#endif
|
||||
|
||||
Array <Sort <float, MLight *>::Entry> array(lights.GetCount());
|
||||
if (!array)
|
||||
__ERRRAW__(__LOG_E__ << "Failed to allocated sort structure.\n")
|
||||
|
||||
int c = 0;
|
||||
ListForeachPtr(MLight *, l, lights)
|
||||
if (l->isActive())
|
||||
{
|
||||
array[c].o = l;
|
||||
array[c].v = Vector4::Dist2(world_pos, l->GetMatrix().GetRow(3)) * (1.f - l->GetPriority());
|
||||
++c;
|
||||
}
|
||||
|
||||
Sort <float, MLight *>::QuickSort(c, array);
|
||||
for (int n = 0; n < c; n++)
|
||||
{
|
||||
list.Add(array[n].o);
|
||||
if (list.GetCount() == limit)
|
||||
break;
|
||||
}
|
||||
}
|
||||
Camera *IEnvironment::GetCurrentCamera() const
|
||||
{ return scene->current_camera; }
|
||||
void IEnvironment::OnRenderUser(Renderer *renderer) const
|
||||
{
|
||||
scene->scene_event->OnRenderUser(scene);
|
||||
|
||||
// Debug physics.
|
||||
if (scene->flags.IsSet(Scene::FlagDebugPhysics))
|
||||
if (PhysicWorld *world = scene->physic_world)
|
||||
{
|
||||
if (!world->HasDebugger())
|
||||
world->CreateDebugger(renderer);
|
||||
|
||||
renderer->SetWorldMatrix(Matrix4::IdentityMatrix(), &Matrix4::IdentityMatrix());
|
||||
renderer->ApplyCamera();
|
||||
|
||||
world->DrawDebug(*renderer, scene->current_camera, NULL/*profiler_font[0]*/, true);
|
||||
world->DrawDebug(*renderer, scene->current_camera, NULL/*profiler_font[0]*/, false);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
31
include/engine/scene3d/scene_reset.cpp
Normal file
31
include/engine/scene3d/scene_reset.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::Reset()
|
||||
{
|
||||
__LOG_H__ << "Reset scene '" << name << "'.\n";
|
||||
|
||||
// Reset item sequence.
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
i->ResetToInitialTransformation();
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
i->Reset();
|
||||
|
||||
scene_event->OnReset(this);
|
||||
|
||||
// Reset all benchmark objects.
|
||||
profiler.ResetProfiles();
|
||||
|
||||
flags.Raise(FlagEnd, false);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
46
include/engine/scene3d/scene_script_unit.cpp
Normal file
46
include/engine/scene3d/scene_script_unit.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene_script_unit.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool SceneScriptUnit::Open()
|
||||
{
|
||||
if (!Unit::Open())
|
||||
return false;
|
||||
|
||||
render_callback = vm->GetObjectFromName("OnRender", self);
|
||||
render_done_callback = vm->GetObjectFromName("OnRenderDone", self);
|
||||
render_user_callback = vm->GetObjectFromName("OnRenderUser", self);
|
||||
render_ui_done_callback = vm->GetObjectFromName("OnRenderUIDone", self);
|
||||
|
||||
update_callback = vm->GetObjectFromName("OnUpdate", self);
|
||||
physic_step_callback = vm->GetObjectFromName("OnPhysicStep", self);
|
||||
|
||||
return true;
|
||||
}
|
||||
void SceneScriptUnit::Close()
|
||||
{
|
||||
render_callback = NULL;
|
||||
render_done_callback = NULL;
|
||||
render_user_callback = NULL;
|
||||
render_ui_done_callback = NULL;
|
||||
|
||||
update_callback = NULL;
|
||||
physic_step_callback = NULL;
|
||||
|
||||
Unit::Close();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SceneScriptUnit::SceneScriptUnit(IVM *vm) : Unit(vm) {}
|
||||
SceneScriptUnit::~SceneScriptUnit() { Close(); }
|
||||
//------------------------------------------------------------------------------
|
||||
25
include/engine/scene3d/scene_scripted_object.cpp
Normal file
25
include/engine/scene3d/scene_scripted_object.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene_scripted_object.h"
|
||||
#include "scene3d/scene_script_unit.h"
|
||||
#include "script/script_engine_types.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Unit *SceneScriptedObject::NewUnit() const
|
||||
{
|
||||
Unit *unit = new SceneScriptUnit(vm);
|
||||
if (!unit)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate new scene script unit.", NULL);
|
||||
unit->SetInterfaceObject(scene, typetag_Scene3d);
|
||||
return unit;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
85
include/engine/scene3d/scene_setup.cpp
Normal file
85
include/engine/scene3d/scene_setup.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/instance.h"
|
||||
#include "scene3d/mconstraint.h"
|
||||
#include "core/resource_factories.h"
|
||||
#include "script/scripted_object.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::RenderSetup(Core::ResourceFactories *f, bool setup_items)
|
||||
{
|
||||
__LOG__ << "Scene '" << name << "' render setup...\n";
|
||||
|
||||
if ((render_data = new RenderData) != NULL)
|
||||
{
|
||||
render_data->skybox_shader = f->render->LoadShader(skybox_shader);
|
||||
for (uint n = 0; n < 2; ++n)
|
||||
render_data->skybox_layer[n] = f->render->LoadTexture(skybox_layer[n]);
|
||||
|
||||
render_data->radiance_probe = f->render->LoadTexture(radiance_probe);
|
||||
render_data->irradiance_probe = f->render->LoadTexture(irradiance_probe);
|
||||
}
|
||||
|
||||
if (setup_items)
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (Core::Item *b = i->GetBaseItem())
|
||||
b->RenderSetup(f);
|
||||
}
|
||||
void Scene::InstanceSetup()
|
||||
{
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (i->GetItemType() == Type_Instance)
|
||||
((Instance *)i)->Instantiate(this);
|
||||
}
|
||||
void Scene::Setup(ToolMode tool_mode)
|
||||
{
|
||||
__LOG_H__ << "Setup scene '" << name << "'.\n";
|
||||
|
||||
scene_event->OnSetup(this);
|
||||
|
||||
// Setup items.
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
i->Setup(tool_mode == ToolEdit ? NULL : physic_world.c_ptr());
|
||||
|
||||
scene_event->OnSetupDone(this);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::TestOptimizeGeometry(Render::Geometry *geo, uint octree_node_size)
|
||||
{
|
||||
if (!geo)
|
||||
return;
|
||||
|
||||
// Avoid infinite recursion.
|
||||
if (geo->shadow_proxy == geo)
|
||||
geo->shadow_proxy = NULL;
|
||||
if (geo->lod_proxy == geo)
|
||||
geo->lod_proxy = NULL;
|
||||
|
||||
TestOptimizeGeometry(geo->shadow_proxy, octree_node_size);
|
||||
TestOptimizeGeometry(geo->lod_proxy, octree_node_size);
|
||||
}
|
||||
void Scene::OptimizeForRealtime(uint octree_node_size)
|
||||
{
|
||||
List <Render::sGeometry> list;
|
||||
ListForeachPtr(MItem *, i, item_list)
|
||||
if (i->GetItemType() == Type_Object)
|
||||
if (MObject *o = (MObject *)i)
|
||||
if (o->render_data.IsValid() && o->render_data->geometry.IsValid())
|
||||
list.Add(o->render_data->geometry, true, false);
|
||||
|
||||
for (uint n = 0; n < list.GetCount(); ++n)
|
||||
TestOptimizeGeometry(list[n], octree_node_size);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
29
include/engine/scene3d/scene_trigger.cpp
Normal file
29
include/engine/scene3d/scene_trigger.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mtrigger.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::UpdateTriggers()
|
||||
{
|
||||
ListForeachPtr(MTrigger *, t, trigger_list)
|
||||
if (t->isActive())
|
||||
{
|
||||
t->ReadyItemList();
|
||||
|
||||
ArrayListForeachPtr(MItem *, i, active_list)
|
||||
if (i->mitem_flags.IsSet(MItem::Flag_TriggerDetected)) // TODO make a dedicated list.
|
||||
if (i->isActive() && t->IsInside(i->GetBaseItem()->GetMatrix().GetRow(3)))
|
||||
t->MarkItem(i->GetBaseItem());
|
||||
|
||||
t->PurgeItemList();
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
234
include/engine/scene3d/scene_update.cpp
Normal file
234
include/engine/scene3d/scene_update.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mitem_event_interface.h"
|
||||
#include "ui/ui.h"
|
||||
#include "motion/motion_automation_source.h"
|
||||
#include "automation/automation_source_group.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "core/object.h"
|
||||
#include "core/camera.h"
|
||||
#include "script/script_engine_types.h"
|
||||
#include "script/script_variant.h"
|
||||
#include "sort/sort.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::SetAsScriptGlobalScene(Script::IVM *_vm)
|
||||
{
|
||||
if (!_vm)
|
||||
_vm = vm;
|
||||
if (!_vm || !_vm->IsOpen())
|
||||
return;
|
||||
|
||||
_vm->Set("g_scene", Script::Variant(this, Script::typetag_Scene3d));
|
||||
_vm->Set("g_clock_fq", Platform::Get().GetClockFrequency());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::SetMotion(const char *name, Automation::SourceGroup **group, float blend, Automation::Player::AddSourceMode mode, float weight)
|
||||
{
|
||||
if (group)
|
||||
*group = new Automation::SourceGroup;
|
||||
|
||||
SceneMotion *scene_motion = NULL;
|
||||
ListForeachPtr(SceneMotion *, m, motion.motions)
|
||||
if (m->name == name)
|
||||
{
|
||||
scene_motion = m;
|
||||
break;
|
||||
}
|
||||
|
||||
if (scene_motion)
|
||||
{
|
||||
// Start item motions.
|
||||
ListForeachPtr(SceneMotion::ItemMotion *, m, scene_motion->item_motions)
|
||||
if (MItem *i = ItemFromUid(m->uid))
|
||||
i->automation_player->StartAutomation(new Automation::MotionSource(m->motion, group ? *group : NULL), blend, mode, weight);
|
||||
}
|
||||
else // fallback to the legacy per-item set motion
|
||||
ArrayListForeachPtr(MItem *, item, GetActiveList())
|
||||
if (Motion *motion = item->automation_player->GetMotion(name))
|
||||
item->automation_player->StartAutomation(new Automation::MotionSource(motion, group ? *group : NULL), blend, mode, weight);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::SynchronizePhysics()
|
||||
{
|
||||
Matrix4 m;
|
||||
ArrayListForeachPtr(MItem *, item, active_list)
|
||||
if (item->physic_item)
|
||||
switch (item->physic_item_desc.physic_mode)
|
||||
{
|
||||
case PhysicItemDesc::Mode_Kinematic:
|
||||
case PhysicItemDesc::Mode_Static:
|
||||
item->physic_item->SetEngineMatrix(item->GetBaseItem()->GetMatrix());
|
||||
break;
|
||||
|
||||
case PhysicItemDesc::Mode_Dynamic:
|
||||
case PhysicItemDesc::Mode_Vehicle:
|
||||
case PhysicItemDesc::Mode_Character:
|
||||
item->physic_item->GetGraphicMatrix(m);
|
||||
item->physic_item->SetEngineMatrix(m);
|
||||
item->GetBaseItem()->SetMatrix(m);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::UpdateItemTransformation(MItem *i, const Time &dt)
|
||||
{
|
||||
i->Update(dt);
|
||||
|
||||
if (Core::Item *b = i->GetBaseItem())
|
||||
{
|
||||
if (i->mitem_flags.IsSet(MItem::Flag_Billboard))
|
||||
{
|
||||
Vector4 p, s;
|
||||
|
||||
if (Core::Item *link = b->GetParent())
|
||||
{
|
||||
p = b->GetPosition() * link->GetMatrix();
|
||||
s = b->GetScale() * link->GetScale();
|
||||
}
|
||||
else
|
||||
{
|
||||
p = b->GetPosition();
|
||||
s = b->GetScale();
|
||||
}
|
||||
|
||||
Matrix3 view_matrix(Matrix3::FromMatrix4(current_camera ? current_camera->GetMatrix() : Matrix4::IdentityMatrix()) * Matrix3::RotationMatrixZAxis(b->GetRotation().z));
|
||||
Matrix4 billboard_matrix(Matrix4::TransformationMatrix(p, view_matrix, s));
|
||||
b->SnapshotTransformation(billboard_matrix, false, true);
|
||||
}
|
||||
|
||||
/*
|
||||
[EJ] Force matrix update here so that const references can access
|
||||
up-to-date informations.
|
||||
*/
|
||||
b->GetMatrix();
|
||||
b->GetInverseMatrix();
|
||||
}
|
||||
}
|
||||
void Scene::Update(uint eval_flag)
|
||||
{
|
||||
ScopedSystemProfile(profiler.update);
|
||||
|
||||
{
|
||||
ScopedSystemProfile(profiler.process_queues);
|
||||
|
||||
ProcessItemRemovalQueue();
|
||||
/*
|
||||
Note: This step is intentionally delayed for one update in order to
|
||||
evaluate newly activated items before displaying them.
|
||||
*/
|
||||
ProcessItemActivationQueue();
|
||||
|
||||
/*
|
||||
Store item previous position/rotation (disregarding the inactive flag).
|
||||
Note: This is done here because the physic system will alter item's matrix.
|
||||
*/
|
||||
ArrayListForeachPtr(MItem *, i, active_list)
|
||||
if (Core::Item *b = i->GetBaseItem())
|
||||
b->SetPreviousMatrix(b->GetMatrix());
|
||||
}
|
||||
|
||||
// Update clock.
|
||||
if (clock->GetRefCount() == 1) // Do not update external clock.
|
||||
clock->Update();
|
||||
Time dt = Time::fromSec(clock->GetDeltaf());
|
||||
|
||||
// Update triggers (result is cached in trigger).
|
||||
if (eval_flag & SceneUpdateTrigger)
|
||||
{
|
||||
ScopedSystemProfile(profiler.update_triggers);
|
||||
UpdateTriggers();
|
||||
}
|
||||
|
||||
// Update physics.
|
||||
if (physic_world.IsValid() && (eval_flag & SceneUpdatePhysic))
|
||||
{
|
||||
{
|
||||
ScopedSystemProfile(profiler.physic_step);
|
||||
physic_world->Step(dt);
|
||||
}
|
||||
{
|
||||
ScopedSystemProfile(profiler.synchronize_physics);
|
||||
SynchronizePhysics();
|
||||
}
|
||||
}
|
||||
|
||||
// Update item transformations.
|
||||
{
|
||||
ScopedSystemProfile(profiler.update_item_transformation);
|
||||
|
||||
// Evaluate items and hierarchies (matrix).
|
||||
#if 0
|
||||
Array <Sort::Entry <int, MItem *> > hierarchy_in(active_list.GetCount()), hierarchy_out(active_list.GetCount());
|
||||
|
||||
int count = 0;
|
||||
ArrayListForeachPtr(MItem *, i, active_list)
|
||||
if (Item *b = i->GetBaseItem())
|
||||
{
|
||||
hierarchy_in[count].o = i;
|
||||
hierarchy_in[count].v = 0;
|
||||
for (Item *p = b; p; p = p->GetParent())
|
||||
++hierarchy_in[count].v;
|
||||
++count;
|
||||
}
|
||||
|
||||
Array <Sort::Entry <int, MItem *> > *sorted = nSort::ByteSort(count, &hierarchy_in, &hierarchy_out);
|
||||
|
||||
for (int n = 0; n < count; ++n)
|
||||
UpdateItemTransformation((*sorted)[n].o, dt);
|
||||
#else
|
||||
ArrayListForeachPtr(MItem *, i, active_list)
|
||||
UpdateItemTransformation(i, dt);
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
ScopedSystemProfile(profiler.update_skin);
|
||||
|
||||
// Synchronize all skins with the final matrices.
|
||||
ArrayListForeachPtr(MItem *, i, active_list)
|
||||
if (i->GetItemType() == Type_Object)
|
||||
((Object *)i->GetBaseItem())->UpdateSkin();
|
||||
}
|
||||
|
||||
// Script events.
|
||||
if (eval_flag & SceneUpdateEvent)
|
||||
{
|
||||
{
|
||||
ScopedSystemProfile(profiler.scene_on_update);
|
||||
scene_event->OnUpdate(this);
|
||||
}
|
||||
|
||||
{
|
||||
ScopedSystemProfile(profiler.items_on_update);
|
||||
ArrayListForeachPtr(MItem *, i, active_list)
|
||||
i->item_event->OnUpdate(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Update UI.
|
||||
if (ui)
|
||||
{
|
||||
ScopedSystemProfile(profiler.ui_update);
|
||||
ui->Update();
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user