/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #ifndef __NSCENE__ #define __NSCENE__ #include "scene3d/scene_message.h" #include "scene3d/scene_event_interface.h" #include "scene3d/group.h" #include "scene3d/scene_io_flag.h" #include "scene3d/scene_profiler.h" #include "core/core_profiler.h" #include "core/renderer_environment_interface.h" #include "core/simple_list_renderable.h" #include "core/octree_renderable.h" #include "core/tool_mode.h" #include "core/clock.h" #include "script/script_vm.h" #include "timing/profiler.h" #include "reflection/c_refl.h" /// Debug display flags. #define SceneDebugDisplayItems (1 << 0) #define SceneDebugDisplayBones (1 << 1) #define SceneDebugDisplayBoundingVolumes (1 << 2) #define SceneDebugDisplayOctreeVolumes (1 << 3) #define SceneDebugDisplayMotions (1 << 4) /// Scene update flags. #define SceneUpdateNone 0 #define SceneUpdateMotion (1 << 0) #define SceneUpdatePhysic (1 << 1) #define SceneUpdateEvent (1 << 2) #define SceneUpdateTrigger (1 << 3) #define SceneUpdateAll uint(~0) namespace GS { namespace GPU { class TriangleBatch; } namespace S2D { class Scene; } namespace S3D { struct MLight; struct MObject; struct MTrigger; struct IPhysicWorld; class PhysicWorld; using Render::Renderer; using Render::RasterFont; /*! @short Scene object. @author Emmanuel Julien (ejulien@gsworks.fr) */ class Scene : public SharedObject { uint current_item_uid; struct RenderData { Render::sShader skybox_shader; Render::sTexture skybox_layer[2]; Render::sTexture irradiance_probe, radiance_probe; }; public: /// Scene-wide flag. enum SceneFlag { FlagNone = 0, FlagEnd = (1 << 0), FlagRenderless = (1 << 1), FlagDebugPhysics = (1 << 2) }; protected: Core::sClock clock; SharedList activation_queue, deactivation_queue; SharedList item_list, removal_queue; SharedArrayList active_list; // faster traversal than a shared list SharedList group_list; List light_list; List trigger_list; /// Evaluate item. void UpdateItem(float dt, MItem *, Core::Item *, uint eval_flag = SceneUpdateAll); public: String name; BitField flags; ///< Scene flags. AutoPtr ui; void Render(Renderer &); void RenderUI(Renderer &, GPU::TriangleBatch * = 0); Core::Clock *GetClock() const { return clock; } void SetClock(Core::Clock * = 0, bool set_ui = true); /// Dump scene content to log. void DumpContentToLog() const; Core::Camera *current_camera; /*! @name Core::Item management. @{ */ void SetupItemComponents(MItem *); void AddItem(MItem *, bool setup_components); bool RemoveItem(MItem *); void QueueItemRemoval(MItem *); void ProcessItemRemovalQueue(); bool ActivateItem(MItem *, bool activate); void SetItemStatic(MItem *, bool is_static = true); void QueueItemActivation(MItem *, bool activate = true, bool propagate = false); void ProcessItemActivationQueue(); MItem *DuplicateItem(MItem *); MItemType LocateItem(const Core::Item *, MItem **entity = 0) const; static MItem *LocateManagedItem(Core::Item *); MItem *Item(const char *name, MItem * = 0) const; MItem *ItemFromUid(uint uid) const; const List &GetLightList() const { return light_list; } const SharedList &GetItemList() const { return item_list; } const SharedArrayList &GetActiveList() const { return active_list; } uint GetItemCountByType(MItemType type) const; // Filter item list and extract items of a give type. template uint GetItemListByType(SharedList &out) const { out.Clear(); ListForeachPtr(MItem *, i, item_list) if (i->GetItemType() == C::GetMItemClassType()) out.Add((C *)i); return out.GetCount(); } // Find item by type. template C *FindItemByType(const char *name) const { ListForeachPtr(MItem *, i, item_list) if (i->GetItemType() == C::GetMItemClassType()) if (i->name == name) return (C *)i; return 0; } /*! @} @name Group management. @{ */ Group *AddGroup(Group *); bool RemoveGroup(Group *); Group *FindGroup(const char *name) const; uint GetItemGroupList(const MItem *, SharedList &) const; void UnregisterItemFromGroups(MItem *) const; const SharedList &GetGroupList() const { return group_list; } void GroupMembersSetActive(Group *, bool = true); void DeleteGroupAndMembers(Group *); /*! @} @name Profiling. @{ */ SceneProfiler profiler; /// Display the profiler to screen using the renderer writer. void DrawProfilerText(Renderer &, RasterFont *font[2], float &x, float &y); /*! @} @name Culling system. @{ */ protected: Core::SimpleCullingSystem simple_culling_system; Core::OctreeCullingSystem octree_culling_system; public: void AddRenderable(Core::Renderable *, bool is_static = false); void RemoveRenderable(Core::Renderable *); /// Push this scene renderable onto the renderer display queue. void PushRenderable(Renderer &); /*! @} @name Environment. @{ */ Color background_color, ambient_color; float ambient_intensity, target_exposure; float time_of_day; String skybox_shader; String skybox_layer[2]; String irradiance_probe, radiance_probe; float fog_near, fog_far; Color fog_color; AutoPtr irenderer_environment; /*! @} @name Script system. @{ */ protected: Script::sVM vm; public: Script::IVM *GetVM() const { return vm; } AutoPtr scene_event; AutoPtr scripted_object; /// Set as the script master global scene. void SetAsScriptGlobalScene(Script::IVM * = 0); /// @} /*! @name Motion system. @{ */ Core::SceneMotionContainer motion; /*! @short Start a motion on the scene items. @note Request an animation source group if you need control on the started animation sources. */ void SetMotion(const char *name, Automation::SourceGroup ** = 0, float blend = Units::Sec(0.1), Automation::Player::AddSourceMode = Automation::Player::SourceSet, float weight = 1); /*! @} @name Physic system. @{ */ void SynchronizePhysics(); AutoPtr physic_world; AutoPtr iphysic_world; MTrigger *RaytraceTriggerList(Vector4 &s, Vector4 &d, float l = -1.f, Vector4 *i = 0); /* @} @name Scene Management. @{ */ bool Create(PhysicWorld *); void Reset(); void Clear(bool keep_script = false); void InstanceSetup(); void RenderSetup(Core::ResourceFactories *, bool setup_items = true); void Setup(ToolMode); void RecordAllItemLocation(); /// @} void GetMinMax(MinMax &) const; protected: void TestOptimizeGeometry(Render::Geometry *, uint octree_node_size); void UpdateItemTransformation(MItem *, const Time &dt); public: void OptimizeForRealtime(uint octree_node_size = 1024); void UpdateTriggers(); void Update(uint = SceneUpdateAll); /*! @name Scene serialization @{ */ protected: bool IsItemToBeSaved(MItem *, const Group *, uint flag) const; NML::Tag *LinkInfoAsMetaTag(MItem *, const Group * = 0, uint = SceneIOAll) const; NML::Tag *SkinInfoAsMetaTag(MObject *o, const Group * = 0, uint = SceneIOAll) const; public: /// Load all scene resources in render cache. static bool PreloadResources(Render::ResourceFactory &, const char *uri); /// Load scene from meta file, store content to group. bool FromMetaTagStoreGroup(const NML::Tag &, Group ** = 0, uint = SceneIOAll, ToolMode = NoTool, int load_level = 0); bool FromMetaFileStoreGroup(const char *, Group ** = 0, uint = SceneIOAll, ToolMode = NoTool, int load_level = 0); bool FromMetaTag(const NML::Tag &tag, ToolMode tool = NoTool) { return FromMetaTagStoreGroup(tag, 0, SceneIOAll, tool); } NML::Tag *AsMetaTag(const Group *, uint = SceneIOAll, ToolMode = NoTool) const; NML::Tag *AsMetaTag() const { return AsMetaTag(0); } /// @} AutoPtr render_data; Scene(Script::IVM *vm = 0); virtual ~Scene(); }; } // S3D } // GS #endif // __NSCENE__