Ver código fonte

Merge pull request #2854 from MarianoGnu/color_picker

new ColorPicker
Rémi Verschelde 9 anos atrás
pai
commit
c0b9634235

+ 351 - 123
scene/gui/color_picker.cpp

@@ -28,25 +28,43 @@
 /*************************************************************************/
 #include "color_picker.h"
 
+#include "scene/gui/separator.h"
+#include "scene/main/viewport.h"
+#include "os/os.h"
+#include "os/input.h"
+#include "os/keyboard.h"
+
+void update_material(Ref<CanvasItemMaterial>mat,const Color& p_color) {
+	if (!mat.is_valid())
+		return;
+	Ref<Shader> sdr = mat->get_shader();
+	if (!sdr.is_valid())
+		return;
 
-
+		mat->set_shader_param("R",p_color.r);
+		mat->set_shader_param("G",p_color.g);
+		mat->set_shader_param("B",p_color.b);
+		mat->set_shader_param("H",p_color.get_h());
+		mat->set_shader_param("S",p_color.get_s());
+		mat->set_shader_param("V",p_color.get_v());
+		mat->set_shader_param("A",p_color.a);
+}
 
 void ColorPicker::_notification(int p_what) {
 
 
 	switch(p_what) {
 		case NOTIFICATION_THEME_CHANGED: {
-
+			uv_material->set_shader(get_shader("uv_editor"));
+			w_material->set_shader(get_shader("w_editor"));
+			update_material(uv_material,color);
+			update_material(w_material,color);
 			_update_controls();
 		} break;
 
-/*		case NOTIFICATION_DRAW: {
-
-			int w = get_constant("color_width");
-			int h = ms.height;
-			VisualServer::get_singleton()->canvas_item_add_rect(get_canvas_item(),Rect2(0,0,w,h),color);
-
-		} break;*/
+		case NOTIFICATION_ENTER_TREE: {
+			btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
+		}
 	}
 }
 
@@ -64,10 +82,16 @@ void ColorPicker::_update_controls() {
 
 }
 
-
 void ColorPicker::set_color(const Color& p_color) {
 
 	color=p_color;
+	h=color.get_h();
+	s=color.get_s();
+	v=color.get_v();
+	update_material(uv_material, color);
+	update_material(w_material, color);
+	uv_edit->get_child(0)->cast_to<Control>()->update();
+	w_edit->get_child(0)->cast_to<Control>()->update();
 	_update_color();
 
 }
@@ -77,7 +101,7 @@ void ColorPicker::set_edit_alpha(bool p_show) {
 	edit_alpha=p_show;
 	_update_controls();
 	_update_color();
-	color_box->update();
+	sample->update();
 }
 
 bool ColorPicker::is_editing_alpha() const {
@@ -90,35 +114,17 @@ void ColorPicker::_value_changed(double) {
 	if (updating)
 		return;
 
-	switch(mode) {
-
-		case MODE_RGB: {
-
-			for(int i=0;i<4;i++) {
-				color.components[i] = scroll[i]->get_val() / 255.0;
-			}
-
-		} break;
-		case MODE_HSV: {
-
-			color.set_hsv( CLAMP(scroll[0]->get_val()/359,0,0.9972), scroll[1]->get_val()/100, scroll[2]->get_val()/100 );
-			color.a=scroll[3]->get_val()/100.0;
-
-		} break;
-		case MODE_RAW: {
-
-			for(int i=0;i<4;i++) {
-				color.components[i] = scroll[i]->get_val();
-			}
-
-		} break;
-
+	for(int i=0;i<3;i++) {
+		color.components[i] = scroll[i]->get_val()/(raw_mode_enabled?1.0:255.0);
 	}
+	color.components[3] = scroll[3]->get_val()/255.0;
 
+	update_material(uv_material,color);
+	update_material(w_material,color);
 
 	html->set_text(color.to_html(edit_alpha && color.a<1));
 
-	color_box->update();
+	sample->update();
 
 	emit_signal("color_changed",color);
 
@@ -138,144 +144,325 @@ void ColorPicker::_update_color() {
 
 	updating=true;
 
-	switch(mode) {
-
-		case MODE_RAW: {
-
-			static const char*_lt[4]={"R","G","B","A"};
-
-			for(int i=0;i<4;i++) {
-				scroll[i]->set_max(255);
-				scroll[i]->set_step(0.01);
-				scroll[i]->set_val(color.components[i]);
-				labels[i]->set_text(_lt[i]);
-			}
-		} break;
-		case MODE_RGB: {
-
-			static const char*_lt[4]={"R","G","B","A"};
-
-			for(int i=0;i<4;i++) {
-				scroll[i]->set_max(255);
-				scroll[i]->set_step(1);
-				scroll[i]->set_val(color.components[i]*255);
-				labels[i]->set_text(_lt[i]);
-			}
-
-		} break;
-		case MODE_HSV: {
-
-			static const char*_lt[4]={"H","S","V","A"};
+	for(int i=0;i<4;i++) {
+		scroll[i]->set_max(255);
+		scroll[i]->set_step(0.01);
+		if (raw_mode_enabled && i != 3)
+			scroll[i]->set_val(color.components[i]);
+		else
+			scroll[i]->set_val(color.components[i]*255);
+	}
 
-			for(int i=0;i<4;i++) {
-				labels[i]->set_text(_lt[i]);
-			}
+	html->set_text(color.to_html(edit_alpha && color.a<1));
 
-			scroll[0]->set_max(359);
-			scroll[0]->set_step(0.01);
-			scroll[0]->set_val( color.get_h()*359 );
+	sample->update();
+	updating=false;
+}
 
-			scroll[1]->set_max(100);
-			scroll[1]->set_step(0.01);
-			scroll[1]->set_val( color.get_s()*100 );
+void ColorPicker::_update_presets()
+{
+	Size2 size=bt_add_preset->get_size();
+	preset->set_custom_minimum_size(Size2(size.width*presets.size(),size.height));
+	Image i(size.x*presets.size(),size.y, false, Image::FORMAT_RGB);
+	for (int y=0;y<size.y;y++)
+		for (int x=0;x<size.x*presets.size();x++)
+			i.put_pixel(x,y,presets[(int)x/size.x]);
+	Ref<ImageTexture> t;
+	t.instance();
+	t->create_from_image(i);
+	preset->set_texture(t);
+}
 
-			scroll[2]->set_max(100);
-			scroll[2]->set_step(0.01);
-			scroll[2]->set_val( color.get_v()*100 );
+Color ColorPicker::get_color() const {
 
-			scroll[3]->set_max(100);
-			scroll[3]->set_step(0.01);
-			scroll[3]->set_val( color.a*100);
+	return color;
+}
 
-		} break;
+void ColorPicker::add_preset(const Color &p_color)
+{
+	if (presets.find(p_color)) {
+		presets.move_to_back(presets.find(p_color));
+	} else {
+		presets.push_back(p_color);
 	}
+	_update_presets();
+	if (presets.size()==10)
+		bt_add_preset->hide();
+}
 
 
-	html->set_text(color.to_html(edit_alpha && color.a<1));
+void ColorPicker::set_raw_mode(bool p_enabled) {
 
-	color_box->update();
-	updating=false;
+	if (raw_mode_enabled==p_enabled)
+		return;
+	raw_mode_enabled=p_enabled;
+	if (btn_mode->is_pressed()!=p_enabled)
+		btn_mode->set_pressed(p_enabled);
+	
+	_update_controls();
+	_update_color();
 }
 
-Color ColorPicker::get_color() const {
+bool ColorPicker::is_raw_mode() const {
 
-	return color;
+	return raw_mode_enabled;
 }
 
+void ColorPicker::_sample_draw() {
+	sample->draw_rect(Rect2(Point2(),Size2(256,20)),color);
+}
 
-void ColorPicker::set_mode(Mode p_mode) {
+void ColorPicker::_hsv_draw(int p_wich,Control* c)
+{
+	if (!c)
+		return;
+	if (p_wich==0) {
+		int x=c->get_size().x*color.get_s();
+		int y=c->get_size().y-c->get_size().y*color.get_v();
+		c->draw_line(Point2(x,0),Point2(x,c->get_size().y),color.inverted());
+		c->draw_line(Point2(0,y),Point2(c->get_size().x,y),color.inverted());
+		c->draw_line(Point2(x,y),Point2(x,y),Color(1,1,1),2);
+	} else if (p_wich==1) {
+		int y=c->get_size().y-c->get_size().y*color.get_h();
+		Color col=Color();
+		col.set_hsv(color.get_h(),1,1);
+		c->draw_line(Point2(0,y),Point2(c->get_size().x,y),col.inverted());
+	}
+}
 
-	ERR_FAIL_INDEX(p_mode,3);
-	mode=p_mode;
-	if (mode_box->get_selected()!=p_mode)
-		mode_box->select(p_mode);
+void ColorPicker::_uv_input(const InputEvent &ev) {
+	if (ev.type == InputEvent::MOUSE_BUTTON) {
+		const InputEventMouseButton &bev = ev.mouse_button;
+		if (bev.pressed) {
+			changing_color = true;
+			float x = CLAMP((float)bev.x,0,256);
+			float y = CLAMP((float)bev.y,0,256);
+			s=x/256;
+			v=1.0-y/256.0;
+			color.set_hsv(h,s,v,color.a);
+			set_color(color);
+			_update_color();
+			emit_signal("color_changed", color);
+		} else {
+			changing_color = false;
+		}
+	} else if (ev.type == InputEvent::MOUSE_MOTION) {
+		const InputEventMouse &bev = ev.mouse_motion;
+		if (!changing_color)
+			return;
+		float x = CLAMP((float)bev.x,0,256);
+		float y = CLAMP((float)bev.y,0,256);
+		s=x/256;
+		v=1.0-y/256.0;
+		color.set_hsv(h,s,v,color.a);
+		set_color(color);
+		_update_color();
+		emit_signal("color_changed", color);
+	}
+}
 
-	_update_controls();
-	_update_color();
+void ColorPicker::_w_input(const InputEvent &ev) {
+	if (ev.type == InputEvent::MOUSE_BUTTON) {
+		const InputEventMouseButton &bev = ev.mouse_button;
+		if (bev.pressed) {
+			changing_color = true;
+			h=1-((float)bev.y)/256.0;
+			
+		} else {
+			changing_color = false;
+		}
+		color.set_hsv(h,s,v,color.a);
+		set_color(color);
+		_update_color();
+		emit_signal("color_changed", color);
+	} else if (ev.type == InputEvent::MOUSE_MOTION) {
+		const InputEventMouse &bev = ev.mouse_motion;
+		if (!changing_color)
+			return;
+		float y = CLAMP((float)bev.y,0,256);
+		h=1.0-y/256.0;
+		color.set_hsv(h,s,v,color.a);
+		set_color(color);
+		_update_color();
+		emit_signal("color_changed", color);
+	}
 }
 
-ColorPicker::Mode ColorPicker::get_mode() const {
+void ColorPicker::_preset_input(const InputEvent &ev) {
+	if (ev.type == InputEvent::MOUSE_BUTTON) {
+		const InputEventMouseButton &bev = ev.mouse_button;
+		if (bev.pressed && bev.button_index==BUTTON_LEFT) {
+			int index = bev.x/(preset->get_size().x/presets.size());
+			set_color(presets[index]);
+		} else if (bev.pressed && bev.button_index==BUTTON_RIGHT) {
+			int index = bev.x/(preset->get_size().x/presets.size());
+			presets.erase(presets[index]);
+			_update_presets();
+			bt_add_preset->show();
+		}
+		_update_color();
+		emit_signal("color_changed", color);
+	} else if (ev.type == InputEvent::MOUSE_MOTION) {
+		const InputEventMouse &mev = ev.mouse_motion;
+		int index = mev.x/(preset->get_size().x/presets.size());
+		if (index<0 || index >= presets.size())
+			return;
+		preset->set_tooltip("Color: #"+presets[index].to_html(presets[index].a<1)+"\n"
+							"LMB: Set color\n"
+							"RMB: Remove preset");
+	}
+}
 
-	return mode;
+void ColorPicker::_screen_input(const InputEvent &ev)
+{
+	if (ev.type==InputEvent::MOUSE_BUTTON) {
+		const InputEventMouseButton &bev = ev.mouse_button;
+		if (bev.button_index==BUTTON_LEFT&&!bev.pressed) {
+			emit_signal("color_changed", color);
+			screen->hide();
+		}
+	} else if (ev.type==InputEvent::MOUSE_MOTION) {
+		const InputEventMouse &mev = ev.mouse_motion;
+		Viewport *r=get_tree()->get_root();
+		if (!r->get_rect().has_point(Point2(mev.global_x,mev.global_y)))
+			return;
+		Image img =r->get_screen_capture();
+		if (!img.empty())
+			last_capture=img;
+			r->queue_screen_capture();
+		if (!last_capture.empty())
+			set_color(last_capture.get_pixel(mev.global_x,mev.global_y));
+	}
 }
 
-void ColorPicker::_color_box_draw() {
+void ColorPicker::_add_preset_pressed() {
+	add_preset(color);
+}
 
-	color_box->draw_rect( Rect2( Point2(), color_box->get_size()), color);
+void ColorPicker::_screen_pick_pressed()
+{
+	Viewport *r=get_tree()->get_root();
+	if (!screen) {
+		screen=memnew( Control );
+		r->add_child(screen);
+		screen->set_area_as_parent_rect();
+		screen->connect("input_event",this,"_screen_input");
+	}
+	screen->raise();
+	screen->show();
+	r->queue_screen_capture();
 }
 
 void ColorPicker::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("set_color","color"),&ColorPicker::set_color);
 	ObjectTypeDB::bind_method(_MD("get_color"),&ColorPicker::get_color);
-	ObjectTypeDB::bind_method(_MD("set_mode","mode"),&ColorPicker::set_mode);
-	ObjectTypeDB::bind_method(_MD("get_mode"),&ColorPicker::get_mode);
+	ObjectTypeDB::bind_method(_MD("set_raw_mode","mode"),&ColorPicker::set_raw_mode);
+	ObjectTypeDB::bind_method(_MD("is_raw_mode"),&ColorPicker::is_raw_mode);
 	ObjectTypeDB::bind_method(_MD("set_edit_alpha","show"),&ColorPicker::set_edit_alpha);
 	ObjectTypeDB::bind_method(_MD("is_editing_alpha"),&ColorPicker::is_editing_alpha);
+	ObjectTypeDB::bind_method(_MD("add_preset"), &ColorPicker::add_preset);
 	ObjectTypeDB::bind_method(_MD("_value_changed"),&ColorPicker::_value_changed);
 	ObjectTypeDB::bind_method(_MD("_html_entered"),&ColorPicker::_html_entered);
-	ObjectTypeDB::bind_method(_MD("_color_box_draw"),&ColorPicker::_color_box_draw);
+	ObjectTypeDB::bind_method(_MD("_add_preset_pressed"), &ColorPicker::_add_preset_pressed);
+	ObjectTypeDB::bind_method(_MD("_screen_pick_pressed"), &ColorPicker::_screen_pick_pressed);
+	ObjectTypeDB::bind_method(_MD("_sample_draw"),&ColorPicker::_sample_draw);
+	ObjectTypeDB::bind_method(_MD("_hsv_draw"),&ColorPicker::_hsv_draw);
+	ObjectTypeDB::bind_method(_MD("_uv_input"),&ColorPicker::_uv_input);
+	ObjectTypeDB::bind_method(_MD("_w_input"),&ColorPicker::_w_input);
+	ObjectTypeDB::bind_method(_MD("_preset_input"),&ColorPicker::_preset_input);
+	ObjectTypeDB::bind_method(_MD("_screen_input"),&ColorPicker::_screen_input);
 
 	ADD_SIGNAL( MethodInfo("color_changed",PropertyInfo(Variant::COLOR,"color")));
 }
 
+ColorPicker::ColorPicker() :
+	BoxContainer(true) {
 
-
-
-ColorPicker::ColorPicker() {
-
-
-	//edit_alpha=false;
 	updating=true;
 	edit_alpha=true;
+	raw_mode_enabled=false;
+	changing_color=false;
+	screen=NULL;
+
+	HBoxContainer *hb_smpl = memnew( HBoxContainer );
+	btn_pick = memnew( ToolButton );
+	btn_pick->connect("pressed",this,"_screen_pick_pressed");
+
+	sample = memnew( TextureFrame );
+	sample->set_h_size_flags(SIZE_EXPAND_FILL);
+	sample->connect("draw",this,"_sample_draw");
+
+	hb_smpl->add_child(sample);
+	hb_smpl->add_child(btn_pick);
+	add_child(hb_smpl);
+
+	HBoxContainer *hb_edit = memnew( HBoxContainer );
+
+	uv_edit= memnew ( TextureFrame );
+	Image i(256, 256, false, Image::FORMAT_RGB);
+	for (int y=0;y<256;y++)
+		for (int x=0;x<256;x++)
+			i.put_pixel(x,y,Color());
+	Ref<ImageTexture> t;
+	t.instance();
+	t->create_from_image(i);
+	uv_edit->set_texture(t);
+	uv_edit->set_ignore_mouse(false);
+	uv_edit->set_custom_minimum_size(Size2(256,256));
+	uv_edit->connect("input_event", this, "_uv_input");
+	Control *c= memnew( Control );
+	uv_edit->add_child(c);
+	c->set_area_as_parent_rect();
+	c->set_stop_mouse(false);
+	c->set_material(memnew ( CanvasItemMaterial ));
+	Vector<Variant> args=Vector<Variant>();
+	args.push_back(0);
+	args.push_back(c);
+	c->connect("draw",this,"_hsv_draw",args);
+
+	add_child(hb_edit);
+	w_edit= memnew( TextureFrame );
+	i = Image(15, 256, false, Image::FORMAT_RGB);
+	for (int y=0;y<256;y++)
+		for (int x=0;x<15;x++)
+			i.put_pixel(x,y,Color());
+	Ref<ImageTexture> tw;
+	tw.instance();
+	tw->create_from_image(i);
+	w_edit->set_texture(tw);
+	w_edit->set_ignore_mouse(false);
+	w_edit->set_custom_minimum_size(Size2(15,256));
+	w_edit->connect("input_event", this, "_w_input");
+	c= memnew( Control );
+	w_edit->add_child(c);
+	c->set_area_as_parent_rect();
+	c->set_stop_mouse(false);
+	c->set_material(memnew ( CanvasItemMaterial ));
+	args.clear();
+	args.push_back(1);
+	args.push_back(c);
+	c->connect("draw",this,"_hsv_draw",args);
+	
+	hb_edit->add_child(uv_edit);
+	hb_edit->add_child(memnew( VSeparator ));
+	hb_edit->add_child(w_edit);
 
 	VBoxContainer *vbl = memnew( VBoxContainer );
 	add_child(vbl);
 
-	mode_box = memnew( OptionButton );
-	mode_box->add_item("RGB");
-	mode_box->add_item("HSV");
-	mode_box->add_item("RAW");
-	mode_box->connect("item_selected",this,"set_mode");
-
-	color_box=memnew( Control );
-	color_box->set_v_size_flags(SIZE_EXPAND_FILL);
-	vbl->add_child(color_box);
-	color_box->connect("draw",this,"_color_box_draw");
-
-	vbl->add_child(mode_box);
-
+	add_child(memnew( HSeparator ));
 
 	VBoxContainer *vbr = memnew( VBoxContainer );
 	add_child(vbr);
 	vbr->set_h_size_flags(SIZE_EXPAND_FILL);
-
+	const char* lt[4] = {"R","G","B","A"};
 
 	for(int i=0;i<4;i++) {
 
 		HBoxContainer *hbc = memnew( HBoxContainer );
 
-		labels[i]=memnew( Label );
+		labels[i]=memnew( Label(lt[i]) );
 		hbc->add_child(labels[i]);
 
 		scroll[i]=memnew( HSlider );
@@ -294,10 +481,14 @@ ColorPicker::ColorPicker() {
 
 		vbr->add_child(hbc);
 
-
 	}
 
 	HBoxContainer *hhb = memnew( HBoxContainer );
+	
+	btn_mode = memnew( CheckButton );
+	btn_mode->set_text("RAW Mode");
+	btn_mode->connect("toggled", this, "set_raw_mode");
+	hhb->add_child(btn_mode);
 	vbr->add_child(hhb);
 	html_num = memnew( Label );
 	hhb->add_child(html_num);
@@ -309,11 +500,49 @@ ColorPicker::ColorPicker() {
 	html->set_h_size_flags(SIZE_EXPAND_FILL);
 
 
-	mode=MODE_RGB;
 	_update_controls();
 	_update_color();
 	updating=false;
 
+	uv_material.instance();
+	Ref<Shader> s_uv = get_shader("uv_editor");
+	uv_material->set_shader(s_uv);
+
+	w_material.instance();
+	
+	Ref<Shader> s_w = get_shader("w_editor");
+	w_material->set_shader(s_w);
+
+	uv_edit->set_material(uv_material);
+	w_edit->set_material(w_material);
+
+	set_color(Color(1,1,1));
+
+	i.create(256,20,false,Image::FORMAT_RGB);
+	for (int y=0;y<20;y++)
+		for(int x=0;x<256;x++)
+			if ((x/4+y/4)%2)
+				i.put_pixel(x,y,Color(1,1,1));
+			else
+				i.put_pixel(x,y,Color(0.6,0.6,0.6));
+	Ref<ImageTexture> t_smpl;
+	t_smpl.instance();
+	t_smpl->create_from_image(i);
+	sample->set_texture(t_smpl);
+
+	HBoxContainer *bbc = memnew( HBoxContainer );
+	add_child(bbc);
+
+	preset = memnew( TextureFrame );
+	bbc->add_child(preset);
+	preset->set_ignore_mouse(false);
+	preset->connect("input_event", this, "_preset_input");
+
+	bt_add_preset = memnew ( Button );
+	bt_add_preset->set_icon(get_icon("add_preset"));
+	bt_add_preset->set_tooltip("Add current color as a preset");
+	bt_add_preset->connect("pressed", this, "_add_preset_pressed");
+	bbc->add_child(bt_add_preset);
 }
 
 
@@ -331,7 +560,7 @@ void ColorPickerButton::_color_changed(const Color& p_color) {
 
 void ColorPickerButton::pressed() {
 
-	Size2 ms = Size2(350, picker->get_combined_minimum_size().height+10);
+	Size2 ms = Size2(300, picker->get_combined_minimum_size().height+10);
 	popup->set_pos(get_global_pos()-Size2(0,ms.height));
 	popup->set_size(ms);
 	popup->popup();
@@ -347,7 +576,6 @@ void ColorPickerButton::_notification(int p_what) {
 	}
 }
 
-
 void ColorPickerButton::set_color(const Color& p_color){
 
 

+ 34 - 19
scene/gui/color_picker.h

@@ -36,25 +36,29 @@
 #include "scene/gui/button.h"
 #include "scene/gui/popup.h"
 #include "scene/gui/box_container.h"
-#include "scene/gui/option_button.h"
+#include "scene/gui/texture_frame.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/check_button.h"
+#include "scene/resources/material.h"
 
-class ColorPicker : public HBoxContainer {
+class ColorPicker : public BoxContainer {
 
-	OBJ_TYPE(ColorPicker,HBoxContainer);
-public:
+	OBJ_TYPE(ColorPicker,BoxContainer);
 
-	enum Mode {
-		MODE_RGB,
-		MODE_HSV,
-		MODE_RAW
-	};
 private:
 
-	Mode mode;
-
-	OptionButton *mode_box;
-
-	Control *color_box;
+	Control *screen;
+	Image last_capture;
+	TextureFrame *uv_edit;
+	TextureFrame *w_edit;
+	TextureFrame *sample;
+	TextureFrame *preset;
+	Button *bt_add_preset;
+	List<Color> presets;
+	ToolButton *btn_pick;
+	CheckButton *btn_mode;
+	Ref<CanvasItemMaterial> uv_material;
+	Ref<CanvasItemMaterial> w_material;
 	HSlider *scroll[4];
 	SpinBox *values[4];
 	Label *labels[4];
@@ -64,13 +68,25 @@ private:
 	Size2i ms;
 
 	Color color;
+	bool raw_mode_enabled;
 	bool updating;
+	bool changing_color;
+	float h,s,v;
 
 	void _html_entered(const String& p_html);
 	void _value_changed(double);
 	void _update_controls();
 	void _update_color();
-	void _color_box_draw();
+	void _update_presets();
+	void _sample_draw();
+	void _hsv_draw(int p_wich,Control *c);
+
+	void _uv_input(const InputEvent& p_input);
+	void _w_input(const InputEvent& p_input);
+	void _preset_input(const InputEvent& p_input);
+	void _screen_input(const InputEvent& p_input);
+	void _add_preset_pressed();
+	void _screen_pick_pressed();
 protected:
 
 	void _notification(int);
@@ -83,15 +99,14 @@ public:
 	void set_color(const Color& p_color);
 	Color get_color() const;
 
-	void set_mode(Mode p_mode);
-	Mode get_mode() const;
+	void add_preset(const Color& p_color);
+	void set_raw_mode(bool p_enabled);
+	bool is_raw_mode() const;
 
 
 	ColorPicker();
 };
 
-VARIANT_ENUM_CAST( ColorPicker::Mode );
-
 class ColorPickerButton : public Button {
 
 	OBJ_TYPE(ColorPickerButton,Button);

+ 93 - 1
scene/gui/control.cpp

@@ -109,6 +109,11 @@ bool Control::_set(const StringName& p_name, const Variant& p_value) {
 			data.icon_override.erase(dname);
 			notification(NOTIFICATION_THEME_CHANGED);
 			update();
+		} else if (name.begins_with("custom_shaders/")) {
+			String dname = name.get_slicec('/',1);
+			data.shader_override.erase(dname);
+			notification(NOTIFICATION_THEME_CHANGED);
+			update();
 		} else if (name.begins_with("custom_styles/")) {
 			String dname = name.get_slicec('/',1);
 			data.style_override.erase(dname);
@@ -137,6 +142,10 @@ bool Control::_set(const StringName& p_name, const Variant& p_value) {
 			String dname = name.get_slicec('/',1);
 			notification(NOTIFICATION_THEME_CHANGED);
 			add_icon_override(dname,p_value);
+		} else if (name.begins_with("custom_shaders/")) {
+			String dname = name.get_slicec('/',1);
+			add_shader_override(dname,p_value);
+			notification(NOTIFICATION_THEME_CHANGED);
 		} else if (name.begins_with("custom_styles/")) {
 			String dname = name.get_slicec('/',1);
 			add_style_override(dname,p_value);
@@ -189,6 +198,10 @@ bool Control::_get(const StringName& p_name,Variant &r_ret) const {
 		String name = sname.get_slicec('/',1);
 
 		r_ret= data.icon_override.has(name)?Variant(data.icon_override[name]):Variant();
+	} else if (sname.begins_with("custom_shaders/")) {
+		String name = sname.get_slicec('/',1);
+
+		r_ret= data.shader_override.has(name)?Variant(data.shader_override[name]):Variant();
 	} else if (sname.begins_with("custom_styles/")) {
 		String name = sname.get_slicec('/',1);
 
@@ -236,6 +249,18 @@ void Control::_get_property_list( List<PropertyInfo> *p_list) const {
 			p_list->push_back( PropertyInfo(Variant::OBJECT,"custom_icons/"+E->get(),PROPERTY_HINT_RESOURCE_TYPE, "Texture",hint) );
 		}
 	}
+	{
+		List<StringName> names;
+		theme->get_shader_list(get_type_name(),&names);
+		for(List<StringName>::Element *E=names.front();E;E=E->next()) {
+
+			uint32_t hint= PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CHECKABLE;
+			if (data.shader_override.has(E->get()))
+				hint|=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_CHECKED;
+
+			p_list->push_back( PropertyInfo(Variant::OBJECT,"custom_shaders/"+E->get(),PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph",hint) );
+		}
+	}
 	{
 		List<StringName> names;
 		theme->get_stylebox_list(get_type_name(),&names);
@@ -650,6 +675,35 @@ Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type
 
 }
 
+Ref<Shader> Control::get_shader(const StringName& p_name,const StringName& p_type) const {
+	if (p_type==StringName()) {
+
+		const Ref<Shader>* sdr = data.shader_override.getptr(p_name);
+		if (sdr)
+			return *sdr;
+	}
+
+	StringName type = p_type?p_type:get_type_name();
+
+	// try with custom themes
+	Control *theme_owner = data.theme_owner;
+
+	while(theme_owner) {
+
+		if (theme_owner->data.theme->has_shader(p_name, type))
+			return data.theme_owner->data.theme->get_shader(p_name, type );
+		Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL;
+
+		if (parent)
+			theme_owner=parent->data.theme_owner;
+		else
+			theme_owner=NULL;
+
+	}
+
+	return Theme::get_default()->get_shader( p_name, type );
+}
+
 Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p_type) const {
 		
 	if (p_type==StringName()) {
@@ -796,7 +850,37 @@ bool Control::has_icon(const StringName& p_name,const StringName& p_type) const
 	}
 
 	return Theme::get_default()->has_icon( p_name, type );
+	
+}
+
+bool Control::has_shader(const StringName &p_name, const StringName &p_type) const
+{
+	if (p_type==StringName()) {
+		const Ref<Shader>* sdr = data.shader_override.getptr(p_name);
+		if (sdr)
+			return true;
+	}
+
+	StringName type = p_type?p_type:get_type_name();
+
+	// try with custom themes
+	Control *theme_owner = data.theme_owner;
+
+	while(theme_owner) {
 
+		if (theme_owner->data.theme->has_shader(p_name, type))
+			return true;
+		Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL;
+
+		if (parent)
+			theme_owner=parent->data.theme_owner;
+		else
+			theme_owner=NULL;
+
+	}
+
+	return Theme::get_default()->has_shader( p_name, type );
+	
 }
 bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) const {
 		
@@ -1261,7 +1345,14 @@ void Control::add_icon_override(const StringName& p_name, const Ref<Texture>& p_
 	data.icon_override[p_name]=p_icon;
 	notification(NOTIFICATION_THEME_CHANGED);
 	update();
+	
+}
 
+void Control::add_shader_override(const StringName &p_name, const Ref<Shader> &p_shader) {
+	ERR_FAIL_COND(p_shader.is_null());
+	data.shader_override[p_name]=p_shader;
+	notification(NOTIFICATION_THEME_CHANGED);
+	update();
 }
 void Control::add_style_override(const StringName& p_name, const Ref<StyleBox>& p_style) {
 
@@ -2011,8 +2102,9 @@ void Control::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("set_theme","theme:Theme"),&Control::set_theme);
 	ObjectTypeDB::bind_method(_MD("get_theme:Theme"),&Control::get_theme);
-
+	
 	ObjectTypeDB::bind_method(_MD("add_icon_override","name","texture:Texture"),&Control::add_icon_override);
+	ObjectTypeDB::bind_method(_MD("add_shader_override","name","shader:Shader"),&Control::add_shader_override);
 	ObjectTypeDB::bind_method(_MD("add_style_override","name","stylebox:StyleBox"),&Control::add_style_override);
 	ObjectTypeDB::bind_method(_MD("add_font_override","name","font:Font"),&Control::add_font_override);
 	ObjectTypeDB::bind_method(_MD("add_color_override","name","color"),&Control::add_color_override);

+ 5 - 1
scene/gui/control.h

@@ -142,6 +142,7 @@ private:
 		NodePath focus_neighbour[4];
 
 		HashMap<StringName, Ref<Texture>, StringNameHasher > icon_override;
+		HashMap<StringName, Ref<Shader>, StringNameHasher > shader_override;
 		HashMap<StringName, Ref<StyleBox>, StringNameHasher > style_override;
 		HashMap<StringName, Ref<Font>, StringNameHasher > font_override;
 		HashMap<StringName, Color, StringNameHasher > color_override;
@@ -315,18 +316,21 @@ public:
 	/* SKINNING */
 	
 	void add_icon_override(const StringName& p_name, const Ref<Texture>& p_icon);
+	void add_shader_override(const StringName& p_name, const Ref<Shader>& p_shader);
 	void add_style_override(const StringName& p_name, const Ref<StyleBox>& p_style);
 	void add_font_override(const StringName& p_name, const Ref<Font>& p_font);
 	void add_color_override(const StringName& p_name, const Color& p_color);
 	void add_constant_override(const StringName& p_name, int p_constant);
 
 	Ref<Texture> get_icon(const StringName& p_name,const StringName& p_type=StringName()) const;
+	Ref<Shader> get_shader(const StringName &p_name, const StringName &p_type=StringName()) const;
 	Ref<StyleBox> get_stylebox(const StringName& p_name,const StringName& p_type=StringName()) const;
 	Ref<Font> get_font(const StringName& p_name,const StringName& p_type=StringName()) const;
 	Color get_color(const StringName& p_name,const StringName& p_type=StringName()) const;
 	int get_constant(const StringName& p_name,const StringName& p_type=StringName()) const;
 
 	bool has_icon(const StringName& p_name,const StringName& p_type=StringName()) const;
+	bool has_shader(const StringName& p_name,const StringName& p_type=StringName()) const;
 	bool has_stylebox(const StringName& p_name,const StringName& p_type=StringName()) const;
 	bool has_font(const StringName& p_name,const StringName& p_type=StringName()) const;
 	bool has_color(const StringName& p_name,const StringName& p_type=StringName()) const;
@@ -358,7 +362,7 @@ public:
 
 	Control();	
 	~Control();
-
+	
 };
 
 VARIANT_ENUM_CAST(Control::AnchorType);

+ 12 - 1
scene/resources/default_theme/default_theme.cpp

@@ -80,6 +80,13 @@ static Ref<Texture> make_icon(T p_src) {
 	return texture;
 }
 
+static Ref<Shader> make_shader(const char*vertex_code,const char*fragment_code,const char*lighting_code) {
+	Ref<Shader> shader = (memnew( Shader(Shader::MODE_CANVAS_ITEM) ));
+	shader->set_code(vertex_code, fragment_code, lighting_code);
+
+	return shader;
+}
+
 static Ref<Font> make_font(int p_height,int p_ascent, int p_valign, int p_charcount, const int *p_chars,const Ref<Texture> &p_texture) {
 
 
@@ -767,7 +774,11 @@ void make_default_theme() {
 	t->set_constant("label_width","ColorPicker", 20);
 	t->set_constant("hseparator","ColorPicker", 4);
 
-
+	t->set_icon("screen_picker","ColorPicker", make_icon( icon_color_pick_png ) );
+	t->set_icon("add_preset","ColorPicker", make_icon( icon_add_png ) );
+	
+	t->set_shader("uv_editor", "ColorPicker", make_shader("", uv_editor_shader_code, ""));
+	t->set_shader("w_editor", "ColorPicker", make_shader("", w_editor_shader_code, ""));
 
 	// TooltipPanel
 

BIN
scene/resources/default_theme/icon_add.png


BIN
scene/resources/default_theme/icon_color_pick.png


+ 43 - 12
scene/resources/default_theme/make_png_header.py → scene/resources/default_theme/make_header.py

@@ -3,9 +3,6 @@ import os;
 import glob;
 import string;
 
-pixmaps = glob.glob("*.png");
-
-pixmaps.sort();
 
 #Generate include files
 
@@ -15,27 +12,61 @@ f.write("// THIS FILE HAS BEEN AUTOGENERATED, DONT EDIT!!\n");
 
 f.write("\n\n");
 
+#Generate png image block
+
+pixmaps = glob.glob("*.png");
+
+pixmaps.sort();
+
 f.write("\n\n\n");
-	
 
-	
 for x in pixmaps:
-	
+
 	var_str=x[:-4]+"_png";
-	
+
 	f.write("static const unsigned char "+ var_str +"[]={\n");
-	
+
 	pngf=open(x,"rb");
-	
+
 	b=pngf.read(1);
 	while(len(b)==1):
 		f.write(hex(ord(b)))
 		b=pngf.read(1);
 		if (len(b)==1):
 			f.write(",")
-			
+
 	f.write("\n};\n\n\n");
 	pngf.close();
-	
-f.close();
 
+#Generate shaders block
+
+shaders = glob.glob("*.gsl")
+
+shaders.sort();
+
+f.write("\n\n\n");
+
+for x in shaders:
+
+	var_str=x[:-4]+"_shader_code";
+
+	f.write("static const char *"+ var_str +"=\n");
+
+	sf=open(x,"rb");
+
+
+	b=sf.readline();
+	while(b!=""):
+		if (b.endswith("\r\n")):
+			b=b[:-2]
+		if (b.endswith("\n")):
+			b=b[:-1]
+		f.write("			\""+b)
+		b=sf.readline();
+		if (b!=""):
+			f.write("\"\n")
+
+	f.write("\";\n\n\n");
+	sf.close();
+
+f.close();

Diferenças do arquivo suprimidas por serem muito extensas
+ 6 - 0
scene/resources/default_theme/theme_data.h


+ 19 - 0
scene/resources/default_theme/uv_editor.gsl

@@ -0,0 +1,19 @@
+vec3 nd1sl2=vec3(UV,0);
+uniform float H=0;
+float nd4sl0=H;
+float nd7sl0=nd1sl2.x;
+float nd7sl1=nd1sl2.y;
+float nd7sl2=nd1sl2.z;
+float nd2sl1def=-1;
+float nd2sl0=nd7sl1*nd2sl1def;
+float nd6sl1def=1;
+float nd6sl0=nd2sl0+nd6sl1def;
+vec3 nd3sl0=vec3(nd4sl0,nd7sl0,nd6sl0);
+vec3 nd5sl0;
+{
+	vec3 c = nd3sl0;
+	vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+	vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+	nd5sl0=c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
+COLOR.rgb=nd5sl0;

+ 11 - 0
scene/resources/default_theme/w_editor.gsl

@@ -0,0 +1,11 @@
+vec3 nd1sl2=vec3(UV,0);
+float nd2sl1=1-nd1sl2.y;
+vec3 nd3sl0=vec3(nd2sl1,1,1);
+vec3 nd6sl0;
+{
+	vec3 c = nd3sl0;
+	vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+	vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+	nd6sl0=c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
+COLOR.rgb=nd6sl0;

+ 45 - 0
scene/resources/theme.cpp

@@ -266,7 +266,52 @@ void Theme::get_icon_list(StringName p_type, List<StringName> *p_list) const {
 
 		p_list->push_back(*key);
 	}
+	
+}
+
+void Theme::set_shader(const StringName &p_name,const StringName &p_type,const Ref<Shader>& p_shader) {
+	bool new_value=!shader_map.has(p_type) || !shader_map[p_type].has(p_name);
+
+	shader_map[p_type][p_name]=p_shader;	
 
+	if (new_value) {
+		_change_notify();
+		emit_changed();;
+	}
+}
+
+Ref<Shader> Theme::get_shader(const StringName &p_name, const StringName &p_type) const {
+	if (shader_map.has(p_type) && shader_map[p_type].has(p_name) && shader_map[p_type][p_name].is_valid()) {
+		return shader_map[p_type][p_name];
+	} else {
+		return NULL;
+	}
+}
+
+bool Theme::has_shader(const StringName &p_name, const StringName &p_type) const {
+	return (shader_map.has(p_type) && shader_map[p_type].has(p_name) && shader_map[p_type][p_name].is_valid());
+}
+
+void Theme::clear_shader(const StringName &p_name, const StringName &p_type) {
+	ERR_FAIL_COND(!shader_map.has(p_type));
+	ERR_FAIL_COND(!shader_map[p_type].has(p_name));
+
+	shader_map[p_type].erase(p_name);
+	_change_notify();
+	emit_changed();;
+}
+
+void Theme::get_shader_list(const StringName &p_type, List<StringName> *p_list) const {
+	if (!shader_map.has(p_type))
+		return;
+
+	const StringName *key=NULL;
+
+	while((key=shader_map[p_type].next(key))) {
+
+		p_list->push_back(*key);
+	}
+	
 }
 
 

+ 9 - 1
scene/resources/theme.h

@@ -33,6 +33,7 @@
 #include "scene/resources/font.h"
 #include "scene/resources/style_box.h"
 #include "scene/resources/texture.h"
+#include "scene/resources/shader.h"
 #include "io/resource_loader.h"
 
 /**
@@ -48,6 +49,7 @@ class Theme : public Resource {
 	HashMap<StringName,HashMap<StringName,Ref<Texture>,StringNameHasher >, StringNameHasher >  icon_map;
 	HashMap<StringName,HashMap<StringName,Ref<StyleBox>,StringNameHasher >,StringNameHasher > style_map;
 	HashMap<StringName,HashMap<StringName,Ref<Font>,StringNameHasher >,StringNameHasher > font_map;
+	HashMap<StringName,HashMap<StringName,Ref<Shader>,StringNameHasher >, StringNameHasher >  shader_map;
 	HashMap<StringName,HashMap<StringName,Color,StringNameHasher >,StringNameHasher > color_map;
 	HashMap<StringName,HashMap<StringName,int,StringNameHasher>,StringNameHasher > constant_map;
 protected:
@@ -86,7 +88,13 @@ public:
 	bool has_icon(const StringName& p_name,const StringName& p_type) const;
 	void clear_icon(const StringName& p_name,const StringName& p_type);
 	void get_icon_list(StringName p_type, List<StringName> *p_list) const;
-	
+
+	void set_shader(const StringName& p_name,const StringName& p_type,const Ref<Shader>& p_shader);
+	Ref<Shader> get_shader(const StringName& p_name,const StringName& p_type) const;
+	bool has_shader(const StringName& p_name,const StringName& p_type) const;
+	void clear_shader(const StringName& p_name,const StringName& p_type);
+	void get_shader_list(const StringName& p_name, List<StringName> *p_list) const;
+
 	void set_stylebox(const StringName& p_name,const StringName& p_type,const Ref<StyleBox>& p_style);
 	Ref<StyleBox> get_stylebox(const StringName& p_name,const StringName& p_type) const;
 	bool has_stylebox(const StringName& p_name,const StringName& p_type) const;

+ 1 - 1
tools/editor/property_editor.cpp

@@ -595,7 +595,7 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty
 			color_picker->show();
 			color_picker->set_edit_alpha(hint!=PROPERTY_HINT_COLOR_NO_ALPHA);
 			color_picker->set_color(v);
-			set_size( Size2(350, color_picker->get_combined_minimum_size().height+10));
+			set_size( Size2(300, color_picker->get_combined_minimum_size().height+10));
 			/*
 			int ofs=80;
 			int m=10;

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff