Explorar o código

Replace color phases with color ramp for Particles2D.

Biliogadafr %!s(int64=10) %!d(string=hai) anos
pai
achega
df9d48d9b5

+ 109 - 59
scene/2d/particles_2d.cpp

@@ -503,19 +503,6 @@ void Particles2D::_notification(int p_what) {
 			if (!local_space)
 				invxform=get_global_transform().affine_inverse();
 
-			int col_count=0;
-			float last=-1;
-			ColorPhase cphase[MAX_COLOR_PHASES];
-
-			for(int i=0;i<color_phase_count;i++) {
-
-				if (color_phases[i].pos<=last)
-					break;
-				cphase[i]=color_phases[i];
-				col_count++;
-			}
-
-
 			int start_particle = (int)(time * (float)particle_count / lifetime);
 			
 			for (int id=0;id<particle_count;++id) {
@@ -537,32 +524,42 @@ void Particles2D::_notification(int p_what) {
 
 				uint32_t rand_seed=p.seed*(i+1);
 
+				Color color;
 
-				int cpos=0;
+				if(color_ramp.is_valid())
+				{
+					Vector<ColorRamp::Point>& color_points = color_ramp->get_points();
 
-				while(cpos<col_count) {
+					int cpos=0;
 
-					if (cphase[cpos].pos > ptime)
-						break;
-					cpos++;
-				}
+					while(cpos<color_points.size()) {
 
-				cpos--;
+						if (color_points[cpos].offset > ptime)
+							break;
+						cpos++;
+					}
 
-				Color color;
-				//could be faster..
-				if (cpos==-1)
-					color=Color(1,1,1,1);
-				else {
-					if (cpos==col_count-1)
-						color=cphase[cpos].color;
-					else {
-						float diff = (cphase[cpos+1].pos-cphase[cpos].pos);
-						if (diff>0)
-							color=cphase[cpos].color.linear_interpolate(cphase[cpos+1].color, (ptime - cphase[cpos].pos) / diff );
+					cpos--;
+					//could be faster..
+					if (cpos==-1)
+						if(color_points.size())
+							color=color_points[0].color;//Extend color to the beginning
 						else
-							color=cphase[cpos+1].color;
+							color=Color(1,1,1,1);//If no points just use white.
+					else {
+						if (cpos==color_points.size()-1)
+							color=color_points[cpos].color;
+						else {
+							float diff = (color_points[cpos+1].offset-color_points[cpos].offset);
+							if (diff>0)
+								color=color_points[cpos].color.linear_interpolate(color_points[cpos+1].color, (ptime - color_points[cpos].offset) / diff );
+							else
+								color=color_points[cpos+1].color;
+						}
 					}
+				} else
+				{
+					color = default_color;
 				}
 
 
@@ -813,6 +810,27 @@ Ref<Texture> Particles2D::get_texture() const {
 	return texture;
 }
 
+void Particles2D::set_color(const Color& p_color) {
+
+	default_color = p_color;
+}
+
+Color Particles2D::get_color() const {
+
+	return default_color;
+}
+
+
+void Particles2D::set_color_ramp(const Ref<ColorRamp>& p_color_ramp) {
+
+	color_ramp=p_color_ramp;
+}
+
+Ref<ColorRamp> Particles2D::get_color_ramp() const {
+
+	return color_ramp;
+}
+
 void Particles2D::set_emissor_offset(const Point2& p_offset) {
 
 	emissor_offset=p_offset;
@@ -834,40 +852,76 @@ bool Particles2D::is_using_local_space() const {
 	return local_space;
 }
 
-
+//Deprecated. Converts color phases to color ramp
 void Particles2D::set_color_phases(int p_phases) {
 
-	ERR_FAIL_INDEX(p_phases,MAX_COLOR_PHASES+1);
-	color_phase_count=p_phases;
+	//Create color ramp if we have 2 or more phases.
+	//Otherwise first phase phase will be assigned to default color.
+	if(p_phases > 1 && color_ramp.is_null())
+	{
+		color_ramp = Ref<ColorRamp>(memnew (ColorRamp()));
+	}
+	if(color_ramp.is_valid())
+	{
+		color_ramp->get_points().resize(p_phases);
+	}
 }
 
+//Deprecated.
 int Particles2D::get_color_phases() const {
 
-	return color_phase_count;
+	if(color_ramp.is_valid())
+	{
+		return color_ramp->get_points_count();
+	}
+	return 0;
 }
 
+//Deprecated. Converts color phases to color ramp
 void Particles2D::set_color_phase_color(int p_phase,const Color& p_color) {
 
 	ERR_FAIL_INDEX(p_phase,MAX_COLOR_PHASES);
-	color_phases[p_phase].color=p_color;
-
+	if(color_ramp.is_valid())
+	{
+		if(color_ramp->get_points_count() > p_phase)
+			color_ramp->set_color(p_phase, p_color);
+	} else
+	{
+		if(p_phase == 0)
+			default_color = p_color;
+	}
 }
+
+//Deprecated.
 Color Particles2D::get_color_phase_color(int p_phase) const {
 
 	ERR_FAIL_INDEX_V(p_phase,MAX_COLOR_PHASES,Color());
-	return color_phases[p_phase].color;
+	if(color_ramp.is_valid())
+	{
+		return color_ramp->get_color(p_phase);
+	}
+	return Color(0,0,0,1);
 }
 
+//Deprecated. Converts color phases to color ramp
 void Particles2D::set_color_phase_pos(int p_phase,float p_pos) {
 	ERR_FAIL_INDEX(p_phase,MAX_COLOR_PHASES);
 	ERR_FAIL_COND(p_pos<0.0 || p_pos>1.0);
-	color_phases[p_phase].pos=p_pos;
-
+	if(color_ramp.is_valid() && color_ramp->get_points_count() > p_phase)
+	{
+		return color_ramp->set_offset(p_phase, p_pos);
+	}
 }
+
+//Deprecated.
 float Particles2D::get_color_phase_pos(int p_phase) const {
 
 	ERR_FAIL_INDEX_V(p_phase,MAX_COLOR_PHASES,0);
-	return color_phases[p_phase].pos;
+	if(color_ramp.is_valid())
+	{
+		return color_ramp->get_offset(p_phase);
+	}
+	return 0;
 }
 
 void Particles2D::set_emission_half_extents(const Vector2& p_extents) {
@@ -997,6 +1051,12 @@ void Particles2D::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_texture:Texture","texture"),&Particles2D::set_texture);
 	ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&Particles2D::get_texture);
 
+	ObjectTypeDB::bind_method(_MD("set_color","color"),&Particles2D::set_color);
+	ObjectTypeDB::bind_method(_MD("get_color"),&Particles2D::get_color);
+
+	ObjectTypeDB::bind_method(_MD("set_color_ramp:ColorRamp","color_ramp"),&Particles2D::set_color_ramp);
+	ObjectTypeDB::bind_method(_MD("get_color_ramp:ColorRamp"),&Particles2D::get_color_ramp);
+
 	ObjectTypeDB::bind_method(_MD("set_emissor_offset","offset"),&Particles2D::set_emissor_offset);
 	ObjectTypeDB::bind_method(_MD("get_emissor_offset"),&Particles2D::get_emissor_offset);
 
@@ -1055,7 +1115,6 @@ void Particles2D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"config/v_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_v_frames"),_SCS("get_v_frames"));
 
 
-
 	for(int i=0;i<PARAM_MAX;i++) {
 		ADD_PROPERTYI(PropertyInfo(Variant::REAL,_particlesframe_property_names[i],PROPERTY_HINT_RANGE,_particlesframe_property_ranges[i]),_SCS("set_param"),_SCS("get_param"),i);
 	}
@@ -1064,14 +1123,17 @@ void Particles2D::_bind_methods() {
 		ADD_PROPERTYI(PropertyInfo(Variant::REAL,_particlesframe_property_rnames[i],PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_randomness"),_SCS("get_randomness"),i);
 	}
 
-	ADD_PROPERTY( PropertyInfo( Variant::INT, "color_phases/count",PROPERTY_HINT_RANGE,"0,4,1"), _SCS("set_color_phases"), _SCS("get_color_phases"));
+	ADD_PROPERTY( PropertyInfo( Variant::INT, "color_phases/count",PROPERTY_HINT_RANGE,"0,4,1", 0), _SCS("set_color_phases"), _SCS("get_color_phases"));
 
+	//Backward compatibility. They will be converted to color ramp
 	for(int i=0;i<MAX_COLOR_PHASES;i++) {
 		String phase="phase_"+itos(i)+"/";
-		ADD_PROPERTYI( PropertyInfo( Variant::REAL, phase+"pos", PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_color_phase_pos"),_SCS("get_color_phase_pos"),i );
-		ADD_PROPERTYI( PropertyInfo( Variant::COLOR, phase+"color"),_SCS("set_color_phase_color"),_SCS("get_color_phase_color"),i );
+		ADD_PROPERTYI( PropertyInfo( Variant::REAL, phase+"pos", PROPERTY_HINT_RANGE,"0,1,0.01", 0),_SCS("set_color_phase_pos"),_SCS("get_color_phase_pos"),i );
+		ADD_PROPERTYI( PropertyInfo( Variant::COLOR, phase+"color", PROPERTY_HINT_NONE, "", 0),_SCS("set_color_phase_color"),_SCS("get_color_phase_color"),i );
 	}
 
+	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color/color"),_SCS("set_color"),_SCS("get_color"));
+	ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"color/color_ramp",PROPERTY_HINT_RESOURCE_TYPE,"ColorRamp"),_SCS("set_color_ramp"),_SCS("get_color_ramp"));
 
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2_ARRAY,"emission_points",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_emission_points"),_SCS("get_emission_points"));
 
@@ -1097,8 +1159,6 @@ void Particles2D::_bind_methods() {
 
 }
 
-
-
 Particles2D::Particles2D() {
 
 	for(int i=0;i<PARAM_MAX;i++) {
@@ -1118,6 +1178,7 @@ Particles2D::Particles2D() {
 	set_param(PARAM_FINAL_SIZE,1.0);
 	set_param(PARAM_ANIM_SPEED_SCALE,1.0);
 
+	set_color(Color(1,1,1,1));
 
 	time=0;
 	lifetime=2;
@@ -1129,17 +1190,6 @@ Particles2D::Particles2D() {
 	preprocess=0;
 	time_scale=1.0;
 
-	color_phase_count=1;
-
-	set_color_phase_pos(0,0.0);
-	set_color_phase_pos(1,1.0);
-	set_color_phase_pos(2,1.0);
-	set_color_phase_pos(3,1.0);
-
-	set_color_phase_color(0,Color(1,1,1));
-	set_color_phase_color(1,Color(0,0,0));
-	set_color_phase_color(2,Color(0,0,0));
-	set_color_phase_color(3,Color(0,0,0));
 
 	flip_h=false;
 	flip_v=false;

+ 10 - 5
scene/2d/particles_2d.h

@@ -31,6 +31,7 @@
 
 #include "scene/2d/node_2d.h"
 #include "scene/resources/texture.h"
+#include "scene/resources/color_ramp.h"
 
 class Particles2D;
 class ParticleAttractor2D : public Node2D {
@@ -125,11 +126,6 @@ private:
 	};
 
 	Vector<Particle> particles;
-	int color_phase_count;
-	struct ColorPhase {
-		Color color;
-		float pos;
-	} color_phases[MAX_COLOR_PHASES];
 
 	struct AttractorCache {
 
@@ -161,6 +157,9 @@ private:
 
 	Ref<Texture> texture;
 
+	//If no color ramp is set then default color is used. Created as simple alternative to color_ramp.
+	Color default_color;
+	Ref<ColorRamp> color_ramp;
 
 	void testee(int a, int b, int c, int d, int e);
 	void _process_particles(float p_delta);
@@ -230,6 +229,12 @@ public:
 	void set_texture(const Ref<Texture>& p_texture);
 	Ref<Texture> get_texture() const;
 
+	void set_color(const Color& p_color);
+	Color get_color() const;
+
+	void set_color_ramp(const Ref<ColorRamp>& p_texture);
+	Ref<ColorRamp> get_color_ramp() const;
+
 	void set_emissor_offset(const Point2& p_offset);
 	Point2 get_emissor_offset() const;
 

+ 368 - 0
scene/gui/color_ramp_edit.cpp

@@ -0,0 +1,368 @@
+#include "color_ramp_edit.h"
+#include "os/keyboard.h"
+
+ColorRampEdit::ColorRampEdit(){
+	grabbed=-1;
+	grabbing=false;
+	set_focus_mode(FOCUS_ALL);
+
+	popup = memnew( PopupPanel );
+	picker = memnew( ColorPicker );
+	popup->add_child(picker);
+	popup->set_child_rect(picker);
+	add_child(popup);
+
+	checker = Ref<ImageTexture>(memnew( ImageTexture ));
+	checker->create_from_image( Image(checker_bg_png),ImageTexture::FLAG_REPEAT );
+}
+
+int ColorRampEdit::_get_point_from_pos(int x) {
+	int result = -1;
+	int total_w = get_size().width-get_size().height-3;
+	for(int i=0;i<points.size();i++) {
+		//Check if we clicked at point
+		if (ABS(x-points[i].offset*total_w+1)<(POINT_WIDTH/2+1)) {
+			result=i;
+		}
+	}
+	return result;
+}
+
+void ColorRampEdit::_show_color_picker() {
+	if (grabbed==-1)
+		return;
+	Size2 ms = Size2(350, picker->get_combined_minimum_size().height+10);
+	picker->set_color(points[grabbed].color);
+	popup->set_pos(get_global_pos()-Vector2(ms.width-get_size().width,ms.height));
+	popup->set_size(ms);
+	popup->popup();
+}
+
+ColorRampEdit::~ColorRampEdit() {
+
+}
+
+void ColorRampEdit::_input_event(const InputEvent& p_event) {
+
+	if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) {
+
+		points.remove(grabbed);
+		grabbed=-1;
+		update();
+		emit_signal("ramp_changed");
+		accept_event();
+	}
+
+	//Show color picker on double click.
+	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 &&  p_event.mouse_button.doubleclick && p_event.mouse_button.pressed) {
+		grabbed=_get_point_from_pos(p_event.mouse_button.x);
+		_show_color_picker();
+		accept_event();
+	}
+
+	//Delete point on right click
+	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==2 && p_event.mouse_button.pressed) {
+		grabbed=_get_point_from_pos(p_event.mouse_button.x);
+		if(grabbed != -1)
+		{
+			points.remove(grabbed);
+			grabbed=-1;
+			update();
+			emit_signal("ramp_changed");
+			accept_event();
+		}
+	}
+
+	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
+
+		update();
+		int x = p_event.mouse_button.x;
+		int total_w = get_size().width-get_size().height-3;
+
+		//Check if color selector was clicked.
+		if (x>total_w+3) {
+			_show_color_picker();
+			return;
+		}
+
+		grabbing=true;
+
+		grabbed=_get_point_from_pos(x);
+		//grab or select
+		if (grabbed!=-1) {
+			return;
+		}
+
+		//insert
+		ColorRamp::Point newPoint;
+		newPoint.offset=CLAMP(x/float(total_w),0,1);
+
+		ColorRamp::Point prev;
+		ColorRamp::Point next;
+
+		int pos=-1;
+		for(int i=0;i<points.size();i++) {
+			if (points[i].offset<newPoint.offset)
+				pos=i;
+		}
+
+		if (pos==-1) {
+
+			prev.color=Color(0,0,0);
+			prev.offset=0;
+			if (points.size()) {
+				next=points[0];
+			} else {
+				next.color=Color(1,1,1);
+				next.offset=1.0;
+			}
+		} else  {
+
+			if (pos==points.size()-1) {
+				next.color=Color(1,1,1);
+				next.offset=1.0;
+			} else {
+				next=points[pos+1];
+			}
+			prev=points[pos];
+
+		}
+
+		newPoint.color=prev.color.linear_interpolate(next.color,(newPoint.offset-prev.offset)/(next.offset-prev.offset));
+
+		points.push_back(newPoint);
+		points.sort();
+		for(int i=0;i<points.size();i++) {
+			if (points[i].offset==newPoint.offset) {
+				grabbed=i;
+				break;
+			}
+		}
+
+		emit_signal("ramp_changed");
+
+	}
+
+	if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) {
+
+		if (grabbing) {
+			grabbing=false;
+			emit_signal("ramp_changed");
+		}
+		update();
+	}
+
+	if (p_event.type==InputEvent::MOUSE_MOTION && grabbing) {
+
+		int total_w = get_size().width-get_size().height-3;
+
+		int x = p_event.mouse_motion.x;
+		float newofs = CLAMP(x/float(total_w),0,1);
+
+		bool valid=true;
+		for(int i=0;i<points.size();i++) {
+
+			if (points[i].offset==newofs && i!=grabbed) {
+				valid=false;
+			}
+		}
+
+		if (!valid)
+			return;
+
+		points[grabbed].offset=newofs;
+
+		points.sort();
+		for(int i=0;i<points.size();i++) {
+			if (points[i].offset==newofs) {
+				grabbed=i;
+				break;
+			}
+		}
+
+		emit_signal("ramp_changed");
+
+		update();
+	}
+}
+
+void ColorRampEdit::_notification(int p_what) {
+
+	if (p_what==NOTIFICATION_ENTER_TREE) {
+		picker->connect("color_changed",this,"_color_changed");
+	}
+	if (p_what==NOTIFICATION_DRAW) {
+
+		int w = get_size().x;
+		int h = get_size().y;
+
+		if (w == 0 || h == 0)
+			return; //Safety check. We have division by 'h'. And in any case there is nothing to draw with such size
+
+		int total_w = get_size().width-get_size().height-3;
+
+		//Draw checker pattern for ramp
+		_draw_checker(0,0, total_w, h);
+
+		//Draw color ramp
+		ColorRamp::Point prev;
+		prev.offset=0;
+		if(points.size() == 0)
+			prev.color=Color(0,0,0); //Draw black rectangle if we have no points
+		else
+			prev.color = points[0].color;  //Extend color of first point to the beginning.
+
+		for(int i=-1;i<points.size();i++) {
+
+			ColorRamp::Point next;
+			//If there is no next point
+			if (i+1 == points.size()) {
+				if(points.size() == 0)
+					next.color=Color(0,0,0); //Draw black rectangle if we have no points
+				else
+					next.color=points[i].color; //Extend color of last point to the end.
+				next.offset=1;
+			} else {
+				next=points[i+1];
+			}
+
+			if (prev.offset==next.offset) {
+				prev=next;
+				continue;
+			}
+
+			Vector<Vector2> points;
+			Vector<Color> colors;
+			points.push_back(Vector2(prev.offset*total_w,h));
+			points.push_back(Vector2(prev.offset*total_w,0));
+			points.push_back(Vector2(next.offset*total_w,0));
+			points.push_back(Vector2(next.offset*total_w,h));
+			colors.push_back(prev.color);
+			colors.push_back(prev.color);
+			colors.push_back(next.color);
+			colors.push_back(next.color);
+			draw_primitive(points,colors,Vector<Point2>());
+			prev=next;
+		}
+
+		//Draw point markers
+		for(int i=0;i<points.size();i++) {
+
+			Color col = i==grabbed?Color(1,0.0,0.0,0.9):points[i].color.contrasted();
+			col.a = 0.9;
+
+			draw_line(Vector2(points[i].offset*total_w,0),Vector2(points[i].offset*total_w,h/2),col);
+			draw_rect(Rect2(points[i].offset*total_w-POINT_WIDTH/2, h/2, POINT_WIDTH, h/2), Color(0.6, 0.6, 0.6, i==grabbed?0.9:0.4));
+			draw_line(Vector2(points[i].offset*total_w-POINT_WIDTH/2,h/2),Vector2(points[i].offset*total_w-POINT_WIDTH/2,h-1),col);
+			draw_line(Vector2(points[i].offset*total_w+POINT_WIDTH/2,h/2),Vector2(points[i].offset*total_w+POINT_WIDTH/2,h-1),col);
+			draw_line(Vector2(points[i].offset*total_w-POINT_WIDTH/2,h/2),Vector2(points[i].offset*total_w+POINT_WIDTH/2,h/2),col);
+			draw_line(Vector2(points[i].offset*total_w-POINT_WIDTH/2,h-1),Vector2(points[i].offset*total_w+POINT_WIDTH/2,h-1),col);
+
+		}
+
+
+		//Draw "button" for color selector
+		_draw_checker(total_w+3,0, h, h);
+		if (grabbed!=-1) {
+			//Draw with selection color
+			draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color);
+		} else {
+			//if no color selected draw grey color with 'X' on top.
+			draw_rect(Rect2(total_w+3,0,h,h), Color(0.5, 0.5, 0.5, 1));
+			draw_line(Vector2(total_w+3,0),Vector2(total_w+3+h,h),Color(1,1,1,0.6));
+			draw_line(Vector2(total_w+3,h),Vector2(total_w+3+h,0),Color(1,1,1,0.6));
+		}
+
+		//Draw borders around color ramp if in focus
+		if (has_focus()) {
+
+			draw_line(Vector2(-1,-1),Vector2(total_w+1,-1),Color(1,1,1,0.6));
+			draw_line(Vector2(total_w+1,-1),Vector2(total_w+1,h+1),Color(1,1,1,0.6));
+			draw_line(Vector2(total_w+1,h+1),Vector2(-1,h+1),Color(1,1,1,0.6));
+			draw_line(Vector2(-1,-1),Vector2(-1,h+1),Color(1,1,1,0.6));
+		}
+
+	}
+}
+
+void ColorRampEdit::_draw_checker(int x, int y, int w, int h) {
+	//Draw it with polygon to insert UVs for scale
+	Vector<Vector2> backPoints;
+	backPoints.push_back(Vector2(x, y));
+	backPoints.push_back(Vector2(x, y+h));
+	backPoints.push_back(Vector2(x+w, y+h));
+	backPoints.push_back(Vector2(x+w, y));
+	Vector<Color> colorPoints;
+	colorPoints.push_back(Color(1, 1, 1, 1));
+	colorPoints.push_back(Color(1, 1, 1, 1));
+	colorPoints.push_back(Color(1, 1, 1, 1));
+	colorPoints.push_back(Color(1, 1, 1, 1));
+	Vector<Vector2> uvPoints;
+	//Draw checker pattern pixel-perfect and scale it by 2.
+	uvPoints.push_back(Vector2(x, y));
+	uvPoints.push_back(Vector2(x, y+h*.5f/checker->get_height()));
+	uvPoints.push_back(Vector2(x+w*.5f/checker->get_width(), y+h*.5f/checker->get_height()));
+	uvPoints.push_back(Vector2(x+w*.5f/checker->get_width(), y));
+	draw_polygon(backPoints, colorPoints, uvPoints, checker);
+}
+
+Size2 ColorRampEdit::get_minimum_size() const {
+
+	return Vector2(0,16);
+}
+
+void ColorRampEdit::_color_changed(const Color& p_color) {
+
+	if (grabbed==-1)
+		return;
+	points[grabbed].color=p_color;
+	update();
+	emit_signal("ramp_changed");
+
+}
+
+void ColorRampEdit::set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors) {
+
+	ERR_FAIL_COND(p_offsets.size()!=p_colors.size());
+	points.clear();
+	for(int i=0;i<p_offsets.size();i++) {
+		ColorRamp::Point p;
+		p.offset=p_offsets[i];
+		p.color=p_colors[i];
+		points.push_back(p);
+	}
+
+	points.sort();
+	update();
+}
+
+Vector<float> ColorRampEdit::get_offsets() const {
+	Vector<float> ret;
+	for(int i=0;i<points.size();i++)
+		ret.push_back(points[i].offset);
+	return ret;
+}
+
+Vector<Color> ColorRampEdit::get_colors() const {
+	Vector<Color> ret;
+	for(int i=0;i<points.size();i++)
+		ret.push_back(points[i].color);
+	return ret;
+}
+
+void ColorRampEdit::set_points(Vector<ColorRamp::Point>& p_points) {
+	if(points.size() != p_points.size())
+		grabbed = -1;
+	points.clear();
+	points = p_points;
+}
+
+Vector<ColorRamp::Point>& ColorRampEdit::get_points() {
+	return points;
+}
+
+void ColorRampEdit::_bind_methods() {
+	ObjectTypeDB::bind_method(_MD("_input_event"),&ColorRampEdit::_input_event);
+	ObjectTypeDB::bind_method(_MD("_color_changed"),&ColorRampEdit::_color_changed);
+	ADD_SIGNAL(MethodInfo("ramp_changed"));
+}

+ 52 - 0
scene/gui/color_ramp_edit.h

@@ -0,0 +1,52 @@
+#ifndef SCENE_GUI_COLOR_RAMP_EDIT_H_
+#define SCENE_GUI_COLOR_RAMP_EDIT_H_
+
+#include "scene/gui/popup.h"
+#include "scene/gui/color_picker.h"
+#include "scene/resources/color_ramp.h"
+#include "scene/resources/default_theme/theme_data.h"
+
+#define POINT_WIDTH 8
+
+class ColorRampEdit : public Control {
+
+	OBJ_TYPE(ColorRampEdit,Control);
+
+	PopupPanel *popup;
+	ColorPicker *picker;
+
+	Ref<ImageTexture> checker;
+
+	bool grabbing;
+	int grabbed;
+	Vector<ColorRamp::Point> points;
+
+	void _draw_checker(int x, int y, int w, int h);
+	void _color_changed(const Color& p_color);
+	int _get_point_from_pos(int x);
+	void _show_color_picker();
+
+protected:
+	void _input_event(const InputEvent& p_event);
+	void _notification(int p_what);
+	static void _bind_methods();
+
+public:
+	void set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors);
+	Vector<float> get_offsets() const;
+	Vector<Color> get_colors() const;
+	void set_points(Vector<ColorRamp::Point>& p_points);
+	Vector<ColorRamp::Point>& get_points();
+	virtual Size2 get_minimum_size() const;
+
+	ColorRampEdit();
+	virtual ~ColorRampEdit();
+};
+
+/*class  ColorRampEditPanel : public Panel
+{
+	OBJ_TYPE(ColorRampEditPanel, Panel );
+};*/
+
+
+#endif /* SCENE_GUI_COLOR_RAMP_EDIT_H_ */

+ 2 - 0
scene/register_scene_types.cpp

@@ -170,6 +170,7 @@
 #include "scene/resources/audio_stream.h"
 #include "scene/resources/gibberish_stream.h"
 #include "scene/resources/bit_mask.h"
+#include "scene/resources/color_ramp.h"
 #include "scene/scene_string_names.h"
 
 
@@ -565,6 +566,7 @@ void register_scene_types() {
 
 	ObjectTypeDB::register_type<PolygonPathFinder>();
 	ObjectTypeDB::register_type<BitMap>();
+	ObjectTypeDB::register_type<ColorRamp>();
 
 	OS::get_singleton()->yield(); //may take time to init
 

+ 111 - 0
scene/resources/color_ramp.cpp

@@ -0,0 +1,111 @@
+/*
+ * color_ramp.h
+ */
+
+#include "color_ramp.h"
+
+//setter and getter names for property serialization
+#define COLOR_RAMP_GET_OFFSETS "get_offsets"
+#define COLOR_RAMP_GET_COLORS "get_colors"
+#define COLOR_RAMP_SET_OFFSETS "set_offsets"
+#define COLOR_RAMP_SET_COLORS "set_colors"
+
+ColorRamp::ColorRamp() {
+	//Set initial color ramp transition from black to white
+	points.resize(2);
+	points[0].color = Color(0,0,0,1);
+	points[0].offset = 0;
+	points[1].color = Color(1,1,1,1);
+	points[1].offset = 1;
+}
+
+ColorRamp::~ColorRamp() {
+
+}
+
+void ColorRamp::_bind_methods() {
+
+	//ObjectTypeDB::bind_method(_MD("set_offset", "pos", "offset"),&ColorRamp::set_offset);
+	//ObjectTypeDB::bind_method(_MD(COLOR_RAMP_GET_OFFSETS),&ColorRamp::get_offset);
+
+	ObjectTypeDB::bind_method(_MD(COLOR_RAMP_SET_OFFSETS,"offsets"),&ColorRamp::set_offsets);
+	ObjectTypeDB::bind_method(_MD(COLOR_RAMP_GET_OFFSETS),&ColorRamp::get_offsets);
+
+	ObjectTypeDB::bind_method(_MD(COLOR_RAMP_SET_COLORS,"colors"),&ColorRamp::set_colors);
+	ObjectTypeDB::bind_method(_MD(COLOR_RAMP_GET_COLORS),&ColorRamp::get_colors);
+
+	ADD_PROPERTY( PropertyInfo(Variant::REAL,"offsets"),_SCS(COLOR_RAMP_SET_OFFSETS),_SCS(COLOR_RAMP_GET_OFFSETS) );
+	ADD_PROPERTY( PropertyInfo(Variant::REAL,"colors"),_SCS(COLOR_RAMP_SET_COLORS),_SCS(COLOR_RAMP_GET_COLORS) );
+}
+
+Vector<float> ColorRamp::get_offsets() const {
+	Vector<float> offsets;
+	offsets.resize(points.size());
+	for(int i = 0; i < points.size(); i++)
+	{
+		offsets[i] = points[i].offset;
+	}
+	return offsets;
+}
+
+Vector<Color> ColorRamp::get_colors() const {
+	Vector<Color> colors;
+	colors.resize(points.size());
+	for(int i = 0; i < points.size(); i++)
+	{
+		colors[i] = points[i].color;
+	}
+	return colors;
+}
+
+void ColorRamp::set_offsets(const Vector<float>& offsets) {
+	points.resize(offsets.size());
+	for(int i = 0; i < points.size(); i++)
+	{
+		points[i].offset = offsets[i];
+	}
+}
+
+void ColorRamp::set_colors(const Vector<Color>& colors) {
+	points.resize(colors.size());
+	for(int i = 0; i < points.size(); i++)
+	{
+		points[i].color = colors[i];
+	}
+}
+
+Vector<ColorRamp::Point>& ColorRamp::get_points() {
+	return points;
+}
+
+void ColorRamp::set_points(Vector<ColorRamp::Point>& p_points) {
+	points = p_points;
+}
+
+void ColorRamp::set_offset(int pos, const float offset) {
+	if(points.size() <= pos)
+		points.resize(pos + 1);
+	points[pos].offset = offset;
+}
+
+float ColorRamp::get_offset(int pos) const {
+	if(points.size() > pos)
+		return points[pos].offset;
+	return 0;  //TODO: Maybe throw some error instead?
+}
+
+void ColorRamp::set_color(int pos, const Color& color) {
+	if(points.size() <= pos)
+		points.resize(pos + 1);
+	points[pos].color = color;
+}
+
+Color ColorRamp::get_color(int pos) const {
+	if(points.size() > pos)
+		return points[pos].color;
+	return Color(0,0,0,1); //TODO: Maybe throw some error instead?
+}
+
+int ColorRamp::get_points_count() const {
+	return points.size();
+}

+ 52 - 0
scene/resources/color_ramp.h

@@ -0,0 +1,52 @@
+/*
+ * color_ramp.h
+ */
+
+#ifndef SCENE_RESOURCES_COLOR_RAMP_H_
+#define SCENE_RESOURCES_COLOR_RAMP_H_
+
+#include "resource.h"
+
+class ColorRamp: public Resource {
+	OBJ_TYPE( ColorRamp, Resource );
+	OBJ_SAVE_TYPE( ColorRamp );
+
+public:
+	struct Point {
+
+		float offset;
+		Color color;
+		bool operator<(const Point& p_ponit) const {
+			return offset<p_ponit.offset;
+		}
+	};
+
+private:
+	Vector<Point> points;
+
+protected:
+	static void _bind_methods();
+
+public:
+	ColorRamp();
+	virtual ~ColorRamp();
+
+	void set_points(Vector<Point>& points);
+	Vector<Point>& get_points();
+
+	void set_offset(int pos, const float offset);
+	float get_offset(int pos) const;
+
+	void set_color(int pos, const Color& color);
+	Color get_color(int pos) const;
+
+	void set_offsets(const Vector<float>& offsets);
+	Vector<float> get_offsets() const;
+
+	void set_colors(const Vector<Color>& colors);
+	Vector<Color> get_colors() const;
+
+	int get_points_count() const;
+};
+
+#endif /* SCENE_RESOURCES_COLOR_RAMP_H_ */

BIN=BIN
scene/resources/default_theme/checker_bg.png


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 5 - 0
scene/resources/default_theme/theme_data.h


+ 2 - 0
tools/editor/editor_node.cpp

@@ -91,6 +91,7 @@
 #include "plugins/polygon_2d_editor_plugin.h"
 #include "plugins/navigation_polygon_editor_plugin.h"
 #include "plugins/light_occluder_2d_editor_plugin.h"
+#include "plugins/color_ramp_editor_plugin.h"
 // end
 #include "tools/editor/io_plugins/editor_texture_import_plugin.h"
 #include "tools/editor/io_plugins/editor_scene_import_plugin.h"
@@ -4157,6 +4158,7 @@ EditorNode::EditorNode() {
 	add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) );
 	add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) );
 	add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) );
+	add_editor_plugin( memnew( ColorRampEditorPlugin(this) ) );
 
 	for(int i=0;i<EditorPlugins::get_plugin_count();i++)
 		add_editor_plugin( EditorPlugins::create(i,this) );

BIN=BIN
tools/editor/icons/icon_color_ramp.png


+ 83 - 0
tools/editor/plugins/color_ramp_editor_plugin.cpp

@@ -0,0 +1,83 @@
+/*
+ * color_ramp_editor_plugin.cpp
+ */
+
+#include "color_ramp_editor_plugin.h"
+
+ColorRampEditorPlugin::ColorRampEditorPlugin(EditorNode *p_node) {
+
+	editor=p_node;
+	ramp_editor = memnew( ColorRampEdit );
+
+	add_custom_control(CONTAINER_CANVAS_EDITOR_BOTTOM,ramp_editor);
+	//add_custom_control(CONTAINER_SPATIAL_EDITOR_BOTTOM,ramp_editor);
+	ramp_editor->set_custom_minimum_size(Size2(100, 48));
+	ramp_editor->hide();
+	ramp_editor->connect("ramp_changed", this, "ramp_changed");
+}
+
+void ColorRampEditorPlugin::edit(Object *p_object) {
+
+	ColorRamp* color_ramp = p_object->cast_to<ColorRamp>();
+	if (!color_ramp)
+		return;
+	color_ramp_ref = Ref<ColorRamp>(color_ramp);
+	ramp_editor->set_points(color_ramp_ref->get_points());
+}
+
+bool ColorRampEditorPlugin::handles(Object *p_object) const {
+
+	return p_object->is_type("ColorRamp");
+}
+
+void ColorRampEditorPlugin::make_visible(bool p_visible) {
+
+	if (p_visible) {
+		ramp_editor->show();
+	} else {
+		ramp_editor->hide();
+	}
+
+}
+
+void ColorRampEditorPlugin::_ramp_changed() {
+
+	if(color_ramp_ref.is_valid())
+	{
+
+		UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+
+		//Not sure if I should convert this data to DVector
+		Vector<float> new_offsets=ramp_editor->get_offsets();
+		Vector<Color> new_colors=ramp_editor->get_colors();
+		Vector<float> old_offsets=color_ramp_ref->get_offsets();
+		Vector<Color> old_colors=color_ramp_ref->get_colors();
+
+		if (old_offsets.size()!=new_offsets.size())
+			ur->create_action("Add/Remove Color Ramp Point");
+		else
+			ur->create_action("Modify Color Ramp",true);
+		ur->add_do_method(this,"undo_redo_color_ramp",new_offsets,new_colors);
+		ur->add_undo_method(this,"undo_redo_color_ramp",old_offsets,old_colors);
+		ur->commit_action();
+
+		//color_ramp_ref->set_points(ramp_editor->get_points());
+	}
+}
+
+void ColorRampEditorPlugin::_undo_redo_color_ramp(const Vector<float>& offsets,
+		const Vector<Color>& colors) {
+
+	color_ramp_ref->set_offsets(offsets);
+	color_ramp_ref->set_colors(colors);
+	ramp_editor->set_points(color_ramp_ref->get_points());
+	ramp_editor->update();
+}
+
+ColorRampEditorPlugin::~ColorRampEditorPlugin(){
+}
+
+void ColorRampEditorPlugin::_bind_methods() {
+	ObjectTypeDB::bind_method(_MD("ramp_changed"),&ColorRampEditorPlugin::_ramp_changed);
+	ObjectTypeDB::bind_method(_MD("undo_redo_color_ramp","offsets","colors"),&ColorRampEditorPlugin::_undo_redo_color_ramp);
+}

+ 37 - 0
tools/editor/plugins/color_ramp_editor_plugin.h

@@ -0,0 +1,37 @@
+/*
+ * color_ramp_editor_plugin.h
+ */
+
+#ifndef TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_
+#define TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_
+
+#include "tools/editor/editor_plugin.h"
+#include "tools/editor/editor_node.h"
+#include "scene/gui/color_ramp_edit.h"
+
+class ColorRampEditorPlugin : public EditorPlugin {
+
+	OBJ_TYPE( ColorRampEditorPlugin, EditorPlugin );
+
+	Ref<ColorRamp> color_ramp_ref;
+	ColorRampEdit *ramp_editor;
+	EditorNode *editor;
+
+protected:
+	static void _bind_methods();
+	void _ramp_changed();
+	void _undo_redo_color_ramp(const Vector<float>& offsets, const Vector<Color>& colors);
+
+public:
+	virtual String get_name() const { return "ColorRamp"; }
+	bool has_main_screen() const { return false; }
+	virtual void edit(Object *p_node);
+	virtual bool handles(Object *p_node) const;
+	virtual void make_visible(bool p_visible);
+
+	ColorRampEditorPlugin(EditorNode *p_node);
+	~ColorRampEditorPlugin();
+
+};
+
+#endif /* TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ */

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio