summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/particles_2d.cpp168
-rw-r--r--scene/2d/particles_2d.h15
-rw-r--r--scene/gui/color_ramp_edit.cpp368
-rw-r--r--scene/gui/color_ramp_edit.h52
-rw-r--r--scene/register_scene_types.cpp2
-rw-r--r--scene/resources/color_ramp.cpp111
-rw-r--r--scene/resources/color_ramp.h52
-rw-r--r--scene/resources/default_theme/checker_bg.pngbin0 -> 180 bytes
-rw-r--r--scene/resources/default_theme/theme_data.h5
9 files changed, 709 insertions, 64 deletions
diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp
index 39d747c436..6effd4f31d 100644
--- a/scene/2d/particles_2d.cpp
+++ b/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;
diff --git a/scene/2d/particles_2d.h b/scene/2d/particles_2d.h
index 90b5a188a6..4ee0fcf8da 100644
--- a/scene/2d/particles_2d.h
+++ b/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;
diff --git a/scene/gui/color_ramp_edit.cpp b/scene/gui/color_ramp_edit.cpp
new file mode 100644
index 0000000000..382c0dc103
--- /dev/null
+++ b/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"));
+}
diff --git a/scene/gui/color_ramp_edit.h b/scene/gui/color_ramp_edit.h
new file mode 100644
index 0000000000..91292eed0d
--- /dev/null
+++ b/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_ */
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 687410d192..d3446ca62d 100644
--- a/scene/register_scene_types.cpp
+++ b/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
diff --git a/scene/resources/color_ramp.cpp b/scene/resources/color_ramp.cpp
new file mode 100644
index 0000000000..ef32ccb6a7
--- /dev/null
+++ b/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();
+}
diff --git a/scene/resources/color_ramp.h b/scene/resources/color_ramp.h
new file mode 100644
index 0000000000..e2f1ac5ed4
--- /dev/null
+++ b/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_ */
diff --git a/scene/resources/default_theme/checker_bg.png b/scene/resources/default_theme/checker_bg.png
new file mode 100644
index 0000000000..0674f9da26
--- /dev/null
+++ b/scene/resources/default_theme/checker_bg.png
Binary files differ
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index 78e210239d..8bd0a66271 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -49,6 +49,11 @@ static const unsigned char checked_png[]={
};
+static const unsigned char checker_bg_png[]={
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b,0xe,0x1b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xd,0x1c,0x1b,0x52,0x41,0x72,0xa4,0x0,0x0,0x0,0x24,0x49,0x44,0x41,0x54,0x28,0x53,0x63,0xfc,0xf,0x4,0xc,0x48,0xa0,0xa1,0xa1,0x1,0xca,0x82,0x0,0x26,0x28,0x8d,0x13,0x50,0xae,0x80,0xb1,0xbe,0xbe,0x7e,0x60,0xdd,0xc0,0xc0,0x0,0x0,0x78,0x11,0x9,0x87,0x2b,0xa,0xe1,0x69,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
static const unsigned char close_png[]={
0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x73,0x0,0x29,0x0,0x7c,0x29,0x1e,0x61,0x18,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x19,0x1,0x14,0x3,0xf4,0x10,0x33,0xed,0x0,0x0,0x1,0x53,0x49,0x44,0x41,0x54,0x38,0xcb,0xcd,0x92,0xbd,0x4e,0x5b,0x41,0x10,0x85,0xbf,0xd9,0x9d,0xfd,0xb9,0xd7,0xb2,0xb9,0x81,0x8e,0x26,0xf4,0x69,0x53,0x50,0x44,0xa2,0x74,0x3,0xd,0xd,0x48,0x48,0xf4,0x3c,0x16,0x8f,0xc1,0x23,0xf0,0x0,0xf4,0x8e,0x90,0x11,0x96,0x25,0xa2,0x10,0x45,0x4a,0x9c,0x6b,0x4f,0xa,0xf6,0x4a,0xe6,0xc6,0x4e,0xb,0x47,0x5a,0xed,0xee,0x9c,0xd9,0xd1,0x99,0xb3,0x3,0x6f,0xd,0xd9,0x70,0xd7,0x72,0xfe,0xd3,0xe3,0x42,0xd9,0x5b,0xc0,0xba,0xa0,0xef,0x3d,0xfe,0xe0,0x9c,0x3b,0x35,0xb3,0x21,0xf0,0x1d,0xf8,0x5d,0xe2,0xd,0xf0,0xd9,0x39,0xf7,0xc5,0xcc,0xee,0x81,0x5f,0x9b,0xd4,0x4,0xe7,0xdc,0x65,0xd3,0x34,0x3f,0x53,0x4a,0x73,0xe0,0x18,0xd8,0x2b,0xeb,0x78,0x38,0x1c,0x3e,0xe5,0x9c,0x7f,0x38,0xe7,0x2e,0xd7,0xd4,0xfc,0x23,0xf1,0x30,0xc6,0x38,0x4b,0x29,0x59,0x8,0xe1,0x1e,0xb8,0x0,0x2e,0xea,0xba,0x7e,0xa8,0xaa,0xca,0x42,0x8,0x33,0xe0,0x70,0x5b,0x1,0x80,0x1d,0x60,0xac,0xaa,0x93,0x9c,0xb3,0xa9,0xea,0x63,0x8c,0x71,0x36,0x18,0xc,0x4c,0x55,0x27,0xc0,0xb8,0xe4,0xfc,0xd7,0xd4,0x5d,0xe0,0x5c,0x55,0xa7,0x39,0x67,0xcb,0x39,0x9b,0xf7,0x7e,0xa,0x9c,0x17,0xee,0x95,0xf1,0xba,0xa5,0x90,0x17,0x11,0x6f,0xf6,0x62,0xb6,0x88,0xb8,0x9e,0xe1,0x5b,0xd1,0x0,0x27,0x75,0x5d,0x3f,0x14,0xd9,0xd3,0x4e,0x49,0xf1,0xe4,0xa4,0xe4,0x6c,0x44,0x10,0x91,0xa3,0xd1,0x68,0xf4,0x54,0x55,0x55,0xd7,0xf3,0x19,0x70,0xa6,0xaa,0x93,0x94,0x92,0xc5,0x18,0xe7,0x22,0x72,0xb4,0x6e,0xe2,0xab,0x16,0xbc,0xf7,0x7,0x8b,0xc5,0x42,0x97,0xcb,0xe5,0xbc,0x6d,0xdb,0x2b,0xe0,0x16,0xa0,0x6d,0xdb,0x67,0xe7,0xdc,0xb5,0x88,0x24,0x11,0xd9,0xef,0x5a,0xeb,0x4f,0x62,0x37,0x48,0xe3,0xd5,0x6a,0xf5,0x15,0xb8,0x3,0x9e,0xb,0x37,0x2,0x3e,0x89,0xc8,0x47,0x33,0xbb,0x1,0xbe,0xad,0x4f,0x63,0xff,0x17,0xc2,0x16,0x73,0xb5,0x70,0xc2,0xbb,0xc2,0x5f,0x47,0xa5,0x56,0x8a,0x30,0xdd,0x7d,0xae,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};