NLS Engine  v0.1
The Next Logical Step in game engine design.
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Defines
RenderModuleComponents.cpp
Go to the documentation of this file.
00001 
00012 #include <boost/function.hpp>
00013 
00014 #include "RenderModule.h"
00015 #include "../sharedbase/EventLogger.h"
00016 #include "../sharedbase/Entity.h"
00017 
00018 #include "component/RenderableComponent.h"
00019 #include "component/CameraComponent.h"
00020 #include "component/renderable/HeightmapRenderable.h"
00021 #include "component/renderable/LightAmbientRenderable.h"
00022 #include "component/renderable/LightDirectionalRenderable.h"
00023 #include "component/renderable/LightPointRenderable.h"
00024 #include "component/renderable/ModelRenderable.h"
00025 #include "component/renderable/RenderableHelicalTube.h"
00026 #include "component/renderable/CubeRenderable.h"
00027 #include "component/renderable/TiledMap.h"
00028 #include "component/renderable/PointLine.h"
00029 #include "component/renderable/Quad.h"
00030 
00031 #include "Components.h"
00032 #include "component/renderable/Sprite.h"
00033 #include "component/renderable/D3DFont.h"
00034 
00035 namespace GraphicsCore {
00036   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00040   template<typename T>
00041   inline void getAttribute(const std::string type, std::map<std::string, boost::any> &attributes, const std::string key, boost::function<bool(T)> setter) {
00042     bool status = false;
00043     
00044     if (attributes.count(key) > 0) {
00045       try {
00046         status = setter(boost::any_cast < T > (attributes[key]));
00047       }
00048       catch (const boost::bad_any_cast &) {
00049         LOG(LOG_PRIORITY::INFO, type + " " + key + " set with invalid data type.");
00050       }
00051       
00052       if (!status) {
00053         LOG(LOG_PRIORITY::INFO, "Setter for " +  type + " " + key + " failed to set. (returned false)");
00054       }
00055     }
00056   }
00057 
00058   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00062   template<typename T>
00063   inline std::pair<bool, T> getAttributeAlt(const std::string type, std::map<std::string, boost::any> &attributes, const std::string key) {
00064     bool status = false;
00065     T result;
00066     if (attributes.count(key) > 0) {
00067       try {
00068         result = boost::any_cast < T > (attributes[key]);
00069         status = true;
00070       }
00071       catch (const boost::bad_any_cast &) {
00072         LOG(LOG_PRIORITY::INFO, type + " " + key + " set with invalid data type.");
00073       }
00074     }
00075     return std::pair<bool, T>(status, result);
00076   }
00077 
00078   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00079   // Called to create a component of type (type), with the set of attributes (attributes), and with parent entity (e)
00080   void RenderModule::CreateComponent(std::string type, std::map<std::string, boost::any> &attributes, EntitySPTR ent) {
00081     EntitySPTR entity(ent);
00082     
00083     if (type == CAMERA && attributes.count(CAMERA__NAME)) {
00084       CameraComponent* cam = new CameraComponent(entity, this);
00085       
00086       getAttribute < CAMERA__FOV_TYPE > (
00087           type, attributes, CAMERA__FOV, std::bind1st(std::mem_fun(&CameraComponent::SetFov), cam)
00088           );
00089       
00090       // Have to use the less-easy method for this, as it doesn'tuse a singular setter.
00091       if (attributes.count(CAMERA__NEAR_CLIP)) {
00092         bool status = false;
00093         std::pair<bool, CAMERA__NEAR_CLIP_TYPE> data;
00094         
00095         if ((data = getAttributeAlt < CAMERA__NEAR_CLIP_TYPE > (type, attributes, CAMERA__NEAR_CLIP)).first) {
00096           status = cam->SetClipRanges(data.second, cam->GetFarClipRange());
00097         }
00098         
00099         if (!status) {
00100           std::string errMsg("Setter for ");
00101           LOG(LOG_PRIORITY::ERR, errMsg.append(type).append(" ").append(CAMERA__NEAR_CLIP).append(" failed to set. (returned false)"));
00102         }
00103       }
00104 
00105       // Have to use the less-easy method for this, as it doesn'tuse a singular setter.
00106       if (attributes.count(CAMERA__FAR_CLIP)) {
00107         bool status = false;
00108         std::pair<bool, CAMERA__FAR_CLIP_TYPE> data;
00109         
00110         if ((data = getAttributeAlt < CAMERA__FAR_CLIP_TYPE > (type, attributes, CAMERA__FAR_CLIP)).first) {
00111           status = cam->SetClipRanges(cam->GetNearClipRange(), data.second);
00112         }
00113         
00114         if (!status) {
00115           std::string errMsg("Setter for ");
00116           LOG(LOG_PRIORITY::ERR, errMsg.append(type).append(" ").append(CAMERA__NEAR_CLIP).append(" failed to set. (returned false)"));
00117         }
00118       }
00119 
00120       getAttribute < CAMERA__OFFSET_TYPE > (
00121           type, attributes, CAMERA__OFFSET, std::bind1st(std::mem_fun(&CameraComponent::SetOffset), cam)
00122           );
00123       
00124       getAttribute < CAMERA__ROTATION_TYPE > (
00125           type, attributes, CAMERA__ROTATION, std::bind1st(std::mem_fun(&CameraComponent::SetRotation), cam)
00126           );
00127       
00128       std::string camera_name("");
00129       try {
00130         camera_name = boost::any_cast < std::string > (attributes[CAMERA__NAME]);
00131       }
00132       catch (const boost::bad_any_cast &) {
00133         std::string errStr("Invalid data type sent for Camera creation.  Camera name was '");
00134         errStr.append(CAMERA__NAME).append("'.");
00135         LOG(LOG_PRIORITY::ERR, errStr);
00136       }
00137       
00138       Threading::UpgradeLock up_lock(this->cameraComponentsMutex);
00139       
00140       cameramap::left_const_iterator cam_it = this->cameraComponents.left.find(camera_name);
00141       
00142       if (camera_name.length() >= 0 && cam_it == this->cameraComponents.left.end()) {
00143         {
00144           Threading::UpgradeToUniqueLock unique_lock(up_lock);
00145           
00146           this->cameraComponents.insert(namedcamera(camera_name, cam));
00147         }
00148         // Register the first created camera as the active camera
00149         if (this->cameraComponents.size() <= 1) {
00150           this->SetCurrentCamera(camera_name);
00151         }
00152       }
00153       else {
00154         std::string errStr("Invalid name sent for Camera creation.  Camera name was '");
00155         errStr.append(CAMERA__NAME).append("' and was either already in-use or blank.");
00156         LOG(LOG_PRIORITY::ERR, errStr);
00157       }
00158     }
00159     else if (type == LIGHT_AMBIENT) {
00160       LightAmbientRenderable* light = new LightAmbientRenderable(entity, this);
00161       
00162       // Pull in color information from attributes
00163       getAttribute < LIGHT__AMBIENT_COLOR_TYPE > (
00164           type, attributes, LIGHT__AMBIENT_COLOR, std::bind1st(std::mem_fun(&LightAmbientRenderable::SetAmbientColor), light)
00165           );
00166       
00167       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00168       
00169       this->myRenderableComponents.insert(light);
00170     }
00171     else if (type == LIGHT_DIRECTIONAL) {
00172       LightDirectionalRenderable* light = new LightDirectionalRenderable(entity, this);
00173       
00174       // Pull in color information and range from attributes
00175       getAttribute < LIGHT__AMBIENT_COLOR_TYPE > (
00176           type, attributes, LIGHT__AMBIENT_COLOR, std::bind1st(std::mem_fun(&LightDirectionalRenderable::SetAmbientColor), light)
00177           );
00178       
00179       getAttribute < LIGHT__DIFFUSE_COLOR_TYPE > (
00180           type, attributes, LIGHT__DIFFUSE_COLOR, std::bind1st(std::mem_fun(&LightDirectionalRenderable::SetDiffuseColor), light)
00181           );
00182       
00183       getAttribute < LIGHT__SPECULAR_COLOR_TYPE > (
00184           type, attributes, LIGHT__SPECULAR_COLOR, std::bind1st(std::mem_fun(&LightDirectionalRenderable::SetSpecularColor), light)
00185           );
00186       
00187       getAttribute < LIGHT__RANGE_TYPE > (
00188           type, attributes, LIGHT__RANGE, std::bind1st(std::mem_fun(&LightDirectionalRenderable::SetRange), light)
00189           );
00190       
00191       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00192       
00193       this->myRenderableComponents.insert(light);
00194     }
00195     else if (type == LIGHT_POINT) {
00196       LightPointRenderable* light = new LightPointRenderable(entity, this);
00197       
00198       // Pull in color information and range from attributes
00199       getAttribute < LIGHT__AMBIENT_COLOR_TYPE > (
00200           type, attributes, LIGHT__AMBIENT_COLOR, std::bind1st(std::mem_fun(&LightPointRenderable::SetAmbientColor), light)
00201           );
00202       
00203       getAttribute < LIGHT__DIFFUSE_COLOR_TYPE > (
00204           type, attributes, LIGHT__DIFFUSE_COLOR, std::bind1st(std::mem_fun(&LightPointRenderable::SetDiffuseColor), light)
00205           );
00206       
00207       getAttribute < LIGHT__SPECULAR_COLOR_TYPE > (
00208           type, attributes, LIGHT__SPECULAR_COLOR, std::bind1st(std::mem_fun(&LightPointRenderable::SetSpecularColor), light)
00209           );
00210       
00211       getAttribute < LIGHT__RANGE_TYPE > (
00212           type, attributes, LIGHT__RANGE, std::bind1st(std::mem_fun(&LightPointRenderable::SetRange), light)
00213           );
00214       
00215       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00216       
00217       this->myRenderableComponents.insert(light);
00218     }
00219     else if (type == HEIGHTMAP) {
00220       HeightmapRenderable* heightmap = new HeightmapRenderable(entity, this, pd3dDevice);
00221       
00222       // Pull in terrain heightmap and texture from attributes
00223       getAttribute < HEIGHTMAP__FILE_TYPE > (
00224           type, attributes, HEIGHTMAP__FILE, boost::bind(&HeightmapRenderable::LoadHeightmapFromFile, boost::ref(heightmap), _1)
00225           );
00226       
00227       getAttribute < HEIGHTMAP__TEXTURE_FILE_TYPE > (
00228           type, attributes, HEIGHTMAP__TEXTURE_FILE, boost::bind(&HeightmapRenderable::LoadTextureFromFile, boost::ref(heightmap), _1)
00229           );
00230       
00231       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00232       
00233       this->myRenderableComponents.insert(heightmap);
00234     }
00235     else if (type == MESH) {
00236       ModelComponent* model = new ModelComponent(entity, this);
00237       
00238       // Pull in the mesh file
00239       getAttribute < MESH__FILE_TYPE > (
00240           type, attributes, MESH__FILE, boost::bind(&ModelComponent::LoadMeshFromFile, boost::ref(model), _1)
00241           );
00242       
00243       getAttribute < RENDER__SPACE_TYPE > (
00244           type, attributes, RENDER__SPACE, boost::bind(&ModelComponent::SetCoordSpace, boost::ref(model), _1)
00245           );
00246       
00247       // Go fetch any incoming materials
00248       {
00249         std::pair<bool, MATERIALS__DATA_TYPE> data;
00250         if ((data = getAttributeAlt < MATERIALS__DATA_TYPE > (type, attributes, MATERIALS__DATA)).first) {
00251           if (!this->CreateMaterial(data.second, model)) {
00252             LOG(LOG_PRIORITY::INFO, type + " " + MATERIALS__DATA + " set with invalid data type.");
00253           }
00254         }
00255       }
00256       
00257       // Go fetch any incoming textures
00258       {
00259         std::pair<bool, TEXTURES__DATA_TYPE> data;
00260         if ((data = getAttributeAlt < TEXTURES__DATA_TYPE > (type, attributes, TEXTURES__DATA)).first) {
00261           if (!this->CreateTexture(data.second, model)) {
00262             LOG(LOG_PRIORITY::INFO, type + " " + TEXTURES__DATA + " set with invalid data type.");
00263           }
00264         }
00265       }
00266       
00267       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00268       
00269       this->myRenderableComponents.insert(model);
00270     }
00271     else if (type == HELICAL_TUBE) {
00272       RenderableHelicalTube* model = new RenderableHelicalTube(entity, this, pd3dDevice);
00273       
00274       // Loadup the attributes
00275       getAttribute < HELICAL_TUBE__RADIUS_TYPE > (
00276           type, attributes, HELICAL_TUBE__RADIUS, std::bind1st(std::mem_fun(&RenderableHelicalTube::SetRadius), model)
00277           );
00278       
00279       getAttribute < HELICAL_TUBE__LENGTH_TYPE > (
00280           type, attributes, HELICAL_TUBE__LENGTH, std::bind1st(std::mem_fun(&RenderableHelicalTube::SetLength), model)
00281           );
00282       
00283       getAttribute < HELICAL_TUBE__PITCH_TYPE > (
00284           type, attributes, HELICAL_TUBE__PITCH, std::bind1st(std::mem_fun(&RenderableHelicalTube::SetPitch), model)
00285           );
00286       
00287       getAttribute < HELICAL_TUBE__SEGMENTS_TYPE > (
00288           type, attributes, HELICAL_TUBE__SEGMENTS, std::bind1st(std::mem_fun(&RenderableHelicalTube::SetSegmentCount), model)
00289           );
00290       
00291       // Go fetch any incoming materials
00292       {
00293         std::pair<bool, MATERIALS__DATA_TYPE> data;
00294         if ((data = getAttributeAlt < MATERIALS__DATA_TYPE > (type, attributes, MATERIALS__DATA)).first) {
00295           if (!this->CreateMaterial(data.second, model)) {
00296             LOG(LOG_PRIORITY::INFO, type + " " + MATERIALS__DATA + " set with invalid data type.");
00297           }
00298         }
00299       }
00300       
00301       // Go fetch any incoming textures
00302       {
00303         std::pair<bool, TEXTURES__DATA_TYPE> data;
00304         if ((data = getAttributeAlt < TEXTURES__DATA_TYPE > (type, attributes, TEXTURES__DATA)).first) {
00305           if (!this->CreateTexture(data.second, model)) {
00306             LOG(LOG_PRIORITY::INFO, type + " " + TEXTURES__DATA + " set with invalid data type.");
00307           }
00308         }
00309       }
00310       
00311       model->UpdateGeometry();
00312       
00313       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00314       
00315       this->myRenderableComponents.insert(model);
00316     }
00317     else if (type == TILED_MAP) {
00318       TiledMap* tmap = new TiledMap(entity, this, pd3dDevice);
00319 
00320       getAttribute < EnvelopeSPTR > (
00321         type, attributes, "mapdata", std::bind1st(std::mem_fun(&TiledMap::LoadMapData), tmap)
00322         );
00323 
00324       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00325       
00326       this->myRenderableComponents.insert(tmap);
00327     }
00328     else if (type == POINTLINE) {
00329       PointLine* pline = new PointLine(entity, this, pd3dDevice);
00330       
00331       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00332       
00333       this->myRenderableComponents.insert(pline);
00334     }
00335     else if (type == SPRITE) {
00336       Sprite* spr = new Sprite(entity, this, pd3dDevice);
00337 
00338       spr->SetSpriteParams(
00339           boost::any_cast<float>(attributes["offsetX"]),
00340           boost::any_cast<float>(attributes["offsetY"]),
00341           boost::any_cast<std::string>(attributes["texfilename"]),
00342           boost::any_cast<unsigned int>(attributes["srcX"]),
00343           boost::any_cast<unsigned int>(attributes["srcY"]),
00344           boost::any_cast<unsigned int>(attributes["width"]),
00345           boost::any_cast<unsigned int>(attributes["height"])
00346         );
00347 
00348       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00349       
00350       this->myRenderableComponents.insert(spr);
00351     }
00352     else if (type == D3DFONT) {
00353       D3DFont* font = new D3DFont(entity, this, pd3dDevice, this->msgrouter, boost::any_cast<unsigned int>(attributes["width"]), boost::any_cast<unsigned int>(attributes["height"]), boost::any_cast<unsigned int>(attributes["weight"]),  boost::any_cast<bool>(attributes["italic"]));
00354       font->SetDialogRect(boost::any_cast<unsigned int>(attributes["rectX"]), boost::any_cast<unsigned int>(attributes["rectY"]), boost::any_cast<unsigned int>(attributes["rectW"]), boost::any_cast<unsigned int>(attributes["rectH"]));
00355 
00356       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00357 
00358       this->myRenderableComponents.insert(font);
00359     }
00360     else if (type == QUAD) {
00361       Quad* model = new Quad(entity, this, pd3dDevice);
00362       
00363       getAttribute < RENDER__SPACE_TYPE > (
00364           type, attributes, RENDER__SPACE, std::bind1st(std::mem_fun(&Quad::SetCoordSpace), model)
00365           );
00366       
00367       getAttribute < QUAD__WIDTH_TYPE > (
00368           type, attributes, QUAD__WIDTH, std::bind1st(std::mem_fun(&Quad::SetWidth), model)
00369           );
00370       
00371       getAttribute < QUAD__HEIGHT_TYPE > (
00372           type, attributes, QUAD__HEIGHT, std::bind1st(std::mem_fun(&Quad::SetHeight), model)
00373           );
00374       
00375       // *HACK: As there is no nice method for attaching the component's enums to script, I'm implementing a uint to enum converter that will be a simple stopgap.
00376       if (attributes.count(QUAD__ORIGIN)) {
00377         bool status = false;
00378         std::pair<bool, QUAD__ORIGIN_TYPE> data;
00379         
00380         if ((data = getAttributeAlt < QUAD__ORIGIN_TYPE > (type, attributes, QUAD__ORIGIN)).first) {
00381           switch (data.second) {
00382             case 1:
00383               status = model->SetOrigin(ORIGIN::UPPER_LEFT);
00384             break;
00385             case 2:
00386               status = model->SetOrigin(ORIGIN::CENTER);
00387             break;
00388             default:
00389               LOG(LOG_PRIORITY::ERR, "Setter for " + type + " " + QUAD__ORIGIN + " was not called: Invalid value " + boost::lexical_cast<std::string>(data.second) + " was passed.  Valid values are: 1 = upper-left, 2 = center.");
00390             break;
00391           }
00392           
00393         }
00394         
00395         if (!status) {
00396           LOG(LOG_PRIORITY::ERR, "Setter for " + type + " " + QUAD__ORIGIN + " failed to set. (returned false)");
00397         }
00398       }
00399       
00400       // *HACK: As there is no nice method for attaching the component's enums to script, I'm implementing a uint to enum converter that will be a simple stopgap.
00401       if (attributes.count(QUAD__ORIENT)) {
00402         bool status = false;
00403         std::pair<bool, QUAD__ORIENT_TYPE> data;
00404         
00405         if ((data = getAttributeAlt < QUAD__ORIENT_TYPE > (type, attributes, QUAD__ORIENT)).first) {
00406           switch (data.second) {
00407             case 1:
00408               status = model->SetOrientation(ORIENTATION::WORLD);
00409             break;
00410             case 2:
00411               status = model->SetOrientation(ORIENTATION::CAMERA);
00412             break;
00413             default:
00414               LOG(LOG_PRIORITY::ERR, "Setter for " + type + " " + QUAD__ORIENT + " was not called: Invalid value " + boost::lexical_cast<std::string>(data.second) + " was passed.  Valid values are: 1 = world, 2 = face camera.");
00415             break;
00416           }
00417           
00418         }
00419         
00420         if (!status) {
00421           LOG(LOG_PRIORITY::ERR, "Setter for " + type + " " + QUAD__ORIENT + " failed to set. (returned false)");
00422         }
00423       }
00424       
00425       // Go fetch any incoming materials
00426       {
00427         std::pair<bool, MATERIALS__DATA_TYPE> data;
00428         if ((data = getAttributeAlt < MATERIALS__DATA_TYPE > (type, attributes, MATERIALS__DATA)).first) {
00429           if (!this->CreateMaterial(data.second, model)) {
00430             LOG(LOG_PRIORITY::WARN, type + " " + MATERIALS__DATA + " set with invalid data type.");
00431           }
00432         }
00433       }
00434       
00435       // Go fetch any incoming textures
00436       {
00437         std::pair<bool, TEXTURES__DATA_TYPE> data;
00438         if ((data = getAttributeAlt < TEXTURES__DATA_TYPE > (type, attributes, TEXTURES__DATA)).first) {
00439           if (!this->CreateTexture(data.second, model)) {
00440             LOG(LOG_PRIORITY::WARN, type + " " + TEXTURES__DATA + " set with invalid data type.");
00441           }
00442         }
00443       }
00444       
00445       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00446       
00447       this->myRenderableComponents.insert(model);
00448     }
00449     else if (type == "Cube") {
00450       CubeRenderable* model = new CubeRenderable(entity, this, pd3dDevice);
00451       
00452       getAttribute < RENDER__SPACE_TYPE > (
00453           type, attributes, RENDER__SPACE, std::bind1st(std::mem_fun(&CubeRenderable::SetCoordSpace), model)
00454           );
00455       
00456       // Go fetch any incoming materials
00457       {
00458         std::pair<bool, MATERIALS__DATA_TYPE> data;
00459         if ((data = getAttributeAlt < MATERIALS__DATA_TYPE > (type, attributes, MATERIALS__DATA)).first) {
00460           if (!this->CreateMaterial(data.second, model)) {
00461             LOG(LOG_PRIORITY::INFO, type + " " + MATERIALS__DATA + " set with invalid data type.");
00462           }
00463         }
00464       }
00465       
00466       Threading::WriteLock w_lock(this->myRenderableComponentsMutex);
00467       
00468       this->myRenderableComponents.insert(model);
00469     }
00470   }
00471   
00472   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00473   WHO_DELETES::TYPE RenderModule::RemoveComponent(ComponentInterface* component) {
00474     // Determine if this is a camera and remove it from this->cameraComponents.
00475     {
00476       CameraComponent* camera = static_cast<CameraComponent*>(component);
00477       
00478       Threading::UpgradeLock up_lock(this->cameraComponentsMutex);
00479       
00480       cameramap::right_const_iterator it = this->cameraComponents.right.find(camera);
00481       if (it != this->cameraComponents.right.end()) {
00482         {
00483           Threading::UpgradeToUniqueLock unique_lock(up_lock);
00484           this->cameraComponents.right.erase(camera);
00485         }
00486         
00487         Threading::UpgradeLock cam_up_lock(this->currentCameraMutex);
00488         if (this->currentCamera == camera) {
00489           Threading::UpgradeToUniqueLock unique_lock(cam_up_lock);
00490           this->currentCamera = nullptr;
00491         }
00492         
00493         return WHO_DELETES::CALLER; // upstream delete
00494       }
00495     }
00496     
00497     // Determine if this is a RenderableComponent and remove it from the lists.
00498     {
00499       RenderableComponent* renderable = static_cast<RenderableComponent*>(component);
00500       
00501       {
00502         Threading::UpgradeLock up_lock(this->renderableComponentsMutex);
00503         
00504         std::set<RenderableComponent*>::iterator it = this->renderableComponents.find(renderable);
00505         if (it != this->renderableComponents.end()) {
00506           Threading::UpgradeToUniqueLock unique_lock(up_lock);
00507           this->renderableComponents.erase(it);
00508         }
00509       }
00510       
00511       {
00512         Threading::UpgradeLock up_lock(this->myRenderableComponentsMutex);
00513         
00514         std::set<RenderableComponent*>::iterator it_mine = this->myRenderableComponents.find(renderable);
00515         if (it_mine != this->myRenderableComponents.end()) {
00516           Threading::UpgradeToUniqueLock unique_lock(up_lock);
00517           this->myRenderableComponents.erase(it_mine);
00518           
00519           return WHO_DELETES::CALLER; // upstream delete
00520         }
00521       }
00522       
00523       return WHO_DELETES::CALLEE; // no delete needed
00524     }
00525   }
00526 }