Browse Source

Merge pull request #465 from AtomicGameEngine/JME-ATOMIC-458-TAKE2

Cubemap Generation
JoshEngebretson 10 years ago
parent
commit
cecd6fb756

+ 6 - 0
Script/AtomicEditor/ui/frames/inspector/CreateComponentButton.ts

@@ -72,6 +72,11 @@ subsystemCreateSource.addItem(new Atomic.UIMenuItem("DebugRenderer", "create com
 subsystemCreateSource.addItem(new Atomic.UIMenuItem("Octree", "create component"));
 subsystemCreateSource.addItem(new Atomic.UIMenuItem("Octree", "create component"));
 subsystemCreateSource.addItem(new Atomic.UIMenuItem("PhysicsWorld", "create component"));
 subsystemCreateSource.addItem(new Atomic.UIMenuItem("PhysicsWorld", "create component"));
 
 
+var editorCreateSource = new Atomic.UIMenuItemSource();
+
+editorCreateSource.addItem(new Atomic.UIMenuItem("CubemapGenerator", "CubemapGenerator"));
+
+
 var componentCreateSource = new Atomic.UIMenuItemSource();
 var componentCreateSource = new Atomic.UIMenuItemSource();
 
 
 var sources = {
 var sources = {
@@ -84,6 +89,7 @@ var sources = {
     Physics: physicsCreateSource,
     Physics: physicsCreateSource,
     Scene: sceneCreateSource,
     Scene: sceneCreateSource,
     SubSystem: subsystemCreateSource,
     SubSystem: subsystemCreateSource,
+    Editor : editorCreateSource
 }
 }
 
 
 for (var sub in sources) {
 for (var sub in sources) {

+ 73 - 0
Script/AtomicEditor/ui/frames/inspector/SelectionSectionCoreUI.ts

@@ -11,6 +11,8 @@ import SelectionSection = require("./SelectionSection");
 import SelectionSectionUI = require("./SelectionSectionUI");
 import SelectionSectionUI = require("./SelectionSectionUI");
 import SerializableEditType = require("./SerializableEditType");
 import SerializableEditType = require("./SerializableEditType");
 
 
+import ProgressModal = require("ui/modal/ProgressModal");
+
 
 
 class CollisionShapeSectionUI extends SelectionSectionUI {
 class CollisionShapeSectionUI extends SelectionSectionUI {
 
 
@@ -45,4 +47,75 @@ class CollisionShapeSectionUI extends SelectionSectionUI {
 
 
 }
 }
 
 
+class CubemapGeneratorSectionUI extends SelectionSectionUI {
+
+    createUI(editType: SerializableEditType) {
+
+        this.editType = editType;
+
+        var button = new Atomic.UIButton();
+        button.fontDescription = InspectorUtils.attrFontDesc;
+        button.gravity = Atomic.UI_GRAVITY_RIGHT;
+        button.text = "Render Cubemap";
+
+        button.onClick = () => {
+
+            var scene = null;
+            var count = 0;
+            var progressModal = new ProgressModal("Rendering Cubemaps", "Rendering Cubemaps, please wait...");
+
+            for (var i in this.editType.objects) {
+
+                var gen = <Editor.CubemapGenerator>this.editType.objects[i];
+
+                if (!scene) {
+
+                    scene = gen.scene;
+
+                    this.subscribeToEvent(scene, "CubemapRenderBegin", () => {
+
+                        count++;
+
+                    })
+
+                    this.subscribeToEvent(scene, "CubemapRenderEnd", () => {
+
+                        count--;
+
+                        if (!count)
+                            progressModal.hide();
+
+                    })
+
+
+                }
+
+                if (!gen.render()) {
+
+                    //TODO: Cancel other renders if any and report better error information
+
+                    EditorUI.showModalError("Render Cubemaps",
+                        "There was an error rendering cubemaps, please see the application log");
+
+                    scene = null;
+                    break;
+
+                }
+            }
+
+            if (scene) {
+
+                progressModal.show();
+
+            }
+
+        };
+
+        this.addChild(button);
+
+    }
+
+}
+
 SelectionSection.registerCustomSectionUI("CollisionShape", CollisionShapeSectionUI);
 SelectionSection.registerCustomSectionUI("CollisionShape", CollisionShapeSectionUI);
+SelectionSection.registerCustomSectionUI("CubemapGenerator", CubemapGeneratorSectionUI);

+ 4 - 3
Script/Packages/Editor/Editor.json

@@ -2,8 +2,9 @@
 	"name" : "Editor",
 	"name" : "Editor",
 	"includes" : ["<Atomic/Graphics/DebugRenderer.h>"],
 	"includes" : ["<Atomic/Graphics/DebugRenderer.h>"],
 	"sources" : ["Source/AtomicEditor/Application", "Source/AtomicEditor/Utils",
 	"sources" : ["Source/AtomicEditor/Application", "Source/AtomicEditor/Utils",
-							"Source/AtomicEditor/EditorMode", "Source/AtomicEditor/PlayerMode",
-							 "Source/AtomicEditor/Editors", "Source/AtomicEditor/Editors/SceneEditor3D"],
+							 "Source/AtomicEditor/EditorMode", "Source/AtomicEditor/PlayerMode",
+							 "Source/AtomicEditor/Editors", "Source/AtomicEditor/Editors/SceneEditor3D",
+						   "Source/AtomicEditor/Components"],
 	"classes" : ["EditorMode", "PlayerMode", "FileUtils", "ResourceEditor", "JSResourceEditor",
 	"classes" : ["EditorMode", "PlayerMode", "FileUtils", "ResourceEditor", "JSResourceEditor",
-								"SceneEditor3D", "SceneView3D", "SceneSelection"]
+							 "SceneEditor3D", "SceneView3D", "SceneSelection", "EditorComponent", "CubemapGenerator"]
 }
 }

+ 4 - 0
Source/AtomicEditor/Application/AEEditorCommon.cpp

@@ -27,6 +27,8 @@
 #include <AtomicNET/NETScript/NETScript.h>
 #include <AtomicNET/NETScript/NETScript.h>
 #endif
 #endif
 
 
+#include "../Components/EditorComponents.h"
+
 #include "AEEditorCommon.h"
 #include "AEEditorCommon.h"
 
 
 namespace Atomic
 namespace Atomic
@@ -75,6 +77,8 @@ void AEEditorCommon::Setup()
     RegisterEnvironmentLibrary(context_);
     RegisterEnvironmentLibrary(context_);
 #endif
 #endif
 
 
+    RegisterEditorComponentLibrary(context_);
+
 #ifdef ATOMIC_DOTNET
 #ifdef ATOMIC_DOTNET
     RegisterNETScriptLibrary(context_);
     RegisterNETScriptLibrary(context_);
 #endif
 #endif

+ 1 - 0
Source/AtomicEditor/CMakeLists.txt

@@ -70,3 +70,4 @@ GroupSources("Editors")
 GroupSources("Javascript")
 GroupSources("Javascript")
 GroupSources("PlayerMode")
 GroupSources("PlayerMode")
 GroupSources("Utils")
 GroupSources("Utils")
+GroupSources("Components")

+ 324 - 0
Source/AtomicEditor/Components/CubemapGenerator.cpp

@@ -0,0 +1,324 @@
+// Portions Copyright (c) 2008-2015 the Urho3D project.
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#include <Atomic/Core/Context.h>
+#include <Atomic/Core/CoreEvents.h>
+
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/FileSystem.h>
+#include <Atomic/IO/File.h>
+
+#include <Atomic/Graphics/Graphics.h>
+#include <Atomic/Graphics/Camera.h>
+#include <Atomic/Graphics/Viewport.h>
+#include <Atomic/Graphics/Texture2D.h>
+#include <Atomic/Graphics/TextureCube.h>
+
+#include <Atomic/Resource/ResourceCache.h>
+#include <Atomic/Resource/XMLFile.h>
+
+#include <Atomic/Scene/Node.h>
+
+#include <ToolCore/ToolSystem.h>
+#include <ToolCore/Project/Project.h>
+
+#include "../Editors/SceneEditor3D/SceneEditor3DEvents.h"
+#include "../Editors/SceneEditor3D/SceneEditor3D.h"
+
+#include "CubemapGenerator.h"
+
+namespace AtomicEditor
+{
+
+CubemapGenerator::CubemapGenerator(Context *context) : EditorComponent(context),
+    updateCycle_(0),
+    imageSize_(512),
+    namePrefix_("Cubemap")
+{
+
+}
+
+CubemapGenerator::~CubemapGenerator()
+{
+
+}
+
+bool CubemapGenerator::Render()
+{
+
+    if(!InitRender())
+    {
+        LOGERRORF("Unable to init render");
+        return false;
+    }
+
+    GetScene()->SendEvent(E_CUBEMAPRENDERBEGIN);    
+    SubscribeToEvent(E_BEGINFRAME, HANDLER(CubemapGenerator, HandleBeginFrame));
+    SubscribeToEvent(E_ENDFRAME, HANDLER(CubemapGenerator, HandleEndFrame));
+
+    return true;
+
+}
+
+bool CubemapGenerator::InitPaths()
+{
+
+    String scenePath = sceneEditor_->GetFullPath();
+
+    String pathName;
+    String fileName;
+    String ext;
+
+    SplitPath(scenePath, pathName, fileName, ext);
+
+    outputPathAbsolute_ = pathName + "Cubemaps/" + fileName + "/";
+
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+
+    if (!fileSystem->DirExists(outputPathAbsolute_))
+    {
+        if (!fileSystem->CreateDirs(pathName,  "Cubemaps/" + fileName + "/"))
+        {
+            LOGERRORF("CubemapGenerator::InitRender - Unable to create path: %s", outputPathAbsolute_.CString());
+            return false;
+        }
+    }
+
+    // TODO: There should be a better way of getting the resource path
+    ToolSystem* tsystem = GetSubsystem<ToolSystem>();
+    Project* project = tsystem->GetProject();
+
+    resourcePath_ = outputPathAbsolute_;
+    resourcePath_.Replace(project->GetResourcePath(), "");
+    resourcePath_ = AddTrailingSlash(resourcePath_);
+
+    return true;
+
+}
+
+bool CubemapGenerator::InitRender()
+{
+
+    sceneEditor_ = GetSceneEditor();
+
+    if (sceneEditor_.Null())
+    {
+        LOGERROR("CubemapGenerator::InitRender - unable to get scene editor");
+        return false;
+    }
+
+    if (!InitPaths())
+        return false;
+
+    cameraNode_ = node_->CreateChild("CubeMapRenderCamera");
+    cameraNode_->SetTemporary(true);
+
+    camera_ = cameraNode_->CreateComponent<Camera>();
+    camera_->SetTemporary(true);
+    camera_->SetFov(90.0f);
+    camera_->SetNearClip(0.0001f);
+    camera_->SetAspectRatio(1.0f);
+
+    RenderPath* renderPath = sceneEditor_->GetSceneView3D()->GetViewport()->GetRenderPath();
+    viewport_ = new Viewport(context_, GetScene(), camera_, renderPath);
+
+    renderImage_ = new Texture2D(context_);
+    renderImage_->SetSize(imageSize_, imageSize_, Graphics::GetRGBAFormat(), TEXTURE_RENDERTARGET);
+
+    renderSurface_ = renderImage_->GetRenderSurface();
+    renderSurface_->SetViewport(0, viewport_);
+    renderSurface_->SetUpdateMode(SURFACE_UPDATEALWAYS);
+
+    return true;
+
+}
+
+void CubemapGenerator::SaveCubemapXML()
+{
+    SharedPtr<XMLFile> xmlFile(new XMLFile(context_));
+    XMLElement rootElem = xmlFile->CreateRoot("cubemap");
+
+    String prefix = resourcePath_ + namePrefix_ + "_";
+
+    String name = prefix + GetFaceName(FACE_POSITIVE_X) + ".png";
+    rootElem.CreateChild("face").SetAttribute("name", name);
+    name = prefix + GetFaceName(FACE_NEGATIVE_X) + ".png";
+    rootElem.CreateChild("face").SetAttribute("name", name);
+    name = prefix + GetFaceName(FACE_POSITIVE_Y) + ".png";
+    rootElem.CreateChild("face").SetAttribute("name", name);
+    name = prefix + GetFaceName(FACE_NEGATIVE_Y) + ".png";
+    rootElem.CreateChild("face").SetAttribute("name", name);
+    name = prefix + GetFaceName(FACE_POSITIVE_Z) + ".png";
+    rootElem.CreateChild("face").SetAttribute("name", name);
+    name = prefix + GetFaceName(FACE_NEGATIVE_Z) + ".png";
+    rootElem.CreateChild("face").SetAttribute("name", name);
+
+    String xmlPath = outputPathAbsolute_ + namePrefix_ + ".xml";
+
+    SharedPtr<File> file(new File(context_, xmlPath, FILE_WRITE));
+    xmlFile->Save(*file, "    ");
+    file->Close();
+
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    TextureCube* texcube = cache->GetResource<TextureCube>(resourcePath_ + namePrefix_ + ".xml");
+    if (texcube)
+        cache->ReloadResource(texcube);
+
+}
+
+void CubemapGenerator::EndRender()
+{
+    UnsubscribeFromEvent(E_BEGINFRAME);
+    UnsubscribeFromEvent(E_ENDFRAME);
+
+    SaveCubemapXML();
+
+    cameraNode_->Remove();
+
+    cameraNode_ = 0;
+    camera_ = 0;
+    viewport_ = 0;
+    renderImage_ = 0;
+    assert(renderSurface_->Refs() == 1);
+    renderSurface_ = 0;
+    updateCycle_ = 0;
+
+    GetScene()->SendEvent(E_CUBEMAPRENDEREND);
+
+}
+
+void CubemapGenerator::HandleBeginFrame(StringHash eventType, VariantMap& eventData)
+{
+    updateCycle_++;
+    if (updateCycle_ < 7)
+        cameraNode_->SetWorldRotation(RotationOf(GetFaceForCycle(updateCycle_)));
+    else
+    {
+        EndRender();
+    }
+}
+
+void CubemapGenerator::HandleEndFrame(StringHash eventType, VariantMap& eventData)
+{
+    SharedPtr<Image> image(GetImage(renderImage_));
+
+    String path = outputPathAbsolute_;
+
+    if (namePrefix_.Length())
+        path += namePrefix_;
+
+    path.AppendWithFormat("_%s.png", GetFaceName(GetFaceForCycle(updateCycle_)).CString());
+
+    image->SavePNG(path);
+
+}
+
+SharedPtr<Image> CubemapGenerator::GetImage(Texture2D* tex2d)
+{
+    Image* rawImage = new Image(tex2d->GetContext());
+
+    const unsigned format = tex2d->GetFormat();
+
+    if (format == Graphics::GetRGBAFormat() || format == Graphics::GetRGBA16Format() || format == Graphics::GetRGBAFloat32Format())
+        rawImage->SetSize(tex2d->GetWidth(), tex2d->GetHeight(), 4);
+    else if (format == Graphics::GetRGBFormat())
+        rawImage->SetSize(tex2d->GetWidth(), tex2d->GetHeight(), 3);
+    else
+        return SharedPtr<Image>();
+
+    tex2d->GetData(0, rawImage->GetData());
+
+    return SharedPtr<Image>(rawImage);
+}
+
+
+CubeMapFace CubemapGenerator::GetFaceForCycle(int cycle)
+{
+    switch (cycle)
+    {
+    case 1:
+        return FACE_POSITIVE_X;
+    case 2:
+        return FACE_POSITIVE_Y;
+    case 3:
+        return FACE_POSITIVE_Z;
+    case 4:
+        return FACE_NEGATIVE_X;
+    case 5:
+        return FACE_NEGATIVE_Y;
+    case 6:
+        return FACE_NEGATIVE_Z;
+    }
+    return FACE_POSITIVE_X;
+
+}
+
+String CubemapGenerator::GetFaceName(CubeMapFace face)
+{
+    switch (face)
+    {
+    case FACE_POSITIVE_X:
+        return "PosX";
+    case FACE_POSITIVE_Y:
+        return "PosY";
+    case FACE_POSITIVE_Z:
+        return "PosZ";
+    case FACE_NEGATIVE_X:
+        return "NegX";
+    case FACE_NEGATIVE_Y:
+        return "NegY";
+    case FACE_NEGATIVE_Z:
+        return "NegZ";
+    default:
+        break;
+
+    }
+    return "PosX";
+}
+
+Quaternion CubemapGenerator::RotationOf(CubeMapFace face)
+{
+    Quaternion result;
+    switch (face)
+    {
+    //  Rotate camera according to probe rotation
+    case FACE_POSITIVE_X:
+        result = Quaternion(0, 90, 0);
+        break;
+    case FACE_NEGATIVE_X:
+        result = Quaternion(0, -90, 0);
+        break;
+    case FACE_POSITIVE_Y:
+        result = Quaternion(-90, 0, 0);
+        break;
+    case FACE_NEGATIVE_Y:
+        result = Quaternion(90, 0, 0);
+        break;
+    case FACE_POSITIVE_Z:
+        result = Quaternion(0, 0, 0);
+        break;
+    case FACE_NEGATIVE_Z:
+        result = Quaternion(0, 180, 0);
+        break;
+    default:
+        break;
+    }
+    return result;
+}
+
+void CubemapGenerator::RegisterObject(Context* context)
+{
+    context->RegisterFactory<CubemapGenerator>();
+
+    ATTRIBUTE("Name Prefix", String, namePrefix_, "Cubemap", AM_DEFAULT);
+    ATTRIBUTE("Image Size", int, imageSize_, 512, AM_DEFAULT);
+
+}
+
+
+}

+ 88 - 0
Source/AtomicEditor/Components/CubemapGenerator.h

@@ -0,0 +1,88 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#pragma once
+
+#include <Atomic/Graphics/GraphicsDefs.h>
+
+#include "EditorComponent.h"
+
+namespace Atomic
+{
+class Node;
+class Zone;
+class Camera;
+class Viewport;
+class Texture2D;
+class RenderSurface;
+class RenderPath;
+class Image;
+}
+
+using namespace Atomic;
+
+namespace AtomicEditor
+{
+
+class CubemapGenerator : public EditorComponent
+{
+    OBJECT(CubemapGenerator);
+
+public:
+    /// Construct.
+    CubemapGenerator(Context* context);
+
+    /// Destruct.
+    virtual ~CubemapGenerator();
+
+    /// Register object factory.
+    static void RegisterObject(Context* context);
+
+    bool Render();
+
+    int GetImageSize() const { return imageSize_; }
+    void SetImageSize(int size) { imageSize_ = size; }
+
+protected:
+
+private:
+
+    void HandleBeginFrame(StringHash eventType, VariantMap& eventData);
+    void HandleEndFrame(StringHash eventType, VariantMap& eventData);
+
+    bool InitRender();
+    bool InitPaths();
+    void EndRender();
+
+    void SaveCubemapXML();
+
+    SharedPtr<Image> GetImage(Texture2D* tex2d);
+
+    CubeMapFace GetFaceForCycle(int cycle);
+    String GetFaceName(CubeMapFace face);
+    Quaternion RotationOf(CubeMapFace face);
+
+    SharedPtr<Node> cameraNode_;
+    SharedPtr<Camera> camera_;
+    SharedPtr<Viewport> viewport_;
+    SharedPtr<Texture2D> renderImage_;
+    SharedPtr<RenderSurface> renderSurface_;
+
+    int updateCycle_;
+    int imageSize_;
+
+    String namePrefix_;
+
+    String outputPathAbsolute_;
+    String resourcePath_;
+
+    WeakPtr<SceneEditor3D> sceneEditor_;
+
+};
+
+
+}

+ 45 - 0
Source/AtomicEditor/Components/EditorComponent.cpp

@@ -0,0 +1,45 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#include <Atomic/Core/Context.h>
+
+#include <Atomic/Graphics/Camera.h>
+#include <Atomic/Graphics/Viewport.h>
+#include <Atomic/Graphics/Texture2D.h>
+
+#include "../Editors/SceneEditor3D/SceneEditor3D.h"
+
+#include "EditorComponent.h"
+
+namespace AtomicEditor
+{
+
+EditorComponent::EditorComponent(Context *context) : Component(context)
+{
+
+}
+
+EditorComponent::~EditorComponent()
+{
+
+}
+
+void EditorComponent::RegisterObject(Context* context)
+{
+    context->RegisterFactory<EditorComponent>();
+}
+
+SceneEditor3D* EditorComponent::GetSceneEditor()
+{
+    if (!GetScene())
+        return NULL;
+
+    return SceneEditor3D::GetSceneEditor(GetScene());
+
+}
+
+}

+ 43 - 0
Source/AtomicEditor/Components/EditorComponent.h

@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#pragma once
+
+#include <Atomic/Scene/Component.h>
+
+using namespace Atomic;
+
+namespace AtomicEditor
+{
+
+class SceneEditor3D;
+
+/// A component that requires the editor, for example CubemapGenerator requires a renderer
+/// IMPORTANT: Other tool related components, which don't require the editor, should be in ToolCore
+class EditorComponent : public Component
+{
+    OBJECT(EditorComponent);
+
+public:
+
+    /// Construct.
+    EditorComponent(Context* context);
+
+    /// Destruct.
+    virtual ~EditorComponent();
+
+    /// Register object factory.
+    static void RegisterObject(Context* context);
+
+protected:
+
+    SceneEditor3D* GetSceneEditor();
+
+
+};
+
+}

+ 15 - 0
Source/AtomicEditor/Components/EditorComponents.cpp

@@ -0,0 +1,15 @@
+#include "EditorComponents.h"
+
+#include "EditorComponent.h"
+#include "CubemapGenerator.h"
+
+namespace AtomicEditor
+{
+
+void RegisterEditorComponentLibrary(Atomic::Context* context)
+{
+    EditorComponent::RegisterObject(context);
+    CubemapGenerator::RegisterObject(context);
+}
+
+}

+ 21 - 0
Source/AtomicEditor/Components/EditorComponents.h

@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#pragma once
+
+namespace Atomic
+{
+class Context;
+}
+
+namespace AtomicEditor
+{
+
+void RegisterEditorComponentLibrary(Atomic::Context* context);
+
+}
+

+ 74 - 4
Source/AtomicEditor/Editors/SceneEditor3D/SceneEditor3D.cpp

@@ -43,8 +43,11 @@ using namespace ToolCore;
 namespace AtomicEditor
 namespace AtomicEditor
 {
 {
 
 
-SceneEditor3D ::SceneEditor3D(Context* context, const String &fullpath, UITabContainer *container) :
-    ResourceEditor(context, fullpath, container)
+Vector<WeakPtr<SceneEditor3D>> SceneEditor3D::sceneEditors_;
+
+SceneEditor3D::SceneEditor3D(Context* context, const String &fullpath, UITabContainer *container) :
+    ResourceEditor(context, fullpath, container),
+    cubemapRenderCount_(0)
 {
 {
 
 
     // store a local reference to user project prefs
     // store a local reference to user project prefs
@@ -115,6 +118,11 @@ SceneEditor3D ::SceneEditor3D(Context* context, const String &fullpath, UITabCon
     SubscribeToEvent(E_EDITORPLAYERSTOPPED, HANDLER(SceneEditor3D, HandlePlayStopped));
     SubscribeToEvent(E_EDITORPLAYERSTOPPED, HANDLER(SceneEditor3D, HandlePlayStopped));
     SubscribeToEvent(scene_, E_SCENEEDITSCENEMODIFIED, HANDLER(SceneEditor3D, HandleSceneEditSceneModified));
     SubscribeToEvent(scene_, E_SCENEEDITSCENEMODIFIED, HANDLER(SceneEditor3D, HandleSceneEditSceneModified));
 
 
+    SubscribeToEvent(scene_, E_CUBEMAPRENDERBEGIN, HANDLER(SceneEditor3D, HandleCubemapRenderBegin));
+    SubscribeToEvent(scene_, E_CUBEMAPRENDEREND, HANDLER(SceneEditor3D, HandleCubemapRenderEnd));
+
+    RegisterSceneEditor();
+
 }
 }
 
 
 SceneEditor3D::~SceneEditor3D()
 SceneEditor3D::~SceneEditor3D()
@@ -196,7 +204,8 @@ void SceneEditor3D::SetFocus()
 
 
 void SceneEditor3D::HandleUpdate(StringHash eventType, VariantMap& eventData)
 void SceneEditor3D::HandleUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
-    gizmo3D_->Update();
+    if (!cubemapRenderCount_)
+        gizmo3D_->Update();
 }
 }
 
 
 void SceneEditor3D::HandlePlayStarted(StringHash eventType, VariantMap& eventData)
 void SceneEditor3D::HandlePlayStarted(StringHash eventType, VariantMap& eventData)
@@ -335,7 +344,7 @@ void SceneEditor3D::HandleSceneEditNodeCreated(StringHash eventType, VariantMap&
 
 
 void SceneEditor3D::HandleSceneEditSceneModified(StringHash eventType, VariantMap& eventData)
 void SceneEditor3D::HandleSceneEditSceneModified(StringHash eventType, VariantMap& eventData)
 {
 {
-    SetModified(true);    
+    SetModified(true);
 }
 }
 
 
 void SceneEditor3D::HandleUserPrefSaved(StringHash eventType, VariantMap& eventData)
 void SceneEditor3D::HandleUserPrefSaved(StringHash eventType, VariantMap& eventData)
@@ -426,4 +435,65 @@ void SceneEditor3D::ReparentNode(Node* node, Node* newParent)
 
 
 }
 }
 
 
+void SceneEditor3D::RegisterSceneEditor()
+{
+    // prune released scene editors
+    for (Vector<WeakPtr<SceneEditor3D> >::Iterator i = sceneEditors_.Begin(); i != sceneEditors_.End();)
+    {
+        if (*i)
+        {
+            ++i;
+        }
+        else
+        {
+            i = sceneEditors_.Erase(i);
+        }
+    }
+
+    sceneEditors_.Push(WeakPtr<SceneEditor3D>(this));
+
+}
+
+SceneEditor3D* SceneEditor3D::GetSceneEditor(Scene* scene)
+{
+
+    for (Vector<WeakPtr<SceneEditor3D> >::Iterator i = sceneEditors_.Begin(); i != sceneEditors_.End();)
+    {
+        if (*i && scene == (*i)->GetScene())
+            return *i;
+
+        i++;
+    }
+
+    return NULL;
+
+}
+
+void SceneEditor3D::HandleCubemapRenderBegin(StringHash eventType, VariantMap& eventData)
+{
+    cubemapRenderCount_++;
+
+    if (cubemapRenderCount_ == 1)
+    {
+        // first time
+        sceneView_->GetDebugRenderer()->SetEnabled(false);
+        gizmo3D_->Hide();
+    }
+
+}
+
+void SceneEditor3D::HandleCubemapRenderEnd(StringHash eventType, VariantMap& eventData)
+{
+    cubemapRenderCount_--;
+
+    if (cubemapRenderCount_ == 0)
+    {
+        // last one
+        sceneView_->GetDebugRenderer()->SetEnabled(true);
+        gizmo3D_->Show();
+    }
+
+}
+
+
 }
 }

+ 11 - 0
Source/AtomicEditor/Editors/SceneEditor3D/SceneEditor3D.h

@@ -81,6 +81,8 @@ public:
 
 
     void InvokeShortcut(const String& shortcut);
     void InvokeShortcut(const String& shortcut);
 
 
+    static SceneEditor3D* GetSceneEditor(Scene* scene);
+
 private:
 private:
 
 
     void HandleUpdate(StringHash eventType, VariantMap& eventData);
     void HandleUpdate(StringHash eventType, VariantMap& eventData);
@@ -94,6 +96,9 @@ private:
     void HandleSceneEditSceneModified(StringHash eventType, VariantMap& eventData);
     void HandleSceneEditSceneModified(StringHash eventType, VariantMap& eventData);
     void HandleSceneEditNodeCreated(StringHash eventType, VariantMap& eventData);
     void HandleSceneEditNodeCreated(StringHash eventType, VariantMap& eventData);
 
 
+    void HandleCubemapRenderBegin(StringHash eventType, VariantMap& eventData);
+    void HandleCubemapRenderEnd(StringHash eventType, VariantMap& eventData);
+
     void UpdateGizmoSnapSettings();
     void UpdateGizmoSnapSettings();
 
 
     SharedPtr<Scene> scene_;
     SharedPtr<Scene> scene_;
@@ -110,6 +115,12 @@ private:
 
 
     WeakPtr<ProjectUserPrefs> userPrefs_;
     WeakPtr<ProjectUserPrefs> userPrefs_;
 
 
+    void RegisterSceneEditor();
+
+    static Vector<WeakPtr<SceneEditor3D>> sceneEditors_;
+
+    int cubemapRenderCount_;
+
 };
 };
 
 
 }
 }

+ 10 - 0
Source/AtomicEditor/Editors/SceneEditor3D/SceneEditor3DEvents.h

@@ -131,4 +131,14 @@ EVENT(E_SCENEEDITSCENEMODIFIED, SceneEditSceneModified)
 
 
 }
 }
 
 
+EVENT(E_CUBEMAPRENDERBEGIN, CubemapRenderBegin)
+{
+
+}
+
+EVENT(E_CUBEMAPRENDEREND, CubemapRenderEnd)
+{
+
+}
+
 }
 }

+ 1 - 0
Source/AtomicEditor/Editors/SceneEditor3D/SceneView3D.cpp

@@ -646,4 +646,5 @@ void SceneView3D::FrameSelection()
 
 
 }
 }
 
 
+
 }
 }

+ 1 - 1
Source/AtomicEditor/Editors/SceneEditor3D/SceneView3D.h

@@ -72,7 +72,7 @@ private:
     void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData);
     void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData);
 
 
     void HandleUIWidgetFocusEscaped(StringHash eventType, VariantMap& eventData);
     void HandleUIWidgetFocusEscaped(StringHash eventType, VariantMap& eventData);
-    void HandleUIUnhandledShortcut(StringHash eventType, VariantMap& eventData);    
+    void HandleUIUnhandledShortcut(StringHash eventType, VariantMap& eventData);
 
 
     void MoveCamera(float timeStep);
     void MoveCamera(float timeStep);