Browse Source

Merge pull request #920 from AtomicGameEngine/JME-ATOMIC-COLORPICKER

Color Picker and skin enhancements
JoshEngebretson 9 years ago
parent
commit
ab35c663d5
72 changed files with 1311 additions and 16 deletions
  1. BIN
      Resources/EditorData/AtomicEditor/editor/skin/HSV21.png
  2. BIN
      Resources/EditorData/AtomicEditor/editor/skin/checkerboard.png
  3. 22 0
      Resources/EditorData/AtomicEditor/editor/skin/skin.tb.txt
  4. BIN
      Resources/EditorData/AtomicEditor/editor/skin_light/HSV21.png
  5. BIN
      Resources/EditorData/AtomicEditor/editor/skin_light/checkerboard.png
  6. 22 0
      Resources/EditorData/AtomicEditor/editor/skin_light/skin.tb.txt
  7. 39 0
      Resources/EditorData/AtomicEditor/editor/ui/colorchooser.tb.txt
  8. 3 3
      Resources/EditorData/AtomicEditor/editor/ui/mainframe.tb.txt
  9. 4 0
      Resources/EditorData/AtomicEditor/editor/ui/maintoolbar.tb.txt
  10. 3 3
      Resources/EditorData/AtomicEditor/editor/ui/welcomeframe.tb.txt
  11. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/checkbox_mark.png
  12. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  13. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  14. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  15. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/checkbox_mark_grey.png
  16. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/checkbox_mark_nonuniform.png
  17. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/radio_mark.png
  18. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  19. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  20. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  21. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/slider_handle.png
  22. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  23. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  24. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  25. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/window_close.png
  26. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  27. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  28. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  29. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/window_close_pressed.png
  30. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  31. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  32. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]
  33. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/checkbox_mark.png
  34. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  35. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  36. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  37. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/checkbox_mark_grey.png
  38. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/checkbox_mark_nonuniform.png
  39. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/radio_mark.png
  40. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  41. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  42. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  43. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/slider_handle.png
  44. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  45. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  46. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  47. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/toggle_section_icon_down.png
  48. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/toggle_section_icon_up.png
  49. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/window_close.png
  50. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  51. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  52. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  53. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/window_close_pressed.png
  54. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  55. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  56. BIN
      Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]
  57. 123 6
      Script/AtomicEditor/ui/frames/inspector/AttributeInfoEdit.ts
  58. 291 0
      Script/AtomicEditor/ui/frames/inspector/ColorChooser.ts
  59. 1 1
      Script/AtomicEditor/ui/frames/inspector/ComponentAttributeUI.ts
  60. 43 0
      Script/AtomicEditor/ui/frames/inspector/InspectorUtils.ts
  61. 1 1
      Script/AtomicEditor/ui/frames/inspector/InspectorWidget.ts
  62. 2 2
      Script/Packages/Atomic/UI.json
  63. 28 0
      Source/Atomic/UI/UI.cpp
  64. 81 0
      Source/Atomic/UI/UIColorWheel.cpp
  65. 55 0
      Source/Atomic/UI/UIColorWheel.h
  66. 94 0
      Source/Atomic/UI/UIColorWidget.cpp
  67. 61 0
      Source/Atomic/UI/UIColorWidget.h
  68. 74 0
      Source/Atomic/UI/UISlider.cpp
  69. 50 0
      Source/Atomic/UI/UISlider.h
  70. 3 0
      Source/AtomicJS/Javascript/JSUI.cpp
  71. 200 0
      Source/ThirdParty/TurboBadger/tb_atomic_widgets.cpp
  72. 111 0
      Source/ThirdParty/TurboBadger/tb_atomic_widgets.h

BIN
Resources/EditorData/AtomicEditor/editor/skin/HSV21.png


BIN
Resources/EditorData/AtomicEditor/editor/skin/checkerboard.png


+ 22 - 0
Resources/EditorData/AtomicEditor/editor/skin/skin.tb.txt

@@ -12,6 +12,28 @@ elements
 		cut 16
 		cut 16
 		expand 12
 		expand 12
 		padding 0
 		padding 0
+
+	Checkerboard
+		type StretchBox
+		bitmap checkerboard.png
+	HSVSkin
+		type StretchBox
+		bitmap HSV21.png
+	AccentColor1
+		text-color #D4FB79
+	AccentColor2
+		text-color #76D6FF
+	AccentColor3
+		text-color #9A7DA1
+	AccentColor4
+		text-color #AAAAAA
+	AccentColorWarn
+		text-color #ffff66
+	AccentColorError
+		text-color #ff3333
+	AccentColorSuccess
+		text-color #33ff33
+
 	Folder
 	Folder
 		text-color #aaaaaa
 		text-color #aaaaaa
 	Folder.selected
 	Folder.selected

BIN
Resources/EditorData/AtomicEditor/editor/skin_light/HSV21.png


BIN
Resources/EditorData/AtomicEditor/editor/skin_light/checkerboard.png


+ 22 - 0
Resources/EditorData/AtomicEditor/editor/skin_light/skin.tb.txt

@@ -12,6 +12,28 @@ elements
 		cut 16
 		cut 16
 		expand 12
 		expand 12
 		padding 0
 		padding 0
+
+	Checkerboard
+		type StretchBox
+		bitmap checkerboard.png
+	HSVSkin
+		type StretchBox
+		bitmap HSV21.png
+	AccentColor1
+		text-color #224444
+	AccentColor2
+		text-color #113333
+	AccentColor3
+		text-color #002222
+	AccentColor4
+		text-color #001111
+	AccentColorWarn
+		text-color #ffff66
+	AccentColorError
+		text-color #ff6666
+	AccentColorSuccess
+		text-color #66ff66
+
 	Folder
 	Folder
 		text-color #2c2c2c
 		text-color #2c2c2c
 	Folder.selected
 	Folder.selected

+ 39 - 0
Resources/EditorData/AtomicEditor/editor/ui/colorchooser.tb.txt

@@ -0,0 +1,39 @@
+TBLayout: axis: y, distribution: gravity, position: left
+	lp: min-width: 300
+	TBLayout: axis: x, distribution: gravity
+		TBColorWheel: id: colorwheel, skin: HSVSkin
+				lp: width: 256, height: 256
+		TBSlider: id: lslider, axis: y, min: 0, max: 255, value: 128
+	TBLayout: axis: x, distribution: available, gravity: left right
+		TBColorWidget: id: colornew, color: blue, skin: Checkerboard
+				lp: width: 128, height: 64, max-width: 150, max-height: 80
+		TBColorWidget: id: colorold, color: red, skin: Checkerboard
+				lp: width: 128, height: 64, max-width: 150, max-height: 80
+	TBLayout: axis: y, distribution: gravity
+		TBLayout: axis: x, distribution: gravity
+			TBTextField: text: " R ", id: redlabel
+			TBInlineSelect: id: redselect, min: 0, max: 255, connection: rconn
+			TBSlider: id: redslider, min: 0, max: 255, connection: rconn
+		TBLayout: axis: x, distribution: gravity
+			TBTextField: text: " G ", id: greenlabel
+			TBInlineSelect: id: greenselect, min: 0, max: 255, connection: gconn
+			TBSlider: id: greenslider, min: 0, max: 255, connection: gconn
+		TBLayout: axis: x, distribution: gravity
+			TBTextField: text: " B ", id: bluelabel
+			TBInlineSelect: id: blueselect, min: 0, max: 255, connection: bconn
+			TBSlider: id: blueslider, min: 0, max: 255, connection: bconn
+		TBSeparator: gravity: left right
+		TBLayout: axis: x, distribution: gravity
+			TBTextField: text: " A ", id: alphalabel
+			TBInlineSelect: id: alphaselect, min: 0, max: 255, connection: aconn
+			TBSlider: id: alphaslider, min: 0, max: 255, value: 255, connection: aconn
+		TBSeparator: gravity: left right
+		TBLayout: axis: x, distribution: available, gravity: left right
+			TBEditField: id: infohex, text: "#000000", readonly: 1
+				font: size: 16
+			TBEditField: id: infohsl, text: "0.0, 0.0, 0,0", readonly: 1
+				font: size: 16
+	TBSeparator: gravity: left right, skin: AESeparator
+	TBLayout:
+		TBButton: text: OK, id: cokbutton
+		TBButton: text: Cancel, id: ccancelbutton

+ 3 - 3
Resources/EditorData/AtomicEditor/editor/ui/mainframe.tb.txt

@@ -37,11 +37,11 @@ TBLayout: distribution: gravity, axis: y
                             TBWidget
                             TBWidget
             TBLayout: distribution: gravity, position: top
             TBLayout: distribution: gravity, position: top
                 TBLayout: distribution: gravity, axis: y, position: left, gravity: top bottom
                 TBLayout: distribution: gravity, axis: y, position: left, gravity: top bottom
-                    TBEditField: text: "<color #AAAAAA>Project</color>", styling: 1, readonly: 1, adapt-to-content: 1, skin: 0
+                    TBEditField: text: "Project", styling: 1, readonly: 1, adapt-to-content: 1, skin: AccentColor4
                         font: size: 11
                         font: size: 11
                     TBLayout: distribution: gravity, id: projectviewcontainer
                     TBLayout: distribution: gravity, id: projectviewcontainer
                     TBSeparator: gravity: left right, skin: AESeparator
                     TBSeparator: gravity: left right, skin: AESeparator
-                    TBEditField: text: "<color #AAAAAA>Hierarchy</color>", styling: 1, readonly: 1, adapt-to-content: 1, skin: 0
+                    TBEditField: text: "Hierarchy", styling: 1, readonly: 1, adapt-to-content: 1, skin: AccentColor4
                         font: size: 11
                         font: size: 11
                     TBLayout: distribution: gravity, id: hierarchycontainer
                     TBLayout: distribution: gravity, id: hierarchycontainer
                         TBWidget: gravity: top bottom
                         TBWidget: gravity: top bottom
@@ -53,7 +53,7 @@ TBLayout: distribution: gravity, axis: y
                         TBEditField: multiline: 1, styling: 1, gravity: left right, id: consoletext
                         TBEditField: multiline: 1, styling: 1, gravity: left right, id: consoletext
                             text: "Hello World!"
                             text: "Hello World!"
                 TBLayout: distribution: gravity, axis: y, position: left, gravity: top bottom, id: inspectorlayout
                 TBLayout: distribution: gravity, axis: y, position: left, gravity: top bottom, id: inspectorlayout
-                    TBEditField: text: "<color #AAAAAA>Inspector</color>", styling: 1, readonly: 1, adapt-to-content: 1, skin: 0
+                    TBEditField: text: "Inspector", styling: 1, readonly: 1, adapt-to-content: 1, skin: AccentColor4
                         font: size: 11
                         font: size: 11
                     TBLayout: distribution: gravity, id: inspectorcontainer
                     TBLayout: distribution: gravity, id: inspectorcontainer
 
 

+ 4 - 0
Resources/EditorData/AtomicEditor/editor/ui/maintoolbar.tb.txt

@@ -22,15 +22,19 @@ TBLayout: distribution: gravity, spacing: 4
 		@include definitions>menubutton
 		@include definitions>menubutton
 		TBSkinImage: skin: 3DTranslateBitmap
 		TBSkinImage: skin: 3DTranslateBitmap
 		id 3d_translate
 		id 3d_translate
+		tooltip Translate
 	TBButton: toggle-mode: 1
 	TBButton: toggle-mode: 1
 		@include definitions>menubutton
 		@include definitions>menubutton
 		TBSkinImage: skin: 3DRotateBitmap
 		TBSkinImage: skin: 3DRotateBitmap
 		id 3d_rotate
 		id 3d_rotate
+		tooltip Rotate
 	TBButton: toggle-mode: 1
 	TBButton: toggle-mode: 1
 		@include definitions>menubutton
 		@include definitions>menubutton
 		TBSkinImage: skin: 3DScaleBitmap
 		TBSkinImage: skin: 3DScaleBitmap
 		id 3d_scale
 		id 3d_scale
+		tooltip Scale
 	TBButton: toggle-mode: 1
 	TBButton: toggle-mode: 1
 		lp: width: 64
 		lp: width: 64
 		text: "Local"
 		text: "Local"
 		id 3d_axismode
 		id 3d_axismode
+		tooltip Effect world or local object

+ 3 - 3
Resources/EditorData/AtomicEditor/editor/ui/welcomeframe.tb.txt

@@ -8,10 +8,10 @@ TBLayout: distribution: gravity, size: available, axis: y, id: welcomelayout, po
                 TBButton: id: new project
                 TBButton: id: new project
                     text New Project
                     text New Project
             TBLayout: distribution: gravity, axis: y, position: left, id: recentprojects
             TBLayout: distribution: gravity, axis: y, position: left, id: recentprojects
-                TBEditField: text: "<color #76D6FF>Recent Projects:</color>", styling: 1, readonly: 1, adapt-to-content: 1, skin: 0
+                TBEditField: text: "Recent Projects:", styling: 1, readonly: 1, adapt-to-content: 1, skin: AccentColor2
     TBLayout: distribution: gravity, size: available
     TBLayout: distribution: gravity, size: available
         TBLayout: distribution: gravity, axis: y, position: left
         TBLayout: distribution: gravity, axis: y, position: left
-            TBEditField: text: "<color #76D6FF>Welcome:</color>", styling: 1, readonly: 1, adapt-to-content: 1, skin: 0
+            TBEditField: text: "Welcome:", styling: 1, readonly: 1, adapt-to-content: 1, skin: AccentColor2
             TBImageWidget: filename: "AtomicEditor/editor/images/earlyaccess_header.png"
             TBImageWidget: filename: "AtomicEditor/editor/images/earlyaccess_header.png"
                 lp: width: 420, height: 137
                 lp: width: 420, height: 137
             TBEditField: multiline: 1, styling: 1, gravity: all, id: welcome_text, readonly: 1, adapt-to-content: 0
             TBEditField: multiline: 1, styling: 1, gravity: all, id: welcome_text, readonly: 1, adapt-to-content: 0
@@ -33,7 +33,7 @@ TBLayout: distribution: gravity, size: available, axis: y, id: welcomelayout, po
             TBLayout: distribution: gravity, size: available
             TBLayout: distribution: gravity, size: available
                 TBContainer: gravity: left right
                 TBContainer: gravity: left right
                     TBLayout: distribution: gravity
                     TBLayout: distribution: gravity
-                        TBEditField: text: "<color #76D6FF>More Examples:</color>", styling: 1, readonly: 1, adapt-to-content: 1, skin: 0
+                        TBEditField: text: "More Examples:", styling: 1, readonly: 1, adapt-to-content: 1, skin: AccentColor2
                         TBButton: id: 'examples_github' text: "https://github.com/AtomicGameEngine/AtomicExamples", skin: TBButton.link
                         TBButton: id: 'examples_github' text: "https://github.com/AtomicGameEngine/AtomicExamples", skin: TBButton.link
                         TBWidget: gravity: left right
                         TBWidget: gravity: left right
             TBScrollContainer: scroll-mode: auto
             TBScrollContainer: scroll-mode: auto

BIN
Resources/EditorData/AtomicEditor/resources/default_skin/checkbox_mark.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/checkbox_mark_grey.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/checkbox_mark_nonuniform.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/radio_mark.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/slider_handle.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/window_close.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/window_close_pressed.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/checkbox_mark.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/checkbox_mark_grey.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/checkbox_mark_nonuniform.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/radio_mark.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/slider_handle.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/toggle_section_icon_down.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/toggle_section_icon_up.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/window_close.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/window_close_pressed.png


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


BIN
Resources/EditorData/AtomicEditor/resources/default_skin_light/[email protected]


+ 123 - 6
Script/AtomicEditor/ui/frames/inspector/AttributeInfoEdit.ts

@@ -24,6 +24,7 @@ import EditorUI = require("ui/EditorUI");
 import InspectorUtils = require("./InspectorUtils");
 import InspectorUtils = require("./InspectorUtils");
 import SerializableEditType = require("./SerializableEditType");
 import SerializableEditType = require("./SerializableEditType");
 import EditorEvents = require("editor/EditorEvents");
 import EditorEvents = require("editor/EditorEvents");
+import ColorChooser = require("./ColorChooser");
 
 
 class AttributeInfoEdit extends Atomic.UILayout {
 class AttributeInfoEdit extends Atomic.UILayout {
 
 
@@ -184,7 +185,7 @@ class BoolAttributeEdit extends AttributeInfoEdit {
 
 
         if (uniform) {
         if (uniform) {
             var object = this.editType.getFirstObject();
             var object = this.editType.getFirstObject();
-            this.editWidget.skinBg = "TBGreyCheckBox";
+            this.editWidget.skinBg = "TBCheckBox";
             if (object) {
             if (object) {
                 var value = object.getAttribute(this.attrInfo.name);
                 var value = object.getAttribute(this.attrInfo.name);
                 this.editWidget.value = (value ? 1 : 0);
                 this.editWidget.value = (value ? 1 : 0);
@@ -192,7 +193,7 @@ class BoolAttributeEdit extends AttributeInfoEdit {
 
 
         } else {
         } else {
 
 
-            this.editWidget.skinBg = "TBGreyCheckBoxNonUniform";
+            this.editWidget.skinBg = "TBCheckBoxNonUniform";
             this.editWidget.value = 1;
             this.editWidget.value = 1;
 
 
         }
         }
@@ -621,14 +622,130 @@ class QuaternionAttributeEdit extends NumberArrayAttributeEdit {
 
 
 }
 }
 
 
-class ColorAttributeEdit extends NumberArrayAttributeEdit {
+class ColorAttributeEdit extends AttributeInfoEdit {
 
 
-    constructor() {
 
 
-        super(4);
+    createLayout() {
+
+        var layout = new Atomic.UILayout();
+        var o = InspectorUtils.createAttrColorFieldWithSelectButton(this.attrInfo.name, layout);
+
+        var colorWidget = this.colorWidget = o.colorWidget;
+        var selectButton = o.selectButton;
+
+        layout.layoutSize = Atomic.UI_LAYOUT_SIZE_AVAILABLE;
+        layout.gravity = Atomic.UI_GRAVITY_LEFT_RIGHT;
+        layout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
+
+
+        var lp = new Atomic.UILayoutParams();
+        lp.width = 140;
+        lp.height = 24;
+        colorWidget.layoutParams = lp;
+
+        this.editWidget = layout;
+
+        this.editWidget.subscribeToEvent(this.editWidget, "WidgetEvent", (data) => this.handleWidgetEvent(data));
+
+        selectButton.onClick = () => {
+
+            // store original color
+            let color = [1, 1, 1, 1];
+            let object = this.editType.getFirstObject();
+
+            if (object) {
+                color = object.getAttribute(this.attrInfo.name);
+            }
+
+            colorWidget.color = color;
+
+            let restore = null;
+            let chooser = new ColorChooser ( color );
+
+            this.subscribeToEvent(chooser, "ColorChooserChanged", (ev) => {
+
+                restore = color;
+                this.updateColor(chooser.getRGBA());
+
+            });
+
+            this.subscribeToEvent(chooser, "UIWidgetEditCanceled", (ev) => {
+
+                if (restore) {
+
+                    colorWidget.color = restore;
+                    this.updateColor(restore);
+
+                }
+
+            });
+
+            this.subscribeToEvent(chooser, "UIWidgetEditComplete", (ev) => {
+
+                let newColor = chooser.getRGBA();
+
+                // check for new color edit
+                let committed = false;
+                for (let i = 0; i < 4; i++) {
+
+                    if (color[i] != newColor[i]) {
+
+                        this.editType.onAttributeInfoEdited(this.attrInfo, newColor);
+                        this.refresh();
+                        committed = true;
+                        break;
+
+                    }
+                }
+
+                if (restore && !committed) {
+
+                    for (let i = 0; i < 4; i++) {
+
+                        if (color[i] != restore[i]) {
+
+                            this.updateColor(color);
+                            break;
+
+                        }
+
+                    }
+
+                }
+
+            });
+
+        };
+
+        this.addChild(this.editWidget);
+
+    }
+
+    refresh() {
+
+        let object = this.editType.getFirstObject();
+
+        if (object) {
+            this.colorWidget.color = object.getAttribute(this.attrInfo.name);
+        }
+    }
+
+    // updates color on selection without committing to undo/redo for preview
+    updateColor(rgba:number[]) {
+
+        this.colorWidget.color = rgba;
+
+        for (var i in this.editType.objects) {
+
+            let object = this.editType.objects[i];
+            object.setAttribute(this.attrInfo.name, rgba );
+
+        }
 
 
     }
     }
 
 
+    colorWidget : Atomic.UIColorWidget;
+
 }
 }
 
 
 class ResourceRefAttributeEdit extends AttributeInfoEdit {
 class ResourceRefAttributeEdit extends AttributeInfoEdit {
@@ -675,7 +792,7 @@ class ResourceRefAttributeEdit extends AttributeInfoEdit {
             this.nameOverride = attrInfo.resourceTypeName + " " + this.refListIndex;
             this.nameOverride = attrInfo.resourceTypeName + " " + this.refListIndex;
 
 
         var importerName = ToolCore.assetDatabase.getResourceImporterName(attrInfo.resourceTypeName);
         var importerName = ToolCore.assetDatabase.getResourceImporterName(attrInfo.resourceTypeName);
-        
+
         if (!importerName)
         if (!importerName)
             return false;
             return false;
 
 

+ 291 - 0
Script/AtomicEditor/ui/frames/inspector/ColorChooser.ts

@@ -0,0 +1,291 @@
+//
+// Copyright (c) 2016 THUNDERBEAST GAMES LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
+
+import EditorUI = require("ui/EditorUI");
+
+class ColorChooser extends Atomic.UIWindow {
+
+    rgbhsla : number[] = [ 0, 0, 0, 0, 0, 0, 255 ]; // 0=R, 1=G , 2=B, 3=H, 4=S, 5=L, 6=Alpha
+    r_ils : Atomic.UIInlineSelect;
+    g_ils : Atomic.UIInlineSelect;
+    b_ils : Atomic.UIInlineSelect;
+    a_ils : Atomic.UIInlineSelect;
+    r_sld : Atomic.UISlider;
+    g_sld : Atomic.UISlider;
+    b_sld : Atomic.UISlider;
+    a_sld : Atomic.UISlider;
+    oldcolor : Atomic.UIColorWidget;
+    newcolor : Atomic.UIColorWidget;
+    wheel : Atomic.UIColorWheel;
+    lslide : Atomic.UISlider;
+    infohex : Atomic.UIEditField;
+    infohsl : Atomic.UIEditField;
+
+    constructor( startRGBA:number[] ) {
+
+        super();
+
+        var view = EditorUI.getView();
+        view.addChild(this);
+
+        this.text = "Color Chooser";
+        this.load("AtomicEditor/editor/ui/colorchooser.tb.txt");
+
+        this.r_ils = <Atomic.UIInlineSelect>this.getWidget("redselect");
+        this.g_ils = <Atomic.UIInlineSelect>this.getWidget("greenselect");
+        this.b_ils = <Atomic.UIInlineSelect>this.getWidget("blueselect");
+        this.a_ils = <Atomic.UIInlineSelect>this.getWidget("alphaselect");
+        this.r_sld = <Atomic.UISlider>this.getWidget("redslider");
+        this.g_sld = <Atomic.UISlider>this.getWidget("greenslider");
+        this.b_sld = <Atomic.UISlider>this.getWidget("blueslider");
+        this.a_sld = <Atomic.UISlider>this.getWidget("alphaslider");
+        this.newcolor = <Atomic.UIColorWidget>this.getWidget("colornew" );
+        this.oldcolor = <Atomic.UIColorWidget>this.getWidget("colorold" );
+        this.infohex = <Atomic.UIEditField>this.getWidget("infohex" );
+        this.infohsl = <Atomic.UIEditField>this.getWidget("infohsl" );
+        this.wheel = <Atomic.UIColorWheel>this.getWidget("colorwheel" );
+        this.lslide = <Atomic.UISlider>this.getWidget("lslider");
+
+        (<Atomic.UIButton>this.getWidget("ccancelbutton")).onClick = () => {
+
+            this.sendEvent("UIWidgetEditCanceled", { widget : this });
+            this.unsubscribeFromEvent("WidgetDeleted");
+            this.close();
+
+        };
+
+        (<Atomic.UIButton>this.getWidget("cokbutton")).onClick = () => {
+
+            this.sendEvent("UIWidgetEditComplete", { widget : this });
+            this.unsubscribeFromEvent("WidgetDeleted");
+            this.close();
+        };
+
+        this.subscribeToEvent(this, "WidgetDeleted", (event: Atomic.UIWidgetDeletedEvent) => {
+
+            this.sendEvent("UIWidgetEditCanceled", { widget : this });
+
+        });
+
+        this.subscribeToEvent(this, "WidgetEvent", (data) => this.handleWidgetEvent(data));
+
+        this.resizeToFitContent();
+        this.center();
+        this.setFocus();
+
+        let rx = Math.min(startRGBA[0] * 255, 255);
+        let gx = Math.min(startRGBA[1] * 255, 255);
+        let bx = Math.min(startRGBA[2] * 255, 255);
+        let ax = Math.min(startRGBA[3] * 255, 255);
+
+        let oldcolor = "#";
+        var rrr =  Math.round(rx).toString(16);
+        if (rrr.length < 2) oldcolor = oldcolor + "0";
+        oldcolor = oldcolor + rrr;
+        var ggg =  Math.round(gx).toString(16);
+        if (ggg.length < 2) oldcolor = oldcolor + "0";
+        oldcolor = oldcolor + ggg;
+        var bbb =  Math.round(bx).toString(16);
+        if (bbb.length < 2) oldcolor = oldcolor + "0";
+        oldcolor = oldcolor + bbb;
+        this.oldcolor.setColorString( oldcolor );
+
+        // start with current color instead of black
+        this.rgbhsla[0] = rx;
+        this.rgbhsla[1] = gx;
+        this.rgbhsla[2] = bx;
+        this.recalc_hsl();
+        this.fixcolor();
+        this.update_rgbwidgets();
+        this.update_hslwidgets();
+
+        Atomic.ui.blockChangedEvents = true;
+
+        this.oldcolor.setAlpha( startRGBA[3] * 255 );
+        this.a_sld.setValue(this.rgbhsla[6]);
+
+        Atomic.ui.blockChangedEvents = false;
+
+    }
+
+    handleWidgetEvent(ev: Atomic.UIWidgetEvent) {
+
+        if (ev.type == Atomic.UI_EVENT_TYPE_CHANGED) {
+
+            let changed = false;
+            let hsltargets = ["colorwheel", "lslider"];
+            let rgbtargets = {
+                "redselect" : 0,
+                "redslider" : 0,
+                "greenselect" : 1,
+                "greenslider" : 1,
+                "blueselect" : 2,
+                "blueslider" : 2,
+                "alphaslider" : 3
+            }
+
+            if (hsltargets.indexOf(ev.target.id) > -1) {
+
+                changed = true;
+                this.rgbhsla[3] = this.wheel.getHue() / 360;
+                this.rgbhsla[4] = this.wheel.getSaturation() / 128;
+                this.rgbhsla[5] = this.lslide.getValue() / 255;
+                this.recalc_rgb();
+                this.fixcolor();
+                this.update_rgbwidgets();
+
+            } else if (ev.target.id in rgbtargets) {
+
+                changed = true;
+                this.rgbhsla[rgbtargets[ev.target.id]] = ev.target.getValue();
+                this.recalc_hsl();
+                this.fixcolor();
+                this.update_hslwidgets();
+
+            }
+
+            if (changed) {
+
+                this.sendEvent("ColorChooserChanged", { widget : this });
+
+            }
+
+        }
+
+    }
+
+    // return current color choice as a RGBA array
+    getRGBA() : number[] {
+
+        var rr = this.rgbhsla[0] / 255;
+        var gg = this.rgbhsla[1] / 255;
+        var bb = this.rgbhsla[2] / 255;
+        var aa = this.rgbhsla[6] / 255;
+
+        return [rr, gg, bb, aa];
+
+    }
+
+    hue2rgb(p: number, q: number, t: number) { // part of rgb conversion
+        if (t < 0) t += 1;
+        if (t > 1) t -= 1;
+        if (t < 1 / 6) return p + (q - p) * 6 * t;
+        if (t < 1 / 2) return q;
+        if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
+        return p;
+    }
+
+    recalc_rgb() {
+        var rr, gg, bb;
+        let hh = this.rgbhsla[3];
+        let ss = this.rgbhsla[4];
+        let ll = this.rgbhsla[5];
+
+        if (ss == 0) {
+            rr = gg = bb = ll; // achromatic
+        } else {
+            var q = ll < 0.5 ? ll * (1 + ss) : ll + ss - ll * ss;
+            var p = 2 * ll - q;
+            rr = this.hue2rgb(p, q, hh + 1 / 3);
+            gg = this.hue2rgb(p, q, hh);
+            bb = this.hue2rgb(p, q, hh - 1 / 3);
+        }
+
+        this.rgbhsla[0] = rr * 255;
+        this.rgbhsla[1] = gg * 255;
+        this.rgbhsla[2] = bb * 255;
+    }
+
+    recalc_hsl() {
+        let rr = this.rgbhsla[0] / 255;
+        let gg = this.rgbhsla[1] / 255;
+        let bb = this.rgbhsla[2] / 255;
+
+        var max = Math.max(rr, gg, bb), min = Math.min(rr, gg, bb);
+        var hh, ss, ll = (max + min) / 2;
+
+        if (max == min) {
+            hh = ss = 0; // achromatic
+        } else {
+            var d = max - min;
+            ss = ll > 0.5 ? d / (2 - max - min) : d / (max + min);
+            switch (max) {
+                case rr: hh = (gg - bb) / d + (gg < bb ? 6 : 0); break;
+                case gg: hh = (bb - rr) / d + 2; break;
+                case bb: hh = (rr - gg) / d + 4; break;
+            }
+            hh /= 6;
+        }
+        this.rgbhsla[3] = hh;
+        this.rgbhsla[4] = ss;
+        this.rgbhsla[5] = ll;
+    }
+
+    update_rgbwidgets() {
+        Atomic.ui.blockChangedEvents = true;
+        this.r_ils.setValue(this.rgbhsla[0]);
+        this.g_ils.setValue(this.rgbhsla[1]);
+        this.b_ils.setValue(this.rgbhsla[2]);
+        this.r_sld.setValue(this.rgbhsla[0]);
+        this.g_sld.setValue(this.rgbhsla[1]);
+        this.b_sld.setValue(this.rgbhsla[2]);
+        Atomic.ui.blockChangedEvents = false;
+    }
+
+    update_hslwidgets() {
+        Atomic.ui.blockChangedEvents = true;
+        this.wheel.setHueSaturation (this.rgbhsla[3], this.rgbhsla[4]);
+        this.lslide.setValue(this.rgbhsla[5] * 128);
+        Atomic.ui.blockChangedEvents = false;
+   }
+
+    fixcolor() {
+        let mycolor = "#";  // create a new string
+
+        var rrr =  Math.round(this.rgbhsla[0]).toString(16);
+        if (rrr.length < 2) mycolor = mycolor + "0";
+        mycolor = mycolor + rrr;
+
+        var ggg =  Math.round(this.rgbhsla[1]).toString(16);
+        if (ggg.length < 2) mycolor = mycolor + "0";
+        mycolor = mycolor + ggg;
+
+        var bbb =  Math.round(this.rgbhsla[2]).toString(16);
+        if (bbb.length < 2) mycolor = mycolor + "0";
+        mycolor = mycolor + bbb;
+
+        this.newcolor.setColorString( mycolor );
+        this.newcolor.setAlpha( this.rgbhsla[6] / 255 );
+        this.infohex.text = mycolor;
+
+        let myhsl = Number(this.rgbhsla[3]).toFixed(2);
+        myhsl += ", ";
+        myhsl += Number(this.rgbhsla[4]).toFixed(2);
+        myhsl += ", ";
+        myhsl += Number(this.rgbhsla[5]).toFixed(2);
+        this.infohsl.text = myhsl;
+    }
+
+}
+
+export = ColorChooser;

+ 1 - 1
Script/AtomicEditor/ui/frames/inspector/ComponentAttributeUI.ts

@@ -337,7 +337,7 @@ class SubmeshAttributeEdit extends AttributeInfoEdit {
 
 
         } else {
         } else {
 
 
-            this.enabledCheckBox.skinBg = "TBGreyCheckBox";
+            this.enabledCheckBox.skinBg = "TBCheckBox";
             this.enabledCheckBox.value = enabled ? 1 : 0;
             this.enabledCheckBox.value = enabled ? 1 : 0;
 
 
         }
         }

+ 43 - 0
Script/AtomicEditor/ui/frames/inspector/InspectorUtils.ts

@@ -84,6 +84,21 @@ class InspectorUtils {
 
 
   }
   }
 
 
+  static createColorWidget():Atomic.UIColorWidget {
+
+    var colorWidget = new Atomic.UIColorWidget();
+    colorWidget.id = "colorfield";
+
+    var lp = new Atomic.UILayoutParams();
+    lp.width = 160;
+    lp.height = 24;
+    colorWidget.layoutParams = lp;
+
+    return colorWidget;
+
+  }
+
+
   static createAttrEditField(name:string, parent:Atomic.UIWidget):Atomic.UIEditField {
   static createAttrEditField(name:string, parent:Atomic.UIWidget):Atomic.UIEditField {
 
 
     var attrLayout = new Atomic.UILayout();
     var attrLayout = new Atomic.UILayout();
@@ -154,6 +169,34 @@ class InspectorUtils {
 
 
   }
   }
 
 
+  static createAttrColorFieldWithSelectButton(name:string, parent:Atomic.UIWidget):{colorWidget:Atomic.UIColorWidget, selectButton:Atomic.UIButton} {
+
+    var attrLayout = new Atomic.UILayout();
+    attrLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP;
+
+    if (name) {
+      var _name = InspectorUtils.createAttrName(name);
+      attrLayout.addChild(_name);
+    }
+
+    var fieldLayout = new Atomic.UILayout();
+    fieldLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP;
+
+    var colorWidget = InspectorUtils.createColorWidget();
+
+    var selectButton = new Atomic.UIButton();
+    selectButton.text = "...";
+    selectButton.fontDescription = InspectorUtils.attrFontDesc;
+
+    fieldLayout.addChild(colorWidget);
+    fieldLayout.addChild(selectButton);
+
+    attrLayout.addChild(fieldLayout);
+    parent.addChild(attrLayout);
+
+    return {colorWidget:colorWidget, selectButton:selectButton};
+
+  }
 
 
   // "static constructor"
   // "static constructor"
   static attrFontDesc:Atomic.UIFontDescription;
   static attrFontDesc:Atomic.UIFontDescription;

+ 1 - 1
Script/AtomicEditor/ui/frames/inspector/InspectorWidget.ts

@@ -117,7 +117,7 @@ class InspectorWidget extends ScriptWidget {
       attrLayout.addChild(_name);
       attrLayout.addChild(_name);
 
 
       var box = new Atomic.UICheckBox();
       var box = new Atomic.UICheckBox();
-      box.skinBg = "TBGreyCheckBox";
+      box.skinBg = "TBCheckBox";
       attrLayout.addChild(box);
       attrLayout.addChild(box);
       parent.addChild(attrLayout);
       parent.addChild(attrLayout);
 
 

+ 2 - 2
Script/Packages/Atomic/UI.json

@@ -8,8 +8,8 @@
 								"UIImageWidget", "UIClickLabel", "UICheckBox", "UIMenuItem", "UIMenuItemSource",
 								"UIImageWidget", "UIClickLabel", "UICheckBox", "UIMenuItem", "UIMenuItemSource",
 								"UISelectList", "UIListView", "UIMessageWindow", "UILayoutParams", "UIFontDescription",
 								"UISelectList", "UIListView", "UIMessageWindow", "UILayoutParams", "UIFontDescription",
 								"UISkinImage", "UITabContainer", "UISceneView", "UIPreferredSize", "UIDragObject",
 								"UISkinImage", "UITabContainer", "UISceneView", "UIPreferredSize", "UIDragObject",
-								"UIContainer", "UISection", "UIInlineSelect", "UITextureWidget",
-								"UIScrollContainer", "UISeparator", "UIDimmer", "UISelectDropdown"],
+								"UIContainer", "UISection", "UIInlineSelect", "UITextureWidget", "UIColorWidget", "UIColorWheel",
+								"UIScrollContainer", "UISeparator", "UIDimmer", "UISelectDropdown", "UISlider"],
 	"overloads" : {
 	"overloads" : {
 	},
 	},
 	"typescript_decl" : {
 	"typescript_decl" : {

+ 28 - 0
Source/Atomic/UI/UI.cpp

@@ -39,6 +39,7 @@
 #include <TurboBadger/tb_menu_window.h>
 #include <TurboBadger/tb_menu_window.h>
 #include <TurboBadger/tb_popup_window.h>
 #include <TurboBadger/tb_popup_window.h>
 #include <TurboBadger/image/tb_image_widget.h>
 #include <TurboBadger/image/tb_image_widget.h>
+#include <TurboBadger/tb_atomic_widgets.h>
 
 
 void register_tbbf_font_renderer();
 void register_tbbf_font_renderer();
 void register_stb_font_renderer();
 void register_stb_font_renderer();
@@ -83,6 +84,9 @@ using namespace tb;
 #include "UISelectDropdown.h"
 #include "UISelectDropdown.h"
 #include "UIMenuWindow.h"
 #include "UIMenuWindow.h"
 #include "UIPopupWindow.h"
 #include "UIPopupWindow.h"
+#include "UISlider.h"
+#include "UIColorWidget.h"
+#include "UIColorWheel.h"
 
 
 #include "SystemUI/SystemUI.h"
 #include "SystemUI/SystemUI.h"
 #include "SystemUI/SystemUIEvents.h"
 #include "SystemUI/SystemUIEvents.h"
@@ -674,6 +678,30 @@ UIWidget* UI::WrapWidget(tb::TBWidget* widget)
         return select;
         return select;
     }
     }
 
 
+    if (widget->IsOfType<TBSlider>())
+    {
+        UISlider* select = new UISlider(context_, false);
+        select->SetWidget(widget);
+        widgetWrap_[widget] = select;
+        return select;
+    }
+
+    if (widget->IsOfType<TBColorWidget>())
+    {
+        UIColorWidget* select = new UIColorWidget(context_, false);
+        select->SetWidget(widget);
+        widgetWrap_[widget] = select;
+        return select;
+    }
+
+    if (widget->IsOfType<TBColorWheel>())
+    {
+        UIColorWheel* select = new UIColorWheel(context_, false);
+        select->SetWidget(widget);
+        widgetWrap_[widget] = select;
+        return select;
+    }
+
     if (widget->IsOfType<TBSection>())
     if (widget->IsOfType<TBSection>())
     {
     {
         UISection* section = new UISection(context_, false);
         UISection* section = new UISection(context_, false);

+ 81 - 0
Source/Atomic/UI/UIColorWheel.cpp

@@ -0,0 +1,81 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include <TurboBadger/tb_widgets.h>
+#include <TurboBadger/tb_atomic_widgets.h>
+
+#include <Atomic/IO/Log.h>
+#include <Atomic/Graphics/Texture.h>
+
+#include "UIEvents.h"
+#include "UI.h"
+#include "UIColorWheel.h"
+
+using namespace tb;
+
+namespace Atomic
+{
+
+UIColorWheel::UIColorWheel(Context* context, bool createWidget) : UIWidget(context, false)
+{
+    UI* ui = GetSubsystem<UI>();
+
+    if (createWidget)
+    {
+        widget_ = new TBColorWheel();
+        widget_->SetDelegate(this);
+        ui->WrapWidget(this, widget_);
+    }
+
+}
+
+UIColorWheel::~UIColorWheel()
+{
+}
+
+bool UIColorWheel::OnEvent(const tb::TBWidgetEvent &ev)
+{
+    return UIWidget::OnEvent(ev);
+}
+
+float UIColorWheel::GetHue()
+{
+    if (!widget_)
+        return 0.0;
+    return ((TBColorWheel*) widget_)->GetHue();
+}
+
+float UIColorWheel::GetSaturation()
+{
+    if (!widget_)
+        return 0.0;
+    return ((TBColorWheel*) widget_)->GetSaturation();
+}
+
+void UIColorWheel::SetHueSaturation ( float hue, float saturation )
+{
+     if (!widget_)
+        return;
+    ((TBColorWheel*) widget_)->SetHueSaturation ( hue, saturation );
+}
+
+}

+ 55 - 0
Source/Atomic/UI/UIColorWheel.h

@@ -0,0 +1,55 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+
+#include "UIWidget.h"
+
+
+namespace Atomic
+{
+
+
+class UIColorWheel : public UIWidget
+{
+    OBJECT(UIColorWheel)
+
+public:
+
+    UIColorWheel(Context* context, bool createWidget = true);
+    virtual ~UIColorWheel();
+
+    float GetHue();
+    float GetSaturation();
+    void SetHueSaturation ( float hue, float saturation );
+
+ 
+protected:
+
+    virtual bool OnEvent(const tb::TBWidgetEvent &ev);
+
+private:
+
+};
+
+}

+ 94 - 0
Source/Atomic/UI/UIColorWidget.cpp

@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include <TurboBadger/tb_widgets.h>
+#include <TurboBadger/tb_atomic_widgets.h>
+
+#include <Atomic/IO/Log.h>
+#include <Atomic/Graphics/Texture.h>
+
+#include "UIEvents.h"
+#include "UI.h"
+#include "UIColorWidget.h"
+
+using namespace tb;
+
+namespace Atomic
+{
+
+UIColorWidget::UIColorWidget(Context* context, bool createWidget) : UIWidget(context, false)
+{
+    UI* ui = GetSubsystem<UI>();
+
+    if (createWidget)
+    {
+        widget_ = new TBColorWidget();
+        widget_->SetDelegate(this);
+        ui->WrapWidget(this, widget_);
+    }
+
+}
+
+UIColorWidget::~UIColorWidget()
+{
+}
+
+bool UIColorWidget::OnEvent(const tb::TBWidgetEvent &ev)
+{
+    return UIWidget::OnEvent(ev);
+}
+
+void UIColorWidget::SetColorString( const String &name )
+{
+     if (!widget_)
+        return;
+    ((TBColorWidget*) widget_)->SetColor(name.CString());
+}
+
+void UIColorWidget::SetColor(const Color& color)
+{
+    if (!widget_)
+        return;
+
+    ((TBColorWidget*)widget_)->SetColor(color.r_ * 255.0f, color.g_ * 255.0f, color.b_ * 255.0f, color.a_ * 255.0f);
+}
+
+Color UIColorWidget::GetColor() const
+{
+    if (!widget_)
+        return Color::BLACK;
+
+    const TBColor& color = ((TBColorWidget*)widget_)->GetColor();
+    float alpha = ((TBColorWidget*)widget_)->GetAlpha();
+
+    return Color(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, alpha / 255.0f);
+
+}
+
+void UIColorWidget::SetAlpha ( float value )
+{
+     if (!widget_)
+        return;
+    ((TBColorWidget*) widget_)->SetAlpha(value);
+}
+
+}

+ 61 - 0
Source/Atomic/UI/UIColorWidget.h

@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+
+#include "UIWidget.h"
+
+
+namespace Atomic
+{
+
+/// A widget that can render a Texture2D, so the image data
+/// doesn't need to be loaded 2x (once for Texture2D and once for say a UIImageWidget)
+class UIColorWidget : public UIWidget
+{
+    OBJECT(UIColorWidget)
+
+public:
+
+    UIColorWidget(Context* context, bool createWidget = true);
+    virtual ~UIColorWidget();
+
+    /// Set color from a Color value
+    void SetColor(const Color& color);
+
+    /// Set color from hex string
+    void SetColorString(const String &name);
+
+    Color GetColor() const;
+
+    void SetAlpha ( float value );
+
+protected:
+
+    virtual bool OnEvent(const tb::TBWidgetEvent &ev);
+
+private:
+
+};
+
+}

+ 74 - 0
Source/Atomic/UI/UISlider.cpp

@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include <TurboBadger/tb_widgets.h>
+#include <TurboBadger/tb_widgets_common.h>
+
+#include <Atomic/IO/Log.h>
+
+#include "UIEvents.h"
+#include "UI.h"
+#include "UILayout.h"
+#include "UISlider.h"
+
+using namespace tb;
+
+namespace Atomic
+{
+
+UISlider::UISlider(Context* context, bool createWidget) : UIWidget(context, false)
+{
+    if (createWidget)
+    {
+        widget_ = new TBSlider();
+        widget_->SetDelegate(this);
+        GetSubsystem<UI>()->WrapWidget(this, widget_);
+    }
+}
+
+UISlider::~UISlider()
+{
+
+}
+
+void UISlider::SetLimits(double minimum, double maximum)
+{
+    if (!widget_)
+        return;
+    ((TBSlider*) widget_)->SetLimits(minimum, maximum);
+
+}
+
+bool UISlider::OnEvent(const tb::TBWidgetEvent &ev)
+{
+    if (ev.type == EVENT_TYPE_CUSTOM && ev.ref_id == TBIDC("edit_complete"))
+    {
+        VariantMap eventData;
+        eventData[UIWidgetEditComplete::P_WIDGET] = this;
+        SendEvent(E_UIWIDGETEDITCOMPLETE, eventData);
+
+        return true;
+    }
+    return UIWidget::OnEvent(ev);
+}
+
+}

+ 50 - 0
Source/Atomic/UI/UISlider.h

@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "UIWidget.h"
+
+namespace Atomic
+{
+
+
+class UISlider : public UIWidget
+{
+    OBJECT(UISlider)
+
+public:
+
+    UISlider(Context* context, bool createWidget = true);
+    virtual ~UISlider();
+
+    void SetLimits(double minimum, double maximum);
+
+protected:
+
+    virtual bool OnEvent(const tb::TBWidgetEvent &ev);
+
+private:
+
+};
+
+}

+ 3 - 0
Source/AtomicJS/Javascript/JSUI.cpp

@@ -83,6 +83,9 @@ JSUI::JSUI(Context* context) : Object(context),
     uiTypes_["UIDimmer"] = true;
     uiTypes_["UIDimmer"] = true;
     uiTypes_["UISelectDropdown"] = true;
     uiTypes_["UISelectDropdown"] = true;
     uiTypes_["UIPopupWindow"] = true;
     uiTypes_["UIPopupWindow"] = true;
+    uiTypes_["UISlider"] = true;
+    uiTypes_["UIColorWidget"] = true;
+    uiTypes_["UIColorWheel"] = true;
 
 
 }
 }
 
 

+ 200 - 0
Source/ThirdParty/TurboBadger/tb_atomic_widgets.cpp

@@ -0,0 +1,200 @@
+// ================================================================================
+// ==      This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås      ==
+// ==                     See tb_core.h for more information.                    ==
+// ================================================================================
+//
+// Copyright (c) 2016, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "tb_widgets_reader.h"
+#include "tb_widgets_common.h"
+#include "tb_node_tree.h"
+#include "tb_system.h"
+#include "tb_atomic_widgets.h"
+#include <math.h>
+
+namespace tb {
+
+// == TBColorWidget =======================================
+
+TBColorWidget::TBColorWidget() : color_(), alpha_ ( 1.0f)
+{
+}
+
+void TBColorWidget::SetColor ( const char *name )
+{
+	if ( name )
+  	 color_.SetFromString(name, strlen(name));
+     
+    InvalidateSkinStates();
+    Invalidate();
+}
+
+void TBColorWidget::SetColor(float r, float g, float b, float a)
+{
+    color_.Set(TBColor(r, g, b, a));
+
+    InvalidateSkinStates();
+    Invalidate();
+}
+
+void TBColorWidget::SetAlpha ( float value )
+{
+    if ( value < 0.0 || value > 1.0 ) 
+    {
+        alpha_ = 1.0;
+        return;
+    }
+    
+    alpha_ = value; 
+
+    InvalidateSkinStates();
+    Invalidate();
+}
+
+void TBColorWidget::OnPaint(const PaintProps &paint_props)
+{
+    TBRect local_rect = GetRect();
+    local_rect.x = 0;
+    local_rect.y = 0;
+    float old_opacity = g_renderer->GetOpacity();
+    g_renderer->SetOpacity(alpha_);
+    g_renderer->DrawRectFill(local_rect, color_);
+    g_renderer->SetOpacity(old_opacity);
+}
+
+void TBColorWidget::OnInflate(const INFLATE_INFO &info)
+{
+    if (const char *colr = info.node->GetValueString("color", nullptr))
+        SetColor(colr);
+    TBWidget::OnInflate(info);
+}
+
+TB_WIDGET_FACTORY(TBColorWidget, TBValue::TYPE_NULL, WIDGET_Z_TOP) {}
+
+
+// == TBColorWheel =======================================
+
+TBColorWheel::TBColorWheel() :
+    markerx_(128),
+    markery_(128),
+    markercolor_(),
+    hue_(0.0),
+    saturation_(0.0)
+{
+}
+
+void TBColorWheel::OnPaint(const PaintProps &paint_props)
+{
+    TBWidget::OnPaint(paint_props);  // draw the widget stuff
+
+    TBRect local_rect ( 0,0,4,4 ); // AND draw a marker where we clicked.
+    local_rect.x = markerx_ - 2;
+    local_rect.y = markery_ - 2;
+    g_renderer->DrawRect( local_rect, markercolor_);
+    local_rect.x -= 1;
+    local_rect.y -= 1;
+    local_rect.w += 2;
+    local_rect.h += 2;
+    g_renderer->DrawRect( local_rect, markercolor_);  // draw double box
+    
+}
+
+bool TBColorWheel::OnEvent(const TBWidgetEvent &ev)
+{
+    if (ev.target == this && ev.type == EVENT_TYPE_CLICK)
+    {
+         SetMarkerX ( ev.target_x );
+         SetMarkerY ( ev.target_y );
+         CalcHueSaturation( markerx_, markery_ );
+         TBWidgetEvent ev(EVENT_TYPE_CHANGED); 
+         InvokeEvent(ev);
+    }
+    return TBWidget::OnEvent(ev);
+}
+
+void TBColorWheel::SetHueSaturation ( float hue, float saturation )
+{
+
+    // suppose to set the marker position to match HS here
+
+    hue_ = hue * 360.0;
+    saturation_ = saturation * 128.0;
+    
+    Invalidate();
+}
+
+void TBColorWheel::CalcHueSaturation ( int rawx, int rawy )
+{
+    TBRect rect = GetRect(); 
+    int centerx = rect.w / 2;
+    int centery = rect.h / 2;
+
+    float X1 = rawx;
+    float Y1 = rawy;
+    float X2 = centerx;
+    float Y2 = centery; 
+    float angle = 0.0;
+    float xd = X2-X1;
+    float yd = Y2-Y1;
+    float dx = sqrt(xd * xd + yd * yd);
+
+    // angle in degrees
+    angle = atan2(Y2 - Y1, X2 - X1) * 180 / 3.14159265358979323846;
+    if (angle < 0) angle += 360.0;
+
+    // if the distance > 128, can we calculate the line point at 128 and set the marker there?
+
+    if( dx > 128.0 ) dx = 128.0;  // limit value
+    
+    saturation_ = dx;
+    hue_ = angle;
+}
+
+void TBColorWheel::SetMarkerX ( int value )
+{
+    markerx_ = value;
+}
+
+void TBColorWheel::SetMarkerY ( int value )
+{
+    markery_ = value;
+}
+
+void TBColorWheel::SetMarkerColor ( const char *name )
+{
+ 	if ( name )
+  	 markercolor_.SetFromString(name, strlen(name));
+     
+    Invalidate();
+}
+
+void TBColorWheel::OnInflate(const INFLATE_INFO &info)
+{
+    if (const char *colr = info.node->GetValueString("color", nullptr))
+        SetMarkerColor(colr);
+    TBWidget::OnInflate(info);
+}
+
+TB_WIDGET_FACTORY(TBColorWheel, TBValue::TYPE_FLOAT, WIDGET_Z_TOP) {}
+
+
+}; // namespace tb

+ 111 - 0
Source/ThirdParty/TurboBadger/tb_atomic_widgets.h

@@ -0,0 +1,111 @@
+// ================================================================================
+// ==      This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås      ==
+// ==                     See tb_core.h for more information.                    ==
+// ================================================================================
+//
+// Copyright (c) 2016, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+#ifndef TB_ATOMIC_WIDGETS_H
+#define TB_ATOMIC_WIDGETS_H
+
+#include "tb_widgets.h"
+#include "tb_layout.h"
+#include "tb_msg.h"
+#include "tb_widgets_listener.h"
+#include "tb_widgets_common.h"
+
+namespace tb {
+
+// fruxo recommends : Subclass TBWidget and override OnPaint. From
+// there you can paint solid colors using g_tb_skin->PaintRectFill.
+class TBColorWidget : public TBWidget
+{
+public:
+    TBOBJECT_SUBCLASS(TBColorWidget, TBWidget);    // For safe typecasting
+
+    TBColorWidget();
+
+    void SetColor ( const char * );
+    void SetColor (float r, float g, float b, float a);
+
+    void SetAlpha ( float );
+
+    const TBColor& GetColor() const { return color_; }
+    float GetAlpha() const { return alpha_; }
+
+    virtual void OnInflate(const INFLATE_INFO &info);
+    virtual void OnPaint(const PaintProps &paint_props);
+
+private:
+
+	TBColor color_;
+    float alpha_;
+};
+
+class TBColorWheel : public TBWidget
+{
+public:
+    TBOBJECT_SUBCLASS(TBColorWheel, TBWidget);    // For safe typecasting
+
+    TBColorWheel();
+
+    virtual void OnInflate(const INFLATE_INFO &info);
+    virtual void OnPaint(const PaintProps &paint_props);
+    virtual bool OnEvent(const TBWidgetEvent &ev);
+
+    float GetHue() const { return hue_; }
+    float GetSaturation() const { return saturation_; }
+    void SetHueSaturation ( float hue, float saturation );
+    
+    void SetMarkerX ( int );
+    void SetMarkerY( int );
+    void SetMarkerColor ( const char * );
+    
+private:
+
+    void CalcHueSaturation ( int, int ); // maths.
+
+    int markerx_;
+    int markery_; // where we clicked, put a box there
+	TBColor markercolor_; // what color box, default = black
+    float hue_;   // varies with the angle
+    float saturation_; // varies with the radius.
+
+};
+
+class TBEventBlocker : public TBWidgetListener
+{
+
+public:
+
+    TBEventBlocker() : TBWidgetListener() { }
+    
+    /** Called when a event is about to be invoked on a widget. This make it possible
+        to intercept events before they are handled, and block it (by returning true --like here ).
+        Note, if returning true, other global listeners will still also be notified. */
+    virtual bool OnWidgetInvokeEvent(TBWidget *widget, const TBWidgetEvent &ev) { return true; } 
+    
+};
+
+
+}; // namespace tb
+
+#endif // TB_ATOMIC_WIDGETS_H