diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 04cd8b3f2130f7c616fc2e480c6df471a54f3298..54e4d296abc5cca55b1cb5c0d26710797ccb30d4 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -133,6 +133,7 @@ set(llui_SOURCE_FILES
     llview.cpp
     llviewquery.cpp
     llviewereventrecorder.cpp
+    llvirtualtrackball.cpp
     llwindowshade.cpp
     llxuiparser.cpp
     llxyvector.cpp
@@ -250,6 +251,7 @@ set(llui_HEADER_FILES
     llview.h
     llviewereventrecorder.h
     llviewquery.h
+    llvirtualtrackball.h
     llwindowshade.h
     llxuiparser.h
     llxyvector.h
diff --git a/indra/llui/llvirtualtrackball.cpp b/indra/llui/llvirtualtrackball.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0ddbe8b9c2424065b3e9c34881d13383aa321543
--- /dev/null
+++ b/indra/llui/llvirtualtrackball.cpp
@@ -0,0 +1,411 @@
+/**
+* @file LLVirtualTrackball.cpp
+* @author Andrey Lihatskiy
+* @brief Implementation for LLVirtualTrackball
+*
+* $LicenseInfo:firstyear=2001&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2018, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+// A control for positioning the sun and the moon in the celestial sphere.
+
+#include "linden_common.h"
+#include "llvirtualtrackball.h"
+#include "llstring.h"
+#include "llrect.h"
+#include "lluictrlfactory.h"
+#include "llrender.h"
+
+// Globals
+static LLDefaultChildRegistry::Register<LLVirtualTrackball> register_virtual_trackball("sun_moon_trackball");
+
+const LLVector3 VectorZero(1.0f, 0.0f, 0.0f);
+
+LLVirtualTrackball::Params::Params()
+  : border("border"),
+    image_moon_back("image_moon_back"),
+    image_moon_front("image_moon_front"),
+    image_sphere("image_sphere"),
+    image_sun_back("image_sun_back"),
+    image_sun_front("image_sun_front"),
+    btn_rotate_top("button_rotate_top"),
+    btn_rotate_bottom("button_rotate_bottom"),
+    btn_rotate_left("button_rotate_left"),
+    btn_rotate_right("button_rotate_right"),
+    thumb_mode("thumb_mode"),
+    lbl_N("labelN"),
+    lbl_S("labelS"),
+    lbl_W("labelW"),
+    lbl_E("labelE"),
+    increment_angle_mouse("increment_angle_mouse", 0.5f),
+    increment_angle_btn("increment_angle_btn", 3.0f)
+{
+}
+
+LLVirtualTrackball::LLVirtualTrackball(const LLVirtualTrackball::Params& p)
+  : LLUICtrl(p),
+    mImgMoonBack(p.image_moon_back),
+    mImgMoonFront(p.image_moon_front),
+    mImgSunBack(p.image_sun_back),
+    mImgSunFront(p.image_sun_front),
+    mImgSphere(p.image_sphere),
+    mThumbMode(p.thumb_mode() == "moon" ? ThumbMode::MOON : ThumbMode::SUN),
+    mIncrementMouse(DEG_TO_RAD * p.increment_angle_mouse()),
+    mIncrementBtn(DEG_TO_RAD * p.increment_angle_btn())
+{
+    LLRect border_rect = getLocalRect();
+    S32 centerX = border_rect.getCenterX();
+    S32 centerY = border_rect.getCenterY();
+    U32 btn_size = 32; // width & height
+    U32 axis_offset_lt = 16; // offset from the axis for left/top sides
+    U32 axis_offset_rb = btn_size - axis_offset_lt; //  and for right/bottom
+
+    LLViewBorder::Params border = p.border;
+    border.rect(border_rect);
+    mBorder = LLUICtrlFactory::create<LLViewBorder>(border);
+    addChild(mBorder);
+
+    
+    LLButton::Params btn_rt = p.btn_rotate_top;
+    btn_rt.rect(LLRect(centerX - axis_offset_lt, border_rect.mTop, centerX + axis_offset_rb, border_rect.mTop - btn_size));
+    btn_rt.click_callback.function(boost::bind(&LLVirtualTrackball::onRotateTopClick, this));
+    btn_rt.mouse_held_callback.function(boost::bind(&LLVirtualTrackball::onRotateTopClick, this));
+    mBtnRotateTop = LLUICtrlFactory::create<LLButton>(btn_rt);
+    addChild(mBtnRotateTop);
+
+    LLTextBox::Params lbl_N = p.lbl_N;
+    LLRect rect_N = btn_rt.rect;
+    //rect_N.translate(btn_rt.rect().getWidth(), 0);
+    lbl_N.rect = rect_N;
+    lbl_N.initial_value(lbl_N.label());
+    mLabelN = LLUICtrlFactory::create<LLTextBox>(lbl_N);
+    addChild(mLabelN);
+
+
+    LLButton::Params btn_rr = p.btn_rotate_right;
+    btn_rr.rect(LLRect(border_rect.mRight - btn_size, centerY + axis_offset_lt, border_rect.mRight, centerY - axis_offset_rb));
+    btn_rr.click_callback.function(boost::bind(&LLVirtualTrackball::onRotateRightClick, this));
+    btn_rr.mouse_held_callback.function(boost::bind(&LLVirtualTrackball::onRotateRightClick, this));
+    mBtnRotateRight = LLUICtrlFactory::create<LLButton>(btn_rr);
+    addChild(mBtnRotateRight);
+
+    LLTextBox::Params lbl_E = p.lbl_E;
+    LLRect rect_E = btn_rr.rect;
+    //rect_E.translate(0, -1 * btn_rr.rect().getHeight());
+    lbl_E.rect = rect_E;
+    lbl_E.initial_value(lbl_E.label());
+    mLabelE = LLUICtrlFactory::create<LLTextBox>(lbl_E);
+    addChild(mLabelE);
+
+
+    LLButton::Params btn_rb = p.btn_rotate_bottom;
+    btn_rb.rect(LLRect(centerX - axis_offset_lt, border_rect.mBottom + btn_size, centerX + axis_offset_rb, border_rect.mBottom));
+    btn_rb.click_callback.function(boost::bind(&LLVirtualTrackball::onRotateBottomClick, this));
+    btn_rb.mouse_held_callback.function(boost::bind(&LLVirtualTrackball::onRotateBottomClick, this));
+    mBtnRotateBottom = LLUICtrlFactory::create<LLButton>(btn_rb);
+    addChild(mBtnRotateBottom);
+
+    LLTextBox::Params lbl_S = p.lbl_S;
+    LLRect rect_S = btn_rb.rect;
+    //rect_S.translate(btn_rb.rect().getWidth(), 0);
+    lbl_S.rect = rect_S;
+    lbl_S.initial_value(lbl_S.label());
+    mLabelS = LLUICtrlFactory::create<LLTextBox>(lbl_S);
+    addChild(mLabelS);
+
+
+    LLButton::Params btn_rl = p.btn_rotate_left;
+    btn_rl.rect(LLRect(border_rect.mLeft, centerY + axis_offset_lt, border_rect.mLeft + btn_size, centerY - axis_offset_rb));
+    btn_rl.click_callback.function(boost::bind(&LLVirtualTrackball::onRotateLeftClick, this));
+    btn_rl.mouse_held_callback.function(boost::bind(&LLVirtualTrackball::onRotateLeftClick, this));
+    mBtnRotateLeft = LLUICtrlFactory::create<LLButton>(btn_rl);
+    addChild(mBtnRotateLeft);
+
+    LLTextBox::Params lbl_W = p.lbl_W;
+    LLRect rect_W = btn_rl.rect;
+    //rect_W.translate(0, -1* btn_rl.rect().getHeight());
+    lbl_W.rect = rect_W;
+    lbl_W.initial_value(lbl_W.label());
+    mLabelW = LLUICtrlFactory::create<LLTextBox>(lbl_W);
+    addChild(mLabelW);
+
+
+    LLPanel::Params touch_area;
+    touch_area.rect = LLRect(centerX - mImgSphere->getWidth() / 2,
+                             centerY + mImgSphere->getHeight() / 2,
+                             centerX + mImgSphere->getWidth() / 2,
+                             centerY - mImgSphere->getHeight() / 2);
+    mTouchArea = LLUICtrlFactory::create<LLPanel>(touch_area);
+    addChild(mTouchArea);
+}
+
+LLVirtualTrackball::~LLVirtualTrackball()
+{
+}
+
+BOOL LLVirtualTrackball::postBuild()
+{
+    return TRUE;
+}
+
+
+void LLVirtualTrackball::drawThumb(S32 x, S32 y, ThumbMode mode, bool upperHemi)
+{
+    LLUIImage* thumb;
+    if (mode == ThumbMode::SUN)
+    {
+        if (upperHemi)
+        {
+            thumb = mImgSunFront;
+        }
+        else
+        {
+            thumb = mImgSunBack;
+        }
+    }
+    else
+    {
+        if (upperHemi)
+        {
+            thumb = mImgMoonFront;
+        }
+        else
+        {
+            thumb = mImgMoonBack;
+        }
+    }
+    thumb->draw(LLRect(x - thumb->getWidth() / 2,
+                       y + thumb->getHeight() / 2,
+                       x + thumb->getWidth() / 2,
+                       y - thumb->getHeight() / 2));
+}
+
+bool LLVirtualTrackball::pointInTouchCircle(S32 x, S32 y) const
+{
+    S32 centerX = mTouchArea->getRect().getCenterX();
+    S32 centerY = mTouchArea->getRect().getCenterY();
+
+    bool in_circle = pow(x - centerX, 2) + pow(y - centerY, 2) <= pow(mTouchArea->getRect().getWidth() / 2, 2);
+    return in_circle;
+}
+
+void LLVirtualTrackball::draw()
+{
+    LLVector3 draw_point = VectorZero * mValue;
+
+    S32 halfwidth = mTouchArea->getRect().getWidth() / 2;
+    S32 halfheight = mTouchArea->getRect().getHeight() / 2;
+    draw_point.mV[VX] = (draw_point.mV[VX] + 1.0) * halfwidth + mTouchArea->getRect().mLeft;
+    draw_point.mV[VY] = (draw_point.mV[VY] + 1.0) * halfheight + mTouchArea->getRect().mBottom;
+    bool upper_hemisphere = (draw_point.mV[VZ] >= 0.f);
+
+    mImgSphere->draw(mTouchArea->getRect(), upper_hemisphere ? UI_VERTEX_COLOR : UI_VERTEX_COLOR % 0.5f);
+    drawThumb(draw_point.mV[VX], draw_point.mV[VY], mThumbMode, upper_hemisphere);
+
+
+    if (LLView::sDebugRects)
+    {
+        gGL.color4fv(LLColor4::red.mV);
+        gl_circle_2d(mTouchArea->getRect().getCenterX(), mTouchArea->getRect().getCenterY(), mImgSphere->getWidth() / 2, 60, false);
+        gl_circle_2d(draw_point.mV[VX], draw_point.mV[VY], mImgSunFront->getWidth() / 2, 12, false);
+    }
+
+    LLView::draw();
+}
+
+void LLVirtualTrackball::onRotateTopClick()
+{
+    if (getEnabled())
+    {
+        LLQuaternion delta;
+        delta.setAngleAxis(mIncrementBtn, 1, 0, 0); 
+        mValue *= delta;
+        setValueAndCommit(mValue);
+
+        make_ui_sound("UISndClick");
+    }
+}
+
+void LLVirtualTrackball::onRotateBottomClick()
+{
+    if (getEnabled())
+    {
+        LLQuaternion delta;
+        delta.setAngleAxis(mIncrementBtn, -1, 0, 0);
+        mValue *= delta;
+        setValueAndCommit(mValue);
+
+        make_ui_sound("UISndClick");
+    }
+}
+
+void LLVirtualTrackball::onRotateLeftClick()
+{
+    if (getEnabled())
+    {
+        LLQuaternion delta;
+        delta.setAngleAxis(mIncrementBtn, 0, 1, 0);
+        mValue *= delta;
+        setValueAndCommit(mValue);
+
+        make_ui_sound("UISndClick");
+    }
+}
+
+void LLVirtualTrackball::onRotateRightClick()
+{
+    if (getEnabled())
+    {
+        LLQuaternion delta;
+        delta.setAngleAxis(mIncrementBtn, 0, -1, 0);
+        mValue *= delta;
+        setValueAndCommit(mValue);
+
+        make_ui_sound("UISndClick");
+    }
+}
+
+void LLVirtualTrackball::setValue(const LLSD& value)
+{
+	if (value.isArray() && value.size() == 4)
+    {
+        mValue.setValue(value);
+    }
+}
+
+void LLVirtualTrackball::setRotation(const LLQuaternion &value)
+{
+    mValue = value;
+}
+
+void LLVirtualTrackball::setValue(F32 x, F32 y, F32 z, F32 w)
+{
+    mValue.set(x, y, z, w);
+}
+
+void LLVirtualTrackball::setValueAndCommit(const LLQuaternion &value)
+{
+	mValue = value;
+    onCommit();
+}
+
+LLSD LLVirtualTrackball::getValue() const
+{
+    return mValue.getValue();
+}
+
+LLQuaternion LLVirtualTrackball::getRotation() const
+{
+	return mValue;
+}
+
+BOOL LLVirtualTrackball::handleHover(S32 x, S32 y, MASK mask)
+{
+    if (hasMouseCapture())
+    {
+        LLQuaternion delta;
+
+        F32 rotX = x - mPrevX;
+        F32 rotY = y - mPrevY;
+
+        if (abs(rotX) > 1)
+        {
+            F32 direction = (rotX < 0) ? -1 : 1;
+            delta.setAngleAxis(mIncrementMouse * abs(rotX), 0, direction, 0);  // changing X - rotate around Y axis
+            mValue *= delta;
+        }
+
+        if (abs(rotY) > 1)
+        {
+            F32 direction = (rotY < 0) ? 1 : -1; // reverse for Y (value increases from bottom to top)
+            delta.setAngleAxis(mIncrementMouse * abs(rotY), direction, 0, 0);  // changing Y - rotate around X axis
+            mValue *= delta;
+        }
+        
+        onCommit();
+
+        mPrevX = x;
+        mPrevY = y;
+    }
+    return TRUE;
+}
+
+BOOL LLVirtualTrackball::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+    if (hasMouseCapture())
+    {
+        mPrevX = 0;
+        mPrevY = 0;
+        gFocusMgr.setMouseCapture(NULL);
+        make_ui_sound("UISndClickRelease");
+    }
+    return TRUE;
+}
+
+BOOL LLVirtualTrackball::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+    if (pointInTouchCircle(x, y))
+    {
+        mPrevX = x;
+        mPrevY = y;
+        gFocusMgr.setMouseCapture(this);
+        make_ui_sound("UISndClick");
+    }
+    return TRUE;
+}
+
+BOOL LLVirtualTrackball::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+    if (pointInTouchCircle(x, y))
+    {
+
+        //make_ui_sound("UISndClick");
+    }
+    return TRUE;
+}
+
+BOOL LLVirtualTrackball::handleKeyHere(KEY key, MASK mask)
+{
+    BOOL handled = FALSE;
+    switch (key)
+    {
+    case KEY_DOWN:
+        onRotateTopClick();
+        handled = TRUE;
+        break;
+    case KEY_LEFT:
+        onRotateRightClick();
+        handled = TRUE;
+        break;
+    case KEY_UP:
+        onRotateBottomClick();
+        handled = TRUE;
+        break;
+    case KEY_RIGHT:
+        onRotateLeftClick();
+        handled = TRUE;
+        break;
+    default:
+        break;
+    }
+    return handled;
+}
+
diff --git a/indra/llui/llvirtualtrackball.h b/indra/llui/llvirtualtrackball.h
new file mode 100644
index 0000000000000000000000000000000000000000..c1b66550bbb43d91979af2791d95617838150c25
--- /dev/null
+++ b/indra/llui/llvirtualtrackball.h
@@ -0,0 +1,149 @@
+/**
+* @file virtualtrackball.h
+* @author Andrey Lihatskiy
+* @brief Header file for LLVirtualTrackball
+*
+* $LicenseInfo:firstyear=2001&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2018, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+// A control for positioning the sun and the moon in the celestial sphere.
+
+#ifndef LL_LLVIRTUALTRACKBALL_H
+#define LL_LLVIRTUALTRACKBALL_H
+
+#include "lluictrl.h"
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "llbutton.h"
+
+class LLVirtualTrackball
+    : public LLUICtrl
+{
+public:
+    enum ThumbMode
+    {
+        SUN,
+        MOON
+    };
+
+    struct Params
+        : public LLInitParam::Block<Params, LLUICtrl::Params>
+    {
+        Optional<LLViewBorder::Params>	    border;
+        Optional<LLUIImage*>                image_moon_back,
+            image_moon_front,
+            image_sphere,
+            image_sun_back,
+            image_sun_front;
+
+        Optional<std::string>               thumb_mode;
+        Optional<F32>                       increment_angle_mouse,
+            increment_angle_btn;
+
+        Optional<LLTextBox::Params>         lbl_N,
+            lbl_S,
+            lbl_W,
+            lbl_E;
+
+        Optional<LLButton::Params>          btn_rotate_top,
+            btn_rotate_bottom,
+            btn_rotate_left,
+            btn_rotate_right;
+
+        Params();
+    };
+
+
+    virtual ~LLVirtualTrackball();
+    /*virtual*/ BOOL postBuild();
+
+    virtual BOOL    handleHover(S32 x, S32 y, MASK mask);
+    virtual BOOL    handleMouseUp(S32 x, S32 y, MASK mask);
+    virtual BOOL    handleMouseDown(S32 x, S32 y, MASK mask);
+    virtual BOOL    handleRightMouseDown(S32 x, S32 y, MASK mask);
+    virtual BOOL    handleKeyHere(KEY key, MASK mask);
+
+    virtual void    draw();
+
+    virtual void    setValue(const LLSD& value);
+    void            setValue(F32 x, F32 y, F32 z, F32 w);
+    virtual LLSD    getValue() const;
+
+    void            setRotation(const LLQuaternion &value);
+    LLQuaternion    getRotation() const;
+
+protected:
+    friend class LLUICtrlFactory;
+    LLVirtualTrackball(const Params&);
+    void onEditChange();
+
+protected:
+    LLTextBox*          mNLabel;
+    LLTextBox*          mELabel;
+    LLTextBox*          mSLabel;
+    LLTextBox*          mWLabel;
+
+    LLButton*           mBtnRotateTop;
+    LLButton*           mBtnRotateBottom;
+    LLButton*           mBtnRotateLeft;
+    LLButton*           mBtnRotateRight;
+
+    LLTextBox*          mLabelN;
+    LLTextBox*          mLabelS;
+    LLTextBox*          mLabelW;
+    LLTextBox*          mLabelE;
+
+    LLPanel*            mTouchArea;
+    LLViewBorder*       mBorder;
+
+private:
+    void setValueAndCommit(const LLQuaternion &value);
+    void drawThumb(S32 x, S32 y, ThumbMode mode, bool upperHemi = true);
+    bool pointInTouchCircle(S32 x, S32 y) const;
+
+    void onRotateTopClick();
+    void onRotateBottomClick();
+    void onRotateLeftClick();
+    void onRotateRightClick();
+
+    S32 mPrevX;
+    S32 mPrevY;
+
+    LLUIImage*     mImgMoonBack;
+    LLUIImage*     mImgMoonFront;
+    LLUIImage*     mImgSunBack;
+    LLUIImage*     mImgSunFront;
+    LLUIImage*     mImgBtnRotTop;
+    LLUIImage*     mImgBtnRotLeft;
+    LLUIImage*     mImgBtnRotRight;
+    LLUIImage*     mImgBtnRotBottom;
+    LLUIImage*     mImgSphere;
+
+    LLQuaternion   mValue;
+    ThumbMode      mThumbMode;
+
+    F32            mIncrementMouse;
+    F32            mIncrementBtn;
+};
+
+#endif
+
diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp
index 41d351b4812deb81a22a891206bffdbbd6f2e416..87c0a21c423b841100238886b9d1f07ee4ce5b9e 100644
--- a/indra/newview/llpaneleditsky.cpp
+++ b/indra/newview/llpaneleditsky.cpp
@@ -31,7 +31,8 @@
 #include "llslider.h"
 #include "lltexturectrl.h"
 #include "llcolorswatch.h"
-#include "lljoystickbutton.h"
+#include "llvirtualtrackball.h"
+
 
 namespace
 {   
@@ -369,9 +370,9 @@ void LLPanelSettingsSkySunMoonTab::refresh()
     getChild<LLUICtrl>(FIELD_SKY_GLOW_SIZE)->setValue(2.0 - (glow.mV[0] / SLIDER_SCALE_GLOW_R));
     getChild<LLUICtrl>(FIELD_SKY_GLOW_FOCUS)->setValue(glow.mV[2] / SLIDER_SCALE_GLOW_B);
     getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->setValue(mSkySettings->getStarBrightness());
-    getChild<LLJoystickQuaternion>(FIELD_SKY_SUN_ROTATION)->setRotation(mSkySettings->getSunRotation());
+    getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->setRotation(mSkySettings->getSunRotation());
     getChild<LLTextureCtrl>(FIELD_SKY_SUN_IMAGE)->setValue(mSkySettings->getSunTextureId());
-    getChild<LLJoystickQuaternion>(FIELD_SKY_MOON_ROTATION)->setRotation(mSkySettings->getMoonRotation());
+    getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->setRotation(mSkySettings->getMoonRotation());
     getChild<LLTextureCtrl>(FIELD_SKY_MOON_IMAGE)->setValue(mSkySettings->getMoonTextureId());
 }
 
@@ -402,7 +403,7 @@ void LLPanelSettingsSkySunMoonTab::onStarBrightnessChanged()
 
 void LLPanelSettingsSkySunMoonTab::onSunRotationChanged()
 {
-    mSkySettings->setSunRotation(getChild<LLJoystickQuaternion>(FIELD_SKY_SUN_ROTATION)->getRotation());
+    mSkySettings->setSunRotation(getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->getRotation());
     mSkySettings->update();
 }
 
@@ -414,7 +415,7 @@ void LLPanelSettingsSkySunMoonTab::onSunImageChanged()
 
 void LLPanelSettingsSkySunMoonTab::onMoonRotationChanged()
 {
-    mSkySettings->setMoonRotation(getChild<LLJoystickQuaternion>(FIELD_SKY_MOON_ROTATION)->getRotation());
+    mSkySettings->setMoonRotation(getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->getRotation());
     mSkySettings->update();
 }
 
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index a16b1a68adc43d116be41a6369ed33998aecd314..a177dbadd5b6f0effe033446dbe917b1393d31d6 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -689,6 +689,16 @@ with the same filename but different name
   
   <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120"  scale_type="scale_outer"/>
 
+  <texture name="VirtualTrackball_Moon_Back" file_name="widgets/track_control_moon_back.png" />
+  <texture name="VirtualTrackball_Moon_Front" file_name="widgets/track_control_moon_front.png" />
+  <texture name="VirtualTrackball_Rotate_Bottom" file_name="widgets/track_control_rotate_bottom.png" />
+  <texture name="VirtualTrackball_Rotate_Left" file_name="widgets/track_control_rotate_left_side.png" />
+  <texture name="VirtualTrackball_Rotate_Right" file_name="widgets/track_control_rotate_right_side.png" />
+  <texture name="VirtualTrackball_Rotate_Top" file_name="widgets/track_control_rotate_top.png" />
+  <texture name="VirtualTrackball_Sphere" file_name="widgets/track_control_sphere.png" />
+  <texture name="VirtualTrackball_Sun_Back" file_name="widgets/track_control_sun_back.png" />
+  <texture name="VirtualTrackball_Sun_Front" file_name="widgets/track_control_sun_front.png" />
+    
     <texture name="Volume_Background" file_name="windows/Volume_Background.png" preload="false"
            scale.left="6" scale.top="33" scale.right="63" scale.bottom="10" />
 
diff --git a/indra/newview/skins/default/textures/widgets/track_control_moon_back.png b/indra/newview/skins/default/textures/widgets/track_control_moon_back.png
new file mode 100644
index 0000000000000000000000000000000000000000..73d24e53f61bd0d2d91b3662279cd47d8933e737
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_moon_back.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_moon_front.png b/indra/newview/skins/default/textures/widgets/track_control_moon_front.png
new file mode 100644
index 0000000000000000000000000000000000000000..64def00772cdfc6d701b30a7ccdce1e95c347303
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_moon_front.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_bottom.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_bottom.png
new file mode 100644
index 0000000000000000000000000000000000000000..232c812aae5d80bb3d1e39fab9631a18751d9e32
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_bottom.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_left_side.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_left_side.png
new file mode 100644
index 0000000000000000000000000000000000000000..bcc78fc5e437979f166aae5d97cc320f09b26166
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_left_side.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_right_side.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_right_side.png
new file mode 100644
index 0000000000000000000000000000000000000000..d0827abf281db99f8cdd3646ee1f2f9fe2a6efb9
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_right_side.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_top.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_top.png
new file mode 100644
index 0000000000000000000000000000000000000000..13a5e9c2e8b8656619fcb7410dc4d36552789552
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_top.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_sphere.png b/indra/newview/skins/default/textures/widgets/track_control_sphere.png
new file mode 100644
index 0000000000000000000000000000000000000000..a13b7725ea1cdf162e77aedf1c9089e871cedca9
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_sphere.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_sun_back.png b/indra/newview/skins/default/textures/widgets/track_control_sun_back.png
new file mode 100644
index 0000000000000000000000000000000000000000..23c89068f88ad6821989c343021b7afb6d5eb82e
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_sun_back.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_sun_front.png b/indra/newview/skins/default/textures/widgets/track_control_sun_front.png
new file mode 100644
index 0000000000000000000000000000000000000000..6dfdc0442391ca1f220af987d594046ea3db6765
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_sun_front.png differ
diff --git a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
index fb53eb969ba14ddd40433d0bc936f632130e5017..aac2084543b04d2d495dcab6e7b86cd84c906c51 100644
--- a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
+++ b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
@@ -6,7 +6,7 @@
         save_rect="true"
         title="Edit Day Cycle"
         width="705"
-        height="602"
+        height="650"
         min_width="450"
         min_height="85"
         can_resize="true">
@@ -22,7 +22,7 @@
 
     <layout_stack name="outer_stack"
             width="705"
-            height="602"
+            height="650"
             follows="all"
             animate="false"
             top="0"
@@ -450,14 +450,14 @@
                 <layout_panel name="frame_settings_water"
                         auto_resize="true"
                         user_resize="true"
-                        height="420"
+                        height="500"
                         width="700"
                         min_height="0"
                         visible="true">
                     <tab_container
                             follows="all"
                             halign="left"
-                            height="420"
+                            height="430"
                             layout="topleft"
                             left="0"
                             name="water_tabs"
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml
index 1323ad6a17d4124a0c2ba3f8f35e6235e43f3858..a951e39697c59fe891383b7e0eb0c570b89a17a1 100644
--- a/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml
@@ -21,7 +21,7 @@
                 auto_resize="true"
                 user_resize="true"
                 visible="true"
-                height="75">
+                height="350">
             <text
                     follows="left|top"
                     height="10"
@@ -117,7 +117,7 @@
                 auto_resize="true"
                 user_resize="true"
                 visible="true"
-                height="75">
+                height="350">
             <layout_stack 
                     left="5"
                     top="5"
@@ -131,7 +131,7 @@
                         auto_resize="true"
                         user_resize="true"
                         visible="true"
-                        height="75">
+                        height="220">
                     <text
                             follows="left|top"
                             height="10"
@@ -151,23 +151,19 @@
                             width="100">
                         Position:
                     </text>
-                    <joystick_quat
-                            follows="left|top"
-                            height="78"
-                            layout="topleft"
-                            left_delta="0"
-                            top_delta="20"
-                            name="sun_rotation"
-                            quadrant="left"
-                            sound_flags="3"
-                            visible="true"
-                            tool_tip="Move sun in sky"
-                            width="78" /> <!-- Should be 126x126 -->
+                    <sun_moon_trackball
+                        name="sun_rotation"
+                        follows="left|top"
+                        left_delta="0"
+                        top_delta="20"
+                        height="150"
+                        width="150"
+                        thumb_mode="sun" />
                     <text
                             follows="left|top"
                             height="10"
                             layout="topleft"
-                            left_delta="100"
+                            left_delta="160"
                             top_delta="-20"
                             width="200">
                         Image:
@@ -186,7 +182,7 @@
                         auto_resize="true"
                         user_resize="true"
                         visible="true"
-                        height="75">
+                        height="220">
                     <text
                             follows="left|top"
                             height="10"
@@ -206,23 +202,19 @@
                             width="100">
                         Position:
                     </text>
-                    <joystick_quat
-                            follows="left|top"
-                            height="78"
-                            layout="topleft"
-                            left_delta="0"
-                            top_delta="20"
-                            name="moon_rotation"
-                            quadrant="left"
-                            sound_flags="3"
-                            visible="true"
-                            tool_tip="Move sun in sky"
-                            width="78" /> <!-- Should be 126x126 -->
+                    <sun_moon_trackball
+                        name="moon_rotation"
+                        follows="left|top"
+                        left_delta="0"
+                        top_delta="20"
+                        height="150"
+                        width="150"
+                        thumb_mode="moon" />
                     <text
                             follows="left|top"
                             height="10"
                             layout="topleft"
-                            left_delta="100"
+                            left_delta="160"
                             top_delta="-20"
                             width="200">
                         Image:
diff --git a/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml b/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml
new file mode 100644
index 0000000000000000000000000000000000000000..68681b8228e4ea27af103a2c867b194bed552803
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<sun_moon_trackball
+    name="virtualtrackball"
+    width="150"
+    height="150"
+    user_resize="false"     
+    increment_angle_mouse="0.5f"
+    increment_angle_btn="3.0f"    
+    image_sphere="VirtualTrackball_Sphere"
+    image_moon_back="VirtualTrackball_Moon_Back"
+    image_moon_front="VirtualTrackball_Moon_Front"
+    image_sun_back="VirtualTrackball_Sun_Back"
+    image_sun_front="VirtualTrackball_Sun_Front">
+
+    <sun_moon_trackball.border
+        visible="true"/>
+
+    <sun_moon_trackball.labelN
+        font="SansSerif"
+        name="labelN"
+        valign="bottom"
+        halign="left"
+        label="N"/>
+    <sun_moon_trackball.labelS
+        font="SansSerif"
+        name="labelS"
+        valign="top"
+        halign="left"
+        label="S"/>
+    <sun_moon_trackball.labelW
+        font="SansSerif"
+        name="labelW"
+        valign="top"
+        halign="right"
+        label="W"/>
+    <sun_moon_trackball.labelE
+        font="SansSerif"
+        name="labelE"
+        valign="top"
+        halign="left"
+        label="E"/>
+
+    <sun_moon_trackball.button_rotate_top
+        name="btn_rotate_top"
+        image_unselected="VirtualTrackball_Rotate_Top"
+        image_selected="VirtualTrackball_Rotate_Top"
+        image_disabled="VirtualTrackball_Rotate_Top" />
+
+    <sun_moon_trackball.button_rotate_bottom
+        name="btn_rotate_bottom"
+        image_unselected="VirtualTrackball_Rotate_Bottom"
+        image_selected="VirtualTrackball_Rotate_Bottom"
+        image_disabled="VirtualTrackball_Rotate_Bottom" />
+
+    <sun_moon_trackball.button_rotate_left
+        name="btn_rotate_left"
+        image_unselected="VirtualTrackball_Rotate_Left"
+        image_selected="VirtualTrackball_Rotate_Left"
+        image_disabled="VirtualTrackball_Rotate_Left" />
+
+    <sun_moon_trackball.button_rotate_right
+        name="btn_rotate_right"
+        image_unselected="VirtualTrackball_Rotate_Right"
+        image_selected="VirtualTrackball_Rotate_Right"
+        image_disabled="VirtualTrackball_Rotate_Right" />
+
+</sun_moon_trackball>
+