void PrefabDiff::applyDiff(const SPtr<PrefabObjectDiff>& diff, const HSceneObject& object) { if ((diff->soFlags & (UINT32)SceneObjectDiffFlags::Name) != 0) object->setName(diff->name); if ((diff->soFlags & (UINT32)SceneObjectDiffFlags::Position) != 0) object->setPosition(diff->position); if ((diff->soFlags & (UINT32)SceneObjectDiffFlags::Rotation) != 0) object->setRotation(diff->rotation); if ((diff->soFlags & (UINT32)SceneObjectDiffFlags::Scale) != 0) object->setScale(diff->scale); if ((diff->soFlags & (UINT32)SceneObjectDiffFlags::Active) != 0) object->setActive(diff->isActive); // Note: It is important to remove objects and components first, before adding them. // Some systems rely on the fact that applyDiff added components/objects are // always at the end. const Vector<HComponent>& components = object->getComponents(); for (auto& removedId : diff->removedComponents) { for (auto component : components) { if (removedId == component->getLinkId()) { component->destroy(); break; } } } for (auto& removedId : diff->removedChildren) { UINT32 childCount = object->getNumChildren(); for (UINT32 i = 0; i < childCount; i++) { HSceneObject child = object->getChild(i); if (removedId == child->getLinkId()) { child->destroy(); break; } } } for (auto& addedComponentData : diff->addedComponents) { BinarySerializer bs; SPtr<Component> component = std::static_pointer_cast<Component>(bs._decodeFromIntermediate(addedComponentData)); object->addAndInitializeComponent(component); } for (auto& addedChildData : diff->addedChildren) { BinarySerializer bs; SPtr<SceneObject> sceneObject = std::static_pointer_cast<SceneObject>(bs._decodeFromIntermediate(addedChildData)); sceneObject->setParent(object); if(object->isInstantiated()) sceneObject->_instantiate(); } for (auto& componentDiff : diff->componentDiffs) { for (auto& component : components) { if (componentDiff->id == component->getLinkId()) { IDiff& diffHandler = component->getRTTI()->getDiffHandler(); diffHandler.applyDiff(component.getInternalPtr(), componentDiff->data); break; } } } for (auto& childDiff : diff->childDiffs) { UINT32 childCount = object->getNumChildren(); for (UINT32 i = 0; i < childCount; i++) { HSceneObject child = object->getChild(i); if (childDiff->id == child->getLinkId()) { applyDiff(childDiff, child); break; } } } }
/** Set up the 3D object used by the example, and the camera to view the world through. */ void setUp3DScene(const Assets& assets) { /************************************************************************/ /* SCENE OBJECT */ /************************************************************************/ // Now we create a scene object that has a position, orientation, scale and optionally // components to govern its logic. In this particular case we are creating a SceneObject // with a Renderable component which will render a mesh at the position of the scene object // with the provided material. // Create new scene object at (0, 0, 0) HSceneObject pistolSO = SceneObject::create("Pistol"); // Attach the Renderable component and hook up the mesh we imported earlier, // and the material we created in the previous section. HRenderable renderable = pistolSO->addComponent<CRenderable>(); renderable->setMesh(assets.exampleModel); renderable->setMaterial(assets.exampleMaterial); // Add a rotator component so we can rotate the object during runtime pistolSO->addComponent<ObjectRotator>(); /************************************************************************/ /* SKYBOX */ /************************************************************************/ // Add a skybox texture for sky reflections HSceneObject skyboxSO = SceneObject::create("Skybox"); HSkybox skybox = skyboxSO->addComponent<CSkybox>(); skybox->setTexture(assets.exampleSkyCubemap); /************************************************************************/ /* CAMERA */ /************************************************************************/ // In order something to render on screen we need at least one camera. // Like before, we create a new scene object at (0, 0, 0). HSceneObject sceneCameraSO = SceneObject::create("SceneCamera"); // Get the primary render window we need for creating the camera. Additionally // hook up a callback so we are notified when user resizes the window. SPtr<RenderWindow> window = gApplication().getPrimaryWindow(); window->onResized.connect(&renderWindowResized); // Add a Camera component that will output whatever it sees into that window // (You could also use a render texture or another window you created). sceneCamera = sceneCameraSO->addComponent<CCamera>(window); // Set up camera component properties // Set closest distance that is visible. Anything below that is clipped. sceneCamera->setNearClipDistance(0.005f); // Set farthest distance that is visible. Anything above that is clipped. sceneCamera->setFarClipDistance(1000); // Set aspect ratio depending on the current resolution sceneCamera->setAspectRatio(windowResWidth / (float)windowResHeight); // Enable multi-sample anti-aliasing for better quality sceneCamera->setMSAACount(4); // Add a CameraFlyer component that allows us to move the camera. See CameraFlyer for more information. sceneCameraSO->addComponent<CameraFlyer>(); // Position and orient the camera scene object sceneCameraSO->setPosition(Vector3(0.2f, 0.1f, 0.2f)); sceneCameraSO->lookAt(Vector3(-0.1f, 0, 0)); }