kick
/Users/morten/Programmering/cpp/kick/src/kick/scene/scene.cpp
00001 //
00002 //  Scene.cpp
00003 //  KickCPP
00004 //
00005 //  Created by Morten Nobel-Jørgensen on 5/21/13.
00006 //  Copyright (c) 2013 Morten Nobel-Joergensen. All rights reserved.
00007 //
00008 
00009 #include "kick/scene/scene.h"
00010 #include <iostream>
00011 #include <algorithm>
00012 #include "rapidjson/rapidjson.h"
00013 #include "rapidjson/writer.h"
00014 #include "kick/scene/engine_uniforms.h"
00015 #include "kick/scene/camera.h"
00016 #include "updatable.h"
00017 #include "kick/scene/camera_orthographic.h"
00018 #include "kick/scene/camera_perspective.h"
00019 #include "kick/scene/mesh_renderer.h"
00020 #include "kick/mesh/mesh_factory.h"
00021 #include "kick/mesh/mesh.h"
00022 #include "kick/core/engine.h"
00023 #include "kick/scene/light.h"
00024 #include "kick/2d/sprite.h"
00025 #include "glm/gtx/string_cast.hpp"
00026 #include "kick/texture/texture_atlas.h"
00027 #include "kick/2d/button.h"
00028 #include "canvas.h"
00029 
00030 using namespace std;
00031 
00032 namespace kick {
00033     
00034     Scene::Scene(const std::string & name)
00035     : mName(name)
00036     {
00037     }
00038     
00039     Scene::~Scene(){
00040     }
00041     
00042     Scene::Scene(Scene&& scene)
00043     : mGameObjects(move(scene.mGameObjects)),
00044      mCameras(move(scene.mCameras)),
00045      mName(move(scene.mName))
00046     {}
00047     
00048     Scene& Scene::operator=(Scene&& other){
00049         if (this != &other){
00050             mGameObjects = move(other.mGameObjects);
00051             mCameras = move(other.mCameras);
00052             mName = move(other.mName);
00053         }
00054         return *this;
00055     }
00056     
00057     GameObject *Scene::createGameObject(const string &name){
00058         auto res = new GameObject(name, this, ++mUniqueIdGenerator);
00059         EventListener<std::pair<std::shared_ptr<Component>, ComponentUpdateStatus>> eventListener = res->componentEvent.createListener([&](std::pair<std::shared_ptr<Component>, ComponentUpdateStatus> e){
00060             componentListener(e.first, e.second);
00061         });
00062 
00063         mGameObjects.push_back(unique_ptr<GameObject>(res));
00064         mComponentListeners[res] = move(eventListener);
00065         return res;
00066     }
00067 
00068     void Scene::destroyGameObject(GameObject *gameObject){
00069         for (int i=0;i< mGameObjects.size();i++){
00070             if (mGameObjects[i].get() == gameObject){
00071                 mComponentListeners.erase(gameObject);
00072                 mGameObjects.erase(mGameObjects.begin()+i);
00073                 return;
00074             }
00075         }
00076     }
00077     
00078     std::string Scene::name() const{
00079         return mName;
00080     }
00081     
00082     void Scene::setName(std::string name){
00083         this->mName = name;
00084     }
00085     
00086     GameObjectIter Scene::begin() const {
00087         return mGameObjects.begin();
00088     }
00089     
00090     GameObjectIter Scene::end() const {
00091         return mGameObjects.end();
00092     }
00093         
00094     void Scene::update() {
00095         for (auto & component : mUpdatable) {
00096             component->update();
00097         }
00098     }
00099     
00100     void Scene::render(EngineUniforms* engineUniforms){
00101         engineUniforms->sceneLights = &mSceneLights;
00102         std::sort(mCameras.begin(), mCameras.end(), [](std::shared_ptr<Camera> c1, std::shared_ptr<Camera> c2){
00103             return c1->index() < c2->index();
00104         });
00105         for (auto & camera : mCameras) {
00106             if (camera->enabled()){
00107                 engineUniforms->currentCamera = camera;
00108                 camera->render(engineUniforms);
00109             }
00110         }
00111     }
00112     
00113     void Scene::componentListener(std::shared_ptr<Component> component, ComponentUpdateStatus status){
00114         componentEvents.notifyListeners({component, status});
00115         auto camera = std::dynamic_pointer_cast<Camera>(component);
00116         auto light = std::dynamic_pointer_cast<Light>(component);
00117         if (status == ComponentUpdateStatus::Created){
00118             if (camera){
00119                 mCameras.push_back(camera);
00120             } else if (light){
00121                 mLights[light] = light->lightTypeChanged.createListener([&](std::shared_ptr<Light> l){
00122                     rebuildSceneLights();
00123                 }, 0);
00124                 addLight(light);
00125             }
00126             auto updateable = std::dynamic_pointer_cast<Updatable>(component);
00127             if (updateable){
00128                 mUpdatable.push_back(updateable);
00129             }
00130         }
00131         if (status == ComponentUpdateStatus::Destroyed){
00132             if (camera){
00133                 auto pos = find(mCameras.begin(), mCameras.end(), camera);
00134                 if (pos != mCameras.end()){
00135                     mCameras.erase(pos);
00136                 }
00137             } else if (light){
00138                 // rebuild lights
00139                 auto lightPos = mLights.find(light);
00140                 if (lightPos != mLights.end()){
00141                     mLights.erase(lightPos);
00142                     rebuildSceneLights();
00143                 }
00144             }
00145             auto updateable = std::dynamic_pointer_cast<Updatable>(component);
00146             if (updateable){
00147                 auto pos = find(mUpdatable.begin(), mUpdatable.end(), updateable);
00148                 if (pos != mUpdatable.end()){
00149                     mUpdatable.erase(pos);
00150                 }
00151             }
00152         }
00153     }
00154 
00155     void Scene::addLight(std::shared_ptr<Light> light) {
00156         switch (light->lightType()){
00157             case LightType::Ambient:
00158                 this->mSceneLights.ambientLight = light;
00159                 break;
00160             case LightType::Directional:
00161                 this->mSceneLights.directionalLight = light;
00162                 break;
00163             case LightType::Point:
00164                 this->mSceneLights.pointLights.push_back(light);
00165                 break;
00166             case LightType::Spot:
00167                 // todo implement
00168                 break;
00169             case LightType::Uninitialized:
00170                 break;
00171         }
00172     }
00173 
00174     std::shared_ptr<CameraPerspective> Scene::createPerspectiveCamera(GameObject *cameraObject){
00175         if (!cameraObject ){
00176             cameraObject = createGameObject("PerspectiveCamera");
00177         }
00178         auto cam = cameraObject->addComponent<CameraPerspective>();
00179         cam->setNear(0.1f);
00180         cam->setFar(100);
00181         cam->setFieldOfViewY(glm::radians(60.0f));
00182         cam->setClearColor(glm::vec4(0,0,0,1));
00183         return cam;
00184     }
00185 
00186     std::shared_ptr<CameraOrthographic> Scene::createOrthographicCamera(GameObject *cameraObject) {
00187         if (!cameraObject ) {
00188             cameraObject = createGameObject("OrthographicCamera");
00189         }
00190         auto cam = cameraObject->addComponent<CameraOrthographic>();
00191         glm::ivec2 dim = Engine::context()->getContextSurfaceDim();
00192         cam->setNear(-10);
00193         cam->setFar(10);
00194         cam->setLeft(-dim.x/2);
00195         cam->setRight(dim.x/2);
00196         cam->setBottom(-dim.y/2);
00197         cam->setTop(dim.y/2);
00198         cam->setClearColor(glm::vec4(0,0,0,1));
00199         return cam;
00200     }
00201 
00202     std::shared_ptr<MeshRenderer> Scene::createCube(GameObject *gameObject, float length){
00203         if (!gameObject) {
00204             gameObject = createGameObject("Cube");
00205         }
00206         auto meshRenderer = gameObject->addComponent<MeshRenderer>();
00207         auto mesh = make_shared<Mesh>();
00208         mesh->setMeshData(MeshFactory::createCubeData(length*0.5f));
00209         meshRenderer->setMesh(mesh);
00210 
00211         Material* mat = Project::createMaterial("assets/shaders/diffuse.shader");
00212         meshRenderer->setMaterial(mat);
00213         return meshRenderer;
00214     }
00215 
00216     std::shared_ptr<MeshRenderer> Scene::createSphere(GameObject *gameObject){
00217         if (!gameObject ) {
00218             gameObject = createGameObject("Sphere");
00219         }
00220         auto meshRenderer = gameObject->addComponent<MeshRenderer>();
00221         auto mesh = make_shared<Mesh>();
00222         mesh->setMeshData(MeshFactory::createUVSphereData());
00223         meshRenderer->setMesh(mesh);
00224 
00225         Material* mat = Project::createMaterial("assets/shaders/diffuse.shader");
00226         meshRenderer->setMaterial(mat);
00227         return meshRenderer;
00228     }
00229 
00230 
00231     std::shared_ptr<LineRenderer> Scene::createLine(GameObject *gameObject, const vector<glm::vec3> &points, kick::MeshType meshType, const std::vector<GLushort> &indices) {
00232         if (!gameObject) {
00233             gameObject = createGameObject("Plane");
00234         }
00235         auto lineRenderer = gameObject->addComponent<LineRenderer>();
00236         if (points.size()){
00237             lineRenderer->setPoints(points, meshType, indices);
00238         }
00239         return lineRenderer;
00240     }
00241 
00242     std::shared_ptr<MeshRenderer> Scene::createPlane(GameObject *gameObject){
00243         if (!gameObject) {
00244             gameObject = createGameObject("Plane");
00245         }
00246         auto meshRenderer = gameObject->addComponent<MeshRenderer>();
00247         auto mesh = make_shared<Mesh>();
00248         mesh->setMeshData(MeshFactory::createPlaneData());
00249         meshRenderer->setMesh(mesh);
00250 
00251         Material* mat = Project::createMaterial("assets/shaders/diffuse.shader");
00252         meshRenderer->setMaterial(mat);
00253         return meshRenderer;
00254     }
00255 
00256     std::shared_ptr<Light> Scene::createPointLight(GameObject *gameObject){
00257         if (!gameObject) {
00258             gameObject = createGameObject("PointLight");
00259         }
00260         auto light = gameObject->addComponent<Light>();
00261         light->setLightType(LightType::Point);
00262         return light;
00263     }
00264 
00265     std::shared_ptr<Light> Scene::createDirectionalLight(GameObject *gameObject){
00266         if (!gameObject){
00267             gameObject = createGameObject("DirectionalLight");
00268         }
00269         auto light = gameObject->addComponent<Light>();
00270         light->setLightType(LightType::Directional);
00271         return light;
00272     }
00273 
00274     // helper function, which creates a gameobject and attaches a ambient light
00275     std::shared_ptr<Light> Scene::createAmbientLight(float intensity, glm::vec3 color){
00276         GameObject *gameObject = createGameObject("AmbientLight");
00277         auto light = gameObject->addComponent<Light>();
00278         light->setLightType(LightType::Ambient);
00279         light->setIntensity(intensity);
00280         light->setColor(color);
00281         return light;
00282     }
00283 
00284     void Scene::rebuildSceneLights() {
00285         mSceneLights.clear();
00286         for (auto & l : mLights){
00287             addLight(l.first);
00288         }
00289     }
00290 
00291     std::shared_ptr<Canvas> Scene::createCanvas(bool includeUICamera) {
00292         GameObject *gameObject = createGameObject("Canvas");
00293         auto canvas = gameObject->addComponent<Canvas>();
00294         if (includeUICamera){
00295             auto camera = createOrthographicCamera(gameObject);
00296             camera->setMain(false);
00297             camera->setIndex(1);
00298             camera->setCullingMask(256);//0b100000000
00299             camera->setClearColorBuffer(false);
00300             canvas->setCamera(camera);
00301         }
00302         return canvas;
00303     }
00304 
00305     GameObject *Scene::gameObjectByUID(int32_t uid) {
00306         for (auto & gameObject : *this) {
00307             if (gameObject->uniqueId() == uid) {
00308                 return gameObject.get();
00309             }
00310         }
00311         return nullptr;
00312     }
00313 
00314     std::shared_ptr<Camera> Scene::mainCamera() {
00315         for (auto c : mCameras) {
00316             if (c->main()) {
00317                 return c;
00318             }
00319         }
00320         if (!mCameras.empty()) {
00321             return mCameras[0];
00322         }
00323         return std::shared_ptr<Camera>();
00324     }
00325 }
 All Classes Functions Variables