Browse Source

Applied material editor preview patch from primitivewaste, which also adds View3D UI element class.

Lasse Öörni 12 years ago
parent
commit
9ff0247c68

+ 69 - 0
Bin/Data/Scripts/Editor/EditorMaterial.as

@@ -4,6 +4,13 @@ Window@ materialWindow;
 Material@ editMaterial;
 XMLFile@ oldMaterialState;
 bool inMaterialRefresh = true;
+View3D@ materialPreview;
+Scene@ previewScene;
+Node@ previewCameraNode;
+Node@ previewLightNode;
+Light@ previewLight;
+Node@ previewModelNode;
+StaticModel@ previewModel;
 
 void CreateMaterialEditor()
 {
@@ -14,6 +21,7 @@ void CreateMaterialEditor()
     ui.root.AddChild(materialWindow);
     materialWindow.opacity = uiMaxOpacity;
 
+    InitMaterialPreview();
     RefreshMaterialEditor();
 
     int height = Min(ui.root.height - 60, 500);
@@ -53,6 +61,43 @@ void HideMaterialEditor()
     materialWindow.visible = false;
 }
 
+void InitMaterialPreview()
+{
+    previewScene = Scene("PreviewScene");
+    previewScene.CreateComponent("Octree");
+
+    Node@ zoneNode = previewScene.CreateChild("Zone");
+    Zone@ zone = zoneNode.CreateComponent("Zone");
+    zone.boundingBox = BoundingBox(-1000, 1000);
+    zone.ambientColor = Color(0.15, 0.15, 0.15);
+    zone.fogColor = Color(0, 0, 0);
+    zone.fogStart = 10.0;
+    zone.fogEnd = 100.0;
+
+    previewCameraNode = previewScene.CreateChild("PreviewCamera");
+    previewCameraNode.position = Vector3(0, 0, -1.5);
+    Camera@ camera = previewCameraNode.CreateComponent("Camera");
+    camera.nearClip = 0.1f;
+    camera.farClip = 100.0f;
+
+    previewLightNode = previewScene.CreateChild("PreviewLight");
+    previewLightNode.direction = Vector3(0.5, -0.5, 0.5);
+    previewLight = previewLightNode.CreateComponent("Light");
+    previewLight.lightType = LIGHT_DIRECTIONAL;
+    previewLight.specularIntensity = 0.5;
+
+    previewModelNode = previewScene.CreateChild("PreviewModel");
+    previewModelNode.rotation = Quaternion(0, 0, 0);
+    previewModel = previewModelNode.CreateComponent("StaticModel");
+    previewModel.model = cache.GetResource("Model", "Models/Sphere.mdl");
+
+    materialPreview = materialWindow.GetChild("MaterialPreview", true);
+    materialPreview.SetView(previewScene, camera);
+    materialPreview.autoUpdate = false;
+
+    SubscribeToEvent(materialPreview, "DragMove", "RotateMaterialPreview");
+}
+
 void EditMaterial(Material@ mat)
 {
     if (editMaterial !is null)
@@ -68,6 +113,7 @@ void EditMaterial(Material@ mat)
 
 void RefreshMaterialEditor()
 {
+    RefreshMaterialPreview();
     RefreshMaterialName();
     RefreshMaterialTechniques();
     RefreshMaterialTextures();
@@ -75,6 +121,12 @@ void RefreshMaterialEditor()
     RefreshMaterialMiscParameters();
 }
 
+void RefreshMaterialPreview()
+{
+    previewModel.material = editMaterial;
+    materialPreview.QueueUpdate();
+}
+
 void RefreshMaterialName()
 {
     UIElement@ container = materialWindow.GetChild("NameContainer");
@@ -266,6 +318,21 @@ void RefreshMaterialMiscParameters()
     inMaterialRefresh = false;
 }
 
+void RotateMaterialPreview(StringHash eventType, VariantMap& eventData)
+{
+    int elemX = eventData["ElementX"].GetInt();
+    int elemY = eventData["ElementY"].GetInt();
+    
+    if (materialPreview.height > 0 && materialPreview.width > 0)
+    {
+        float yaw = ((materialPreview.height / 2) - elemY) * (90.0 / materialPreview.height);
+        float pitch = ((materialPreview.width / 2) - elemX) * (90.0 / materialPreview.width);
+
+        previewModelNode.rotation = previewModelNode.rotation.Slerp(Quaternion(yaw, pitch, 0), 0.1);
+        materialPreview.QueueUpdate();
+    }
+}
+
 void EditMaterialName(StringHash eventType, VariantMap& eventData)
 {
     LineEdit@ nameEdit = eventData["Element"].GetUIElement();
@@ -741,4 +808,6 @@ void EndMaterialEdit()
     EditMaterialAction@ action = EditMaterialAction();
     action.Define(editMaterial, oldMaterialState);
     SaveEditAction(action);
+
+    materialPreview.QueueUpdate();
 }

+ 10 - 0
Bin/Data/UI/EditorMaterialWindow.xml

@@ -18,6 +18,16 @@
         </element>
     </element>
     <element type="BorderImage" style="EditorDivider" />
+    <element type="View3D">
+        <attribute name="Name" value="MaterialPreview" />
+        <attribute name="Texture" value="Texture2D;" />
+        <attribute name="Use Derived Opacity" value="false" />
+        <attribute name="Min Size" value="8 100" />
+        <attribute name="Is Resizable" value="true" />
+        <attribute name="Fixed Height Resizing" value="true" />
+        <attribute name="Resize Border" value="0 6 0 6" />
+    </element>
+    <element type="BorderImage" style="EditorDivider" />
     <element>
         <attribute name="Min Size" value="0 16" />
         <attribute name="Max Size" value="2147483647 16" />

+ 24 - 0
Source/Engine/Script/APITemplates.h

@@ -1033,6 +1033,30 @@ template <class T> void RegisterBorderImage(asIScriptEngine* engine, const char*
     engine->RegisterObjectMethod(className, "bool get_tiled() const", asMETHOD(T, IsTiled), asCALL_THISCALL);
 }
 
+/// Template function for registering a class derived from Window.
+template <class T> void RegisterWindow(asIScriptEngine* engine, const char* className)
+{
+    RegisterUIElement<T>(engine, className);
+    engine->RegisterObjectMethod(className, "void set_movable(bool)", asMETHOD(T, SetMovable), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "bool get_movable() const", asMETHOD(T, IsMovable), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_resizable(bool)", asMETHOD(T, SetResizable), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "bool get_resizable() const", asMETHOD(T, IsResizable), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_resizeBorder(const IntRect&in)", asMETHODPR(T, SetResizeBorder, (const IntRect&), void), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "const IntRect& get_resizeBorder() const", asMETHOD(T, GetResizeBorder), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_modal(bool)", asMETHOD(T, SetModal), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "bool get_modal() const", asMETHOD(T, IsModal), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_modalShadeColor(const Color&in)", asMETHOD(T, SetModalShadeColor), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "const Color& get_modalShadeColor() const", asMETHOD(T, GetModalShadeColor), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_modalFrameColor(const Color&in)", asMETHOD(T, SetModalFrameColor), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "const Color& get_modalFrameColor() const", asMETHOD(T, GetModalFrameColor), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_modalFrameSize(const IntVector2&in)", asMETHOD(T, SetModalFrameSize), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "const IntVector2& get_modalFrameSize() const", asMETHOD(T, GetModalFrameSize), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_fixedWidthResizing(bool)", asMETHOD(T, SetFixedWidthResizing), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "bool get_fixedWidthResizing() const", asMETHOD(T, GetFixedWidthResizing), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_fixedHeightResizing(bool)", asMETHOD(T, SetFixedHeightResizing), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "bool get_fixedHeightResizing() const", asMETHOD(T, GetFixedHeightResizing), asCALL_THISCALL);
+}
+
 /// Template function for registering a class derived from Button.
 template <class T> void RegisterButton(asIScriptEngine* engine, const char* className)
 {

+ 18 - 15
Source/Engine/Script/UIAPI.cpp

@@ -36,6 +36,7 @@
 #include "Text3D.h"
 #include "UI.h"
 #include "Window.h"
+#include "View3D.h"
 
 namespace Urho3D
 {
@@ -448,21 +449,22 @@ static void RegisterDropDownList(asIScriptEngine* engine)
 
 static void RegisterWindow(asIScriptEngine* engine)
 {
-    RegisterBorderImage<Window>(engine, "Window");
-    engine->RegisterObjectMethod("Window", "void set_movable(bool)", asMETHOD(Window, SetMovable), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "bool get_movable() const", asMETHOD(Window, IsMovable), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "void set_resizable(bool)", asMETHOD(Window, SetResizable), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "bool get_resizable() const", asMETHOD(Window, IsResizable), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "void set_resizeBorder(const IntRect&in)", asMETHODPR(Window, SetResizeBorder, (const IntRect&), void), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "const IntRect& get_resizeBorder() const", asMETHOD(Window, GetResizeBorder), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "void set_modal(bool)", asMETHOD(Window, SetModal), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "bool get_modal() const", asMETHOD(Window, IsModal), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "void set_modalShadeColor(const Color&in)", asMETHOD(Window, SetModalShadeColor), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "const Color& get_modalShadeColor() const", asMETHOD(Window, GetModalShadeColor), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "void set_modalFrameColor(const Color&in)", asMETHOD(Window, SetModalFrameColor), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "const Color& get_modalFrameColor() const", asMETHOD(Window, GetModalFrameColor), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "void set_modalFrameSize(const IntVector2&in)", asMETHOD(Window, SetModalFrameSize), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Window", "const IntVector2& get_modalFrameSize() const", asMETHOD(Window, GetModalFrameSize), asCALL_THISCALL);
+    RegisterWindow<Window>(engine, "Window");
+}
+
+static void RegisterView3D(asIScriptEngine* engine)
+{
+    RegisterWindow<View3D>(engine, "View3D");
+    engine->RegisterObjectMethod("View3D", "void SetView(Scene@+, Camera@+)", asMETHOD(View3D, SetView), asCALL_THISCALL);
+    engine->RegisterObjectMethod("View3D", "void QueueUpdate()", asMETHOD(View3D, QueueUpdate), asCALL_THISCALL);
+    engine->RegisterObjectMethod("View3D", "void set_format(uint)", asMETHOD(View3D, SetFormat), asCALL_THISCALL);
+    engine->RegisterObjectMethod("View3D", "uint get_format() const", asMETHOD(View3D, GetFormat), asCALL_THISCALL);
+    engine->RegisterObjectMethod("View3D", "void set_autoUpdate(bool)", asMETHOD(View3D, SetAutoUpdate), asCALL_THISCALL);
+    engine->RegisterObjectMethod("View3D", "bool get_autoUpdate() const", asMETHOD(View3D, GetAutoUpdate), asCALL_THISCALL);
+    engine->RegisterObjectMethod("View3D", "Texture2D@+ get_renderTexture() const", asMETHOD(View3D, GetRenderTexture), asCALL_THISCALL);
+    engine->RegisterObjectMethod("View3D", "Viewport@+ get_viewport() const", asMETHOD(View3D, GetViewport), asCALL_THISCALL);
+    engine->RegisterObjectMethod("View3D", "Scene@+ get_scene() const", asMETHOD(View3D, GetScene), asCALL_THISCALL);
+    engine->RegisterObjectMethod("View3D", "Node@+ get_cameraNode() const", asMETHOD(View3D, GetCameraNode), asCALL_THISCALL);
 }
 
 static void FileSelectorSetFilters(CScriptArray* filters, unsigned defaultIndex, FileSelector* ptr)
@@ -609,6 +611,7 @@ void RegisterUIAPI(asIScriptEngine* engine)
     RegisterMenu(engine);
     RegisterDropDownList(engine);
     RegisterWindow(engine);
+    RegisterView3D(engine);
     RegisterFileSelector(engine);
     RegisterUI(engine);
 }

+ 2 - 0
Source/Engine/UI/UI.cpp

@@ -51,6 +51,7 @@
 #include "UIEvents.h"
 #include "VertexBuffer.h"
 #include "Window.h"
+#include "View3D.h"
 
 #include "DebugNew.h"
 
@@ -1271,6 +1272,7 @@ void RegisterUILibrary(Context* context)
     Text::RegisterObject(context);
     Text3D::RegisterObject(context);
     Window::RegisterObject(context);
+    View3D::RegisterObject(context);
     LineEdit::RegisterObject(context);
     Slider::RegisterObject(context);
     ScrollBar::RegisterObject(context);

+ 122 - 0
Source/Engine/UI/View3D.cpp

@@ -0,0 +1,122 @@
+#include "Precompiled.h"
+#include "Context.h"
+#include "Camera.h"
+#include "Graphics.h"
+#include "Octree.h"
+#include "Scene.h"
+#include "Texture2D.h"
+#include "Viewport.h"
+#include "View3D.h"
+#include "UI.h"
+#include "UIEvents.h"
+#include "Zone.h"
+
+namespace Urho3D
+{
+
+extern const char* UI_CATEGORY;
+
+View3D::View3D(Context* context) :
+    Window(context),
+    rttFormat_(Graphics::GetRGBFormat()),
+    autoUpdate_(true)
+{
+    renderTexture_ = new Texture2D(context_);
+    viewport_ = new Viewport(context_);
+}
+
+View3D::~View3D()
+{
+}
+
+void View3D::RegisterObject(Context* context)
+{
+    context->RegisterFactory<View3D>(UI_CATEGORY);
+
+    COPY_BASE_ATTRIBUTES(View3D, Window);
+    // The texture format is API specific, so do not register it as a serializable attribute
+    ACCESSOR_ATTRIBUTE(View3D, VAR_BOOL, "Auto Update", GetAutoUpdate, SetAutoUpdate, bool, true, AM_FILE);
+    UPDATE_ATTRIBUTE_DEFAULT_VALUE(View3D, "Clip Children", true);
+    UPDATE_ATTRIBUTE_DEFAULT_VALUE(View3D, "Is Enabled", true);
+}
+
+void View3D::OnResize()
+{
+    int width = GetWidth();
+    int height = GetHeight();
+    
+    if (width > 0 && height >> 0)
+    {
+        renderTexture_->SetSize(width, height, rttFormat_, TEXTURE_RENDERTARGET);
+        RenderSurface* surface = renderTexture_->GetRenderSurface();
+        surface->SetViewport(0, viewport_);
+        surface->SetUpdateMode(autoUpdate_ ? SURFACE_UPDATEALWAYS : SURFACE_MANUALUPDATE);
+
+        SetTexture(renderTexture_);
+        SetImageRect(IntRect(0, 0, width, height));
+
+        if (!autoUpdate_)
+            surface->QueueUpdate();
+    }
+}
+
+void View3D::SetView(Scene* scene, Camera* camera)
+{
+    scene_ = scene;
+    cameraNode_ = camera ? camera->GetNode() : 0;
+    
+    viewport_->SetScene(scene_);
+    viewport_->SetCamera(camera);
+}
+
+void View3D::SetFormat(unsigned format)
+{
+    if (format != rttFormat_)
+    {
+        rttFormat_ = format;
+        OnResize();
+    }
+}
+
+void View3D::SetAutoUpdate(bool enable)
+{
+    if (enable != autoUpdate_)
+    {
+        autoUpdate_ = enable;
+        RenderSurface* surface = renderTexture_->GetRenderSurface();
+        if (surface)
+            surface->SetUpdateMode(autoUpdate_ ? SURFACE_UPDATEALWAYS : SURFACE_MANUALUPDATE);
+    }
+}
+
+void View3D::QueueUpdate()
+{
+    if (!autoUpdate_)
+    {
+        RenderSurface* surface = renderTexture_->GetRenderSurface();
+        if (surface)
+            surface->QueueUpdate();
+    }
+}
+
+Scene* View3D::GetScene() const
+{
+    return scene_;
+}
+
+Node* View3D::GetCameraNode() const
+{
+    return cameraNode_;
+}
+
+Texture2D* View3D::GetRenderTexture() const
+{
+    return renderTexture_;
+}
+
+Viewport* View3D::GetViewport() const
+{
+    return viewport_;
+}
+
+}

+ 66 - 0
Source/Engine/UI/View3D.h

@@ -0,0 +1,66 @@
+#pragma once
+
+#include "Window.h"
+
+namespace Urho3D
+{
+
+class Camera;
+class Node;
+class Scene;
+class Texture2D;
+class Viewport;
+
+/// %UI element which renders a 3D scene.
+class URHO3D_API View3D : public Window
+{
+    OBJECT(View3D);
+
+public:
+    /// Construct.
+    View3D(Context* context);
+    /// Destruct.
+    ~View3D();
+    /// Register object factory.
+    static void RegisterObject(Context* context);
+
+    /// React to resize.
+    virtual void OnResize();
+
+    /// Define the scene and camera to use in rendering. The View3D will take ownership of them with shared pointers.
+    void SetView(Scene* scene, Camera* camera);
+    /// Set render texture pixel format. Default is RGB.
+    void SetFormat(unsigned format);
+    /// Set render target auto update mode. Default is true.
+    void SetAutoUpdate(bool enable);
+    /// Queue manual update on the render texture.
+    void QueueUpdate();
+    
+    /// Return render texture pixel format.
+    unsigned GetFormat() const { return rttFormat_; }
+    /// Return whether render target updates automatically.
+    bool GetAutoUpdate() const { return autoUpdate_; }
+    /// Return scene.
+    Scene* GetScene() const;
+    /// Return camera scene node.
+    Node* GetCameraNode() const;
+    /// Return render texture.
+    Texture2D* GetRenderTexture() const;
+    /// Return viewport.
+    Viewport* GetViewport() const;
+    
+    /// Renderable texture.
+    SharedPtr<Texture2D> renderTexture_;
+    /// Viewport.
+    SharedPtr<Viewport> viewport_;
+    /// Scene.
+    SharedPtr<Scene> scene_;
+    /// Camera scene node.
+    SharedPtr<Node> cameraNode_;
+    /// Render texture format.
+    unsigned rttFormat_;
+    /// Render texture auto update mode.
+    bool autoUpdate_;
+};
+
+}

+ 35 - 8
Source/Engine/UI/Window.cpp

@@ -41,6 +41,8 @@ Window::Window(Context* context) :
     BorderImage(context),
     movable_(false),
     resizable_(false),
+    fixedWidthResizing_(false),
+    fixedHeightResizing_(false),
     resizeBorder_(DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER),
     dragMode_(DRAG_NONE),
     modal_(false),
@@ -70,6 +72,8 @@ void Window::RegisterObject(Context* context)
         DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER), AM_FILE);
     ACCESSOR_ATTRIBUTE(Window, VAR_BOOL, "Is Movable", IsMovable, SetMovable, bool, false, AM_FILE);
     ACCESSOR_ATTRIBUTE(Window, VAR_BOOL, "Is Resizable", IsResizable, SetResizable, bool, false, AM_FILE);
+    ACCESSOR_ATTRIBUTE(Window, VAR_BOOL, "Fixed Width Resizing", GetFixedWidthResizing, SetFixedWidthResizing, bool, false, AM_FILE);
+    ACCESSOR_ATTRIBUTE(Window, VAR_BOOL, "Fixed Height Resizing", GetFixedHeightResizing, SetFixedHeightResizing, bool, false, AM_FILE);
     ACCESSOR_ATTRIBUTE(Window, VAR_BOOL, "Is Modal", IsModal, SetModal, bool, false, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Window, VAR_COLOR, "Modal Shade Color", GetModalShadeColor, SetModalShadeColor, Color, Color::TRANSPARENT, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Window, VAR_COLOR, "Modal Frame Color", GetModalFrameColor, SetModalFrameColor, Color, Color::TRANSPARENT, AM_FILE);
@@ -137,6 +141,7 @@ void Window::OnDragMove(const IntVector2& position, const IntVector2& screenPosi
         return;
 
     IntVector2 delta = screenPosition - dragBeginCursor_;
+    IntVector2 dragSize;
 
     const IntVector2& position_ = GetPosition();
     const IntVector2& size_ = GetSize();
@@ -152,39 +157,51 @@ void Window::OnDragMove(const IntVector2& position, const IntVector2& screenPosi
     case DRAG_RESIZE_TOPLEFT:
         SetPosition(Clamp(dragBeginPosition_.x_ + delta.x_, position_.x_ - (maxSize_.x_ - size_.x_), position_.x_ + (size_.x_ - minSize_.x_)),
             Clamp(dragBeginPosition_.y_ + delta.y_, position_.y_ - (maxSize_.y_ - size_.y_), position_.y_ + (size_.y_ - minSize_.y_)));
-        SetSize(dragBeginSize_ - delta);
+        dragSize = dragBeginSize_ - delta;
+        fixedWidthResizing_ ? SetFixedWidth(dragSize.x_) : SetWidth(dragSize.x_);
+        fixedHeightResizing_ ? SetFixedHeight(dragSize.y_) : SetHeight(dragSize.y_);
         break;
 
     case DRAG_RESIZE_TOP:
         SetPosition(dragBeginPosition_.x_, Clamp(dragBeginPosition_.y_ + delta.y_, position_.y_ - (maxSize_.y_ - size_.y_), position_.y_ + (size_.y_ - minSize_.y_)));
-        SetSize(dragBeginSize_.x_, dragBeginSize_.y_ - delta.y_);
+        dragSize = IntVector2(dragBeginSize_.x_, dragBeginSize_.y_ - delta.y_);
+        fixedHeightResizing_ ? SetFixedHeight(dragSize.y_) : SetHeight(dragSize.y_);
         break;
 
     case DRAG_RESIZE_TOPRIGHT:
         SetPosition(dragBeginPosition_.x_, dragBeginPosition_.y_ + delta.y_);
-        SetSize(dragBeginSize_.x_ + delta.x_, dragBeginSize_.y_ - delta.y_);
+        dragSize = IntVector2(dragBeginSize_.x_ + delta.x_, dragBeginSize_.y_ - delta.y_);
+        fixedWidthResizing_ ? SetFixedWidth(dragSize.x_) : SetWidth(dragSize.x_);
+        fixedHeightResizing_ ? SetFixedHeight(dragSize.y_) : SetHeight(dragSize.y_);
         break;
 
     case DRAG_RESIZE_RIGHT:
-        SetSize(dragBeginSize_.x_ + delta.x_, dragBeginSize_.y_);
+        dragSize = IntVector2(dragBeginSize_.x_ + delta.x_, dragBeginSize_.y_);
+        fixedWidthResizing_ ? SetFixedWidth(dragSize.x_) : SetWidth(dragSize.x_);
         break;
 
     case DRAG_RESIZE_BOTTOMRIGHT:
-        SetSize(dragBeginSize_ + delta);
+        dragSize = dragBeginSize_ + delta;
+        fixedWidthResizing_ ? SetFixedWidth(dragSize.x_) : SetWidth(dragSize.x_);
+        fixedHeightResizing_ ? SetFixedHeight(dragSize.y_) : SetHeight(dragSize.y_);
         break;
 
     case DRAG_RESIZE_BOTTOM:
-        SetSize(dragBeginSize_.x_, dragBeginSize_.y_ + delta.y_);
+        dragSize = IntVector2(dragBeginSize_.x_, dragBeginSize_.y_ + delta.y_);
+        fixedHeightResizing_ ? SetFixedHeight(dragSize.y_) : SetHeight(dragSize.y_);
         break;
 
     case DRAG_RESIZE_BOTTOMLEFT:
         SetPosition(Clamp(dragBeginPosition_.x_ + delta.x_, position_.x_ - (maxSize_.x_ - size_.x_), position_.x_ + (size_.x_ - minSize_.x_)), dragBeginPosition_.y_);
-        SetSize(dragBeginSize_.x_ - delta.x_, dragBeginSize_.y_ + delta.y_);
+        dragSize = IntVector2(dragBeginSize_.x_ - delta.x_, dragBeginSize_.y_ + delta.y_);
+        fixedWidthResizing_ ? SetFixedWidth(dragSize.x_) : SetWidth(dragSize.x_);
+        fixedHeightResizing_ ? SetFixedHeight(dragSize.y_) : SetHeight(dragSize.y_);
         break;
 
     case DRAG_RESIZE_LEFT:
         SetPosition(Clamp(dragBeginPosition_.x_ + delta.x_, position_.x_ - (maxSize_.x_ - size_.x_), position_.x_ + (size_.x_ - minSize_.x_)), dragBeginPosition_.y_);
-        SetSize(dragBeginSize_.x_ - delta.x_, dragBeginSize_.y_);
+        dragSize = IntVector2(dragBeginSize_.x_ - delta.x_, dragBeginSize_.y_);
+        fixedWidthResizing_ ? SetFixedWidth(dragSize.x_) : SetWidth(dragSize.x_);
         break;
 
     default:
@@ -210,6 +227,16 @@ void Window::SetResizable(bool enable)
     resizable_ = enable;
 }
 
+void Window::SetFixedWidthResizing(bool enable)
+{
+    fixedWidthResizing_ = enable;
+}
+
+void Window::SetFixedHeightResizing(bool enable)
+{
+    fixedHeightResizing_ = enable;
+}
+
 void Window::SetResizeBorder(const IntRect& rect)
 {
     resizeBorder_.left_ = Max(rect.left_, 0);

+ 12 - 0
Source/Engine/UI/Window.h

@@ -71,6 +71,10 @@ public:
     void SetMovable(bool enable);
     /// Set whether can be resized.
     void SetResizable(bool enable);
+    /// Set whether resizing width is fixed.
+    void SetFixedWidthResizing(bool enable);
+    /// Set whether resizing height is fixed.
+    void SetFixedHeightResizing(bool enable);
     /// Set resize area width at edges.
     void SetResizeBorder(const IntRect& rect);
     /// Set modal flag. When the modal flag is set, the focused window needs to be dismissed first to allow other UI elements to gain focus.
@@ -86,6 +90,10 @@ public:
     bool IsMovable() const { return movable_; }
     /// Return whether is resizable.
     bool IsResizable() const { return resizable_; }
+    /// Return whether is resizing width is fixed.
+    bool GetFixedWidthResizing() const { return fixedWidthResizing_; }
+    /// Return whether is resizing height is fixed.
+    bool GetFixedHeightResizing() const { return fixedHeightResizing_; }
     /// Return resize area width at edges.
     const IntRect& GetResizeBorder() const { return resizeBorder_; }
     /// Return modal flag.
@@ -111,6 +119,10 @@ protected:
     bool movable_;
     /// Resizable flag.
     bool resizable_;
+    /// Fixed width resize flag.
+    bool fixedWidthResizing_;
+    /// Fixed height resize flag.
+    bool fixedHeightResizing_;
     /// Resize area width at edges.
     IntRect resizeBorder_;
     /// Current drag mode.

+ 22 - 0
Source/Extras/LuaScript/pkgs/UI/View3D.pkg

@@ -0,0 +1,22 @@
+$#include "View3D.h"
+
+class View3D : public Window
+{
+    View3D(Context* context);
+    ~View3D();
+
+    void SetView(Scene* scene, Camera* camera);
+    void SetFormat(unsigned format);
+    void SetAutoUpdate(bool enable);
+    void QueueUpdate();
+    
+    unsigned GetFormat() const;
+    bool GetAutoUpdate() const;
+    Scene* GetScene() const;
+    Node* GetCameraNode() const;
+    Texture2D* GetRenderTexture() const;
+    Viewport* GetViewport() const;
+    
+    tolua_property__get_set unsigned format;
+    tolua_property__get_set bool autoUpdate;
+};

+ 6 - 0
Source/Extras/LuaScript/pkgs/UI/Window.pkg

@@ -21,6 +21,8 @@ class Window : public BorderImage
     
     void SetMovable(bool enable);
     void SetResizable(bool enable);
+    void SetFixedWidthResizing(bool enable);
+    void SetFixedHeightResizing(bool enable);
     void SetResizeBorder(const IntRect& rect);
     void SetModal(bool modal);
     void SetModalShadeColor(const Color& color);
@@ -29,6 +31,8 @@ class Window : public BorderImage
 
     bool IsMovable() const;
     bool IsResizable() const;
+    bool GetFixedWidthResizing() const;
+    bool GetFixedHeightResizing() const;
     const IntRect& GetResizeBorder() const;
     bool IsModal() const;
     const Color& GetModalShadeColor() const;
@@ -37,6 +41,8 @@ class Window : public BorderImage
     
     tolua_property__is_set bool movable;
     tolua_property__is_set bool resizable;
+    tolua_property__get_set bool fixedWidthResizing;
+    tolua_property__get_set bool fixedHeightResizing;
     tolua_property__get_set IntRect& resizeBorder;
     tolua_property__is_set bool modal;
     tolua_property__get_set Color& modalShadeColor;

+ 1 - 0
Source/Extras/LuaScript/pkgs/UILuaAPI.pkg

@@ -19,6 +19,7 @@ $pfile "UI/Text3D.pkg"
 $pfile "UI/UI.pkg"
 $pfile "UI/UIElement.pkg"
 $pfile "UI/Window.pkg"
+$pfile "UI/View3D.pkg"
 
 $using namespace Urho3D;
 $#pragma warning(disable:4800)