/* ----------------------------------------------------------------------------- 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 > 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 > *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(); } } //------------------------------------------------------------------------------