Browse Source

Added entity group flags for group-based scene queries.
Fixed Input error message in headless mode.

Lasse Öörni 15 years ago
parent
commit
c3acff9a2d

+ 3 - 3
Bin/Data/TestLevel.xml

@@ -4,7 +4,7 @@
         <linear restthreshold="0.1" dampingthreshold="0" dampingscale="0.001" />
     </physics>
     <interpolation predictiontime="2" constant="50" snapthreshold="200" />
-    <entity id="65536" name="Zone" netflags="0" netdistance="0">
+    <entity id="65536" name="Zone" netflags="0" netdistance="0" groupflags="0">
         <component type="Zone" netflags="0">
             <transform pos="0 0 0" rot="1 0 0 0" scale="1 1 1" />
             <render castshadows="false" occluder="false" visible="true" />
@@ -32,7 +32,7 @@
             <material index="0" name="Materials/CloudPlane.xml" />
         </component>
     </entity>
-    <entity id="65537" name="Static" netflags="0" netdistance="0">
+    <entity id="65537" name="Static" netflags="0" netdistance="0" groupflags="0">
         <component type="StaticModel" netflags="0">
             <transform pos="0 0 0" rot="1 0 0 0" scale="1 1 1" />
             <parent id="65537" type="RigidBody" />
@@ -43,7 +43,7 @@
         </component>
         <component type="RigidBody" netflags="0">
             <transform pos="0 0 0" rot="1 0 0 0" scale="1 1 1" />
-            <body mode="0" mass="1.0" friction="0.5" bounce="0" active="false" />
+            <body mode="static" mass="1.0" friction="0.5" bounce="0" active="false" />
             <collision shape="Physics/Level.xml" group="2" mask="3" />
         </component>
     </entity>

+ 1 - 0
Engine/Engine/Client.cpp

@@ -977,6 +977,7 @@ void Client::readNetUpdateBlock(Deserializer& source, unsigned char msgID, const
                 entity->setOwner(mServerConnection);
             else
                 entity->setOwner(0);
+            entity->setGroupFlags(source.readVLE());
             
             entity->setProperties(source.readVariantMap(), true);
             

+ 9 - 0
Engine/Engine/RegisterScene.cpp

@@ -220,6 +220,7 @@ static void registerEntity(asIScriptEngine* engine)
     engine->RegisterObjectBehaviour("Entity", asBEHAVE_RELEASE, "void f()", asMETHOD(Entity, releaseRef), asCALL_THISCALL);
     engine->RegisterObjectMethod("Entity", "void setName(const string& in)", asMETHOD(Entity, setName), asCALL_THISCALL);
     engine->RegisterObjectMethod("Entity", "void setNetFlags(uint8)", asMETHOD(Entity, setNetFlags), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Entity", "void setGroupFlags(uint)", asMETHOD(Entity, setGroupFlags), asCALL_THISCALL);
     engine->RegisterObjectMethod("Entity", "void setProperty(const string& in, const Variant& in)", asFUNCTION(EntitySetProperty), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Entity", "void setProperty(const string& in, const Variant& in, bool)", asFUNCTION(EntitySetPropertyWithSync), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Entity", "void setPropertySync(const string& in, bool)", asFUNCTION(EntitySetPropertySync), asCALL_CDECL_OBJLAST);
@@ -238,6 +239,7 @@ static void registerEntity(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Entity", "bool isLocal() const", asMETHOD(Entity, isLocal), asCALL_THISCALL);
     engine->RegisterObjectMethod("Entity", "const string& getName() const", asMETHOD(Entity, getName), asCALL_THISCALL);
     engine->RegisterObjectMethod("Entity", "uint8 getNetFlags() const", asMETHOD(Entity, getNetFlags), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Entity", "uint getGroupFlags() const", asMETHOD(Entity, getGroupFlags), asCALL_THISCALL);
     engine->RegisterObjectMethod("Entity", "Scene@+ getScene() const", asMETHOD(Entity, getScene), asCALL_THISCALL);
     engine->RegisterObjectMethod("Entity", "const Variant& getProperty(const string& in)", asFUNCTION(EntityGetProperty), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Entity", "bool getPropertySync(const string& in)", asFUNCTION(EntityGetPropertySync), asCALL_CDECL_OBJLAST);
@@ -401,6 +403,12 @@ static CScriptArray* SceneGetEntities(Scene* ptr)
     return vectorToHandleArray<Entity>(result, "array<Entity@>");
 }
 
+static CScriptArray* SceneGetEntitiesWithFlags(unsigned includeFlags, unsigned excludeFlags, Scene* ptr)
+{
+    std::vector<Entity*> result = ptr->getEntities(includeFlags, excludeFlags);
+    return vectorToHandleArray<Entity>(result, "array<Entity@>");
+}
+
 static CScriptArray* SceneGetScriptedEntities(Scene* ptr)
 {
     const std::map<EntityID, SharedPtr<Entity> >& entities = ptr->getEntities();
@@ -466,6 +474,7 @@ static void registerScene(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Scene", "Entity@+ getEntity(const string& in) const", asMETHODPR(Scene, getEntity, (const std::string&) const, Entity*), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "uint getNumEntities() const", asMETHOD(Scene, getNumEntities), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "array<Entity@>@ getEntities() const", asFUNCTION(SceneGetEntities), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Scene", "array<Entity@>@ getEntities(uint, uint) const", asFUNCTION(SceneGetEntitiesWithFlags), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Scene", "array<Entity@>@ getScriptedEntities() const", asFUNCTION(SceneGetScriptedEntities), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Scene", "array<Entity@>@ getScriptedEntities(const string& in) const", asFUNCTION(SceneGetScriptedEntitiesWithClass), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Scene", "Vector3 getEntityPosition(Entity@+) const", asMETHOD(Scene, getEntityPosition), asCALL_THISCALL);

+ 3 - 2
Engine/Engine/Server.cpp

@@ -897,6 +897,7 @@ void Server::writeNetUpdate(Connection* connection, Serializer& dest)
                 dest.writeUShort(entity->getID());
                 dest.writeString(entity->getName());
                 dest.writeUByte(getClientNetFlags(connection, entity, entity->getNetFlags()));
+                dest.writeVLE(entity->getGroupFlags());
                 
                 // Write a full update of entity properties
                 newRevision.seek(0);
@@ -1058,8 +1059,8 @@ void Server::writeNetUpdate(Connection* connection, Serializer& dest)
 
 void Server::getRelevantEntities(Connection* connection, std::set<EntityID>& dest) const
 {
-    // Here we just generate the raw set of relevant entities based on their owner, distance and references. An entity might
-    // need to stay relevant because it has unacked changes, or has time left in its relevancy timer, but that is checked in
+    // Generate just the raw set of relevant entities based on their owner, distance and references. An entity might need
+    // to stay relevant because it has unacked changes, or has time left in its relevancy timer, but that is checked in
     // writeNetUpdate()
     PROFILE(Server_GetRelevantEntities);
     

+ 2 - 1
Engine/Input/Input.cpp

@@ -44,7 +44,8 @@ Input::Input(Renderer* renderer) :
     
     makeActive();
     
-    subscribeToEvent(mRenderer, EVENT_WINDOWMESSAGE, EVENT_HANDLER(Input, handleWindowMessage));
+    if (mRenderer)
+        subscribeToEvent(mRenderer, EVENT_WINDOWMESSAGE, EVENT_HANDLER(Input, handleWindowMessage));
 }
 
 Input::~Input()

+ 6 - 14
Engine/Scene/Component.cpp

@@ -39,38 +39,30 @@ Component::Component(const std::string& name) :
 
 void Component::save(Serializer& dest)
 {
-    // Write type hash & name
+    // Write identification and netflags
     dest.writeShortStringHash(getType());
     dest.writeString(mName);
-    
-    // Write netflags
     dest.writeUByte(mNetFlags);
 }
 
 void Component::load(Deserializer& source, ResourceCache* cache)
 {
-    // Type and name are handled on the Entity level
-    
-    // Read netflags
+    // Entity reads the identification, so do not read here
     mNetFlags = source.readUByte();
 }
 
 void Component::saveXML(XMLElement& dest)
 {
-    // Write typename & name
+    // Write identification and netflags
     dest.setString("type", getTypeName());
     if (!mName.empty())
         dest.setString("name", mName);
-    
-    // Write netflags
     dest.setInt("netflags", mNetFlags);
 }
 
 void Component::loadXML(const XMLElement& source, ResourceCache* cache)
 {
-    // Type and name are handled on the Entity level
-    
-    // Read netflags
+    // Entity reads the identification, so do not read here
     mNetFlags = source.getInt("netflags");
 }
 
@@ -160,8 +152,8 @@ ComponentRef::ComponentRef(Component* component, bool forXML) :
     }
     else
     {
-        // The component does not directly belong to an entity. However, if it is a scene node, check if any of the components
-        // in the parent chain belongs to an entity
+        // The component does not directly belong to an entity. However, if it is a scene node,
+        // check if any of the components in the parent chain belongs to an entity, and use its ID in that case
         Node* node = dynamic_cast<Node*>(component);
         while (node)
         {

+ 16 - 13
Engine/Scene/Entity.cpp

@@ -33,6 +33,7 @@ Entity::Entity(EntityID id, const std::string& name) :
     mName(name),
     mNameHash(name),
     mNetFlags(NET_SYNCTOALL),
+    mGroupFlags(0),
     mScene(0),
     mOwner(0),
     mNextComponentName(0x30),
@@ -55,7 +56,8 @@ void Entity::onEvent(EventListener* sender, StringHash eventType, VariantMap& ev
     {
         // Do not check if the component actually subscribes to the event, because its onEvent() does that check
         mEventListeners[i]->onEvent(sender, eventType, eventData);
-        // Exit if entity was removed as a response to the event
+        
+        // Exit immediately if entity was removed as a response to the event
         if (self.isExpired())
             return;
     }
@@ -63,13 +65,12 @@ void Entity::onEvent(EventListener* sender, StringHash eventType, VariantMap& ev
 
 void Entity::save(Serializer& dest)
 {
-    // Write ID & name
+    // Write identification and flags
     dest.writeUInt(mID);
     dest.writeString(mName);
-    
-    // Write netflags and update distance
     dest.writeUByte(mNetFlags);
     dest.writeFloat(mNetUpdateDistance);
+    dest.writeUInt(mGroupFlags);
     
     // Write properties
     dest.writeVLE(mProperties.size());
@@ -88,14 +89,13 @@ void Entity::save(Serializer& dest)
 
 void Entity::load(Deserializer& source, ResourceCache* cache)
 {
-    // ID and name are handled at the Scene level
-    
     // Load should only be called for new entities, but remove components just to be sure
     removeAllComponents();
     
-    // Read netflags and update distance
+    // Scene reads the identification, so do not read here
     mNetFlags = source.readUByte();
     mNetUpdateDistance = source.readFloat();
+    mGroupFlags = source.readUInt();
     
     // Read properties
     mProperties.clear();
@@ -122,14 +122,13 @@ void Entity::load(Deserializer& source, ResourceCache* cache)
 
 void Entity::saveXML(XMLElement& dest)
 {
-    // Write ID & name
+    // Write identification and flags
     dest.setInt("id", mID);
     if (!mName.empty())
         dest.setString("name", mName);
-    
-    // Write netflags & netupdate distance
     dest.setInt("netflags", mNetFlags);
     dest.setFloat("netdistance", mNetUpdateDistance);
+    dest.setInt("groupflags", mGroupFlags);
     
     // Write properties
     for (PropertyMap::const_iterator i = mProperties.begin(); i != mProperties.end(); ++i)
@@ -155,14 +154,13 @@ void Entity::saveXML(XMLElement& dest)
 
 void Entity::loadXML(const XMLElement& source, ResourceCache* cache)
 {
-    // ID and name are handled at the Scene level
-    
     // Load should only be called for new entities, but remove components just to be sure
     removeAllComponents();
     
-    // Read netflags
+    // Scene reads the identification, so do not read here
     mNetFlags = source.getInt("netflags");
     mNetUpdateDistance = source.getFloat("netdistance");
+    mGroupFlags = source.getInt("groupflags");
     
     // Read properties
     mProperties.clear();
@@ -295,6 +293,11 @@ void Entity::setNetFlags(unsigned char flags)
         mNetFlags = flags;
 }
 
+void Entity::setGroupFlags(unsigned flags)
+{
+    mGroupFlags = flags;
+}
+
 void Entity::setOwner(Connection* owner)
 {
     if (mID >= LOCAL_ENTITY)

+ 6 - 0
Engine/Scene/Entity.h

@@ -91,6 +91,8 @@ public:
     void getResourceRefs(std::vector<Resource*>& dest);
     //! Set name
     void setName(const std::string& name);
+   //! Set group flags
+    void setGroupFlags(unsigned flags);
     //! Set network replication flags
     void setNetFlags(unsigned char flags);
     //! Set network owner
@@ -144,6 +146,8 @@ public:
     const std::string& getName() const { return mName; }
     //! Return name hash
     StringHash getNameHash() const { return mNameHash; }
+    //! Return group flags
+    unsigned getGroupFlags() const { return mGroupFlags; }
     //! Return network replication flags
     unsigned char getNetFlags() const { return mNetFlags; }
     //! Return scene
@@ -244,6 +248,8 @@ private:
     StringHash mNameHash;
     //! Network replication flags
     unsigned char mNetFlags;
+    //! Group flags
+    unsigned mGroupFlags;
     //! Scene
     Scene* mScene;
     //! Network owner

+ 14 - 0
Engine/Scene/Scene.cpp

@@ -871,6 +871,20 @@ Entity* Scene::getEntity(StringHash nameHash) const
     return 0;
 }
 
+std::vector<Entity*> Scene::getEntities(unsigned includeFlags, unsigned excludeFlags) const
+{
+    std::vector<Entity*> ret;
+    
+    for (std::map<EntityID, SharedPtr<Entity> >::const_iterator i = mEntities.begin(); i != mEntities.end(); ++i)
+    {
+        unsigned flags = i->second->getGroupFlags();
+        if ((flags & includeFlags) && (!(flags & excludeFlags)))
+            ret.push_back(i->second);
+    }
+    
+    return ret;
+}
+
 Component* Scene::getComponent(const ComponentRef& ref) const
 {
     if (!ref.mEntityID)

+ 2 - 0
Engine/Scene/Scene.h

@@ -161,6 +161,8 @@ public:
     unsigned getNumEntities() const { return mEntities.size(); }
     //! Return all entities
     const std::map<EntityID, SharedPtr<Entity> >& getEntities() const { return mEntities; }
+    //! Return entities by group flags
+    std::vector<Entity*> getEntities(unsigned includeFlags, unsigned excludeFlags) const;
     //! Return a component by component reference, or null if not found
     Component* getComponent(const ComponentRef& ref) const;
     //! Return entity position by going through scene node components it has (RigidBody is preferred)

+ 0 - 1
Engine/UI/Menu.cpp

@@ -173,4 +173,3 @@ void Menu::handleTryFocus(StringHash eventType, VariantMap& eventData)
     
     showPopup(false);
 }
-