Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polyline #7352

Merged
merged 1 commit into from Feb 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
307 changes: 307 additions & 0 deletions scene/2d/line_2d.cpp
@@ -0,0 +1,307 @@
#include "line_2d.h"
#include "core_string_names.h"


// Needed so we can bind functions
VARIANT_ENUM_CAST(LineJointMode)
VARIANT_ENUM_CAST(LineCapMode)
VARIANT_ENUM_CAST(LineTextureMode)


Line2D::Line2D() : Node2D() {
_joint_mode = LINE_JOINT_SHARP;
_begin_cap_mode = LINE_CAP_NONE;
_end_cap_mode = LINE_CAP_NONE;
_width = 10;
_default_color = Color(0.4,0.5,1);
_sharp_limit = 2.f;
_round_precision = 8;
}

void Line2D::set_points(const PoolVector<Vector2> &p_points) {
_points = p_points;
update();
}

void Line2D::set_width(float width) {
if(width < 0.0)
width = 0.0;
_width = width;
update();
}

float Line2D::get_width() const {
return _width;
}

PoolVector<Vector2> Line2D::get_points() const {
return _points;
}

void Line2D::set_point_pos(int i, Vector2 pos) {
_points.set(i, pos);
update();
}

Vector2 Line2D::get_point_pos(int i) const {
return _points.get(i);
}

int Line2D::get_point_count() const {
return _points.size();
}

void Line2D::add_point(Vector2 pos) {
_points.append(pos);
update();
}

void Line2D::remove_point(int i) {
_points.remove(i);
update();
}

void Line2D::set_default_color(Color color) {
_default_color = color;
update();
}

Color Line2D::get_default_color() const {
return _default_color;
}

void Line2D::set_gradient(const Ref<ColorRamp>& gradient) {

// Cleanup previous connection if any
if(_gradient.is_valid()) {
(**_gradient).disconnect(CoreStringNames::get_singleton()->changed, this, "_gradient_changed");
}

_gradient = gradient;

// Connect to the gradient so the line will update when the ColorRamp is changed
if(_gradient.is_valid()) {
(**_gradient).connect(CoreStringNames::get_singleton()->changed, this, "_gradient_changed");
}

update();
}

Ref<ColorRamp> Line2D::get_gradient() const {
return _gradient;
}

void Line2D::set_texture(const Ref<Texture>& texture) {
_texture = texture;
update();
}

Ref<Texture> Line2D::get_texture() const {
return _texture;
}

void Line2D::set_texture_mode(const LineTextureMode mode) {
_texture_mode = mode;
update();
}

LineTextureMode Line2D::get_texture_mode() const {
return _texture_mode;
}

void Line2D::set_joint_mode(LineJointMode mode) {
_joint_mode = mode;
update();
}

LineJointMode Line2D::get_joint_mode() const {
return _joint_mode;
}

void Line2D::set_begin_cap_mode(LineCapMode mode) {
_begin_cap_mode = mode;
update();
}

LineCapMode Line2D::get_begin_cap_mode() const {
return _begin_cap_mode;
}

void Line2D::set_end_cap_mode(LineCapMode mode) {
_end_cap_mode = mode;
update();
}

LineCapMode Line2D::get_end_cap_mode() const {
return _end_cap_mode;
}

void Line2D::_notification(int p_what) {
switch(p_what) {
case NOTIFICATION_DRAW:
_draw();
break;
}
}

void Line2D::set_sharp_limit(float limit) {
if(limit < 0.f)
limit = 0.f;
_sharp_limit = limit;
update();
}

float Line2D::get_sharp_limit() const {
return _sharp_limit;
}

void Line2D::set_round_precision(int precision) {
if(precision < 1)
precision = 1;
_round_precision = precision;
update();
}

int Line2D::get_round_precision() const {
return _round_precision;
}

void Line2D::_draw() {
if(_points.size() <= 1 || _width == 0.f)
return;

// TODO Is this really needed?
// Copy points for faster access
Vector<Vector2> points;
points.resize(_points.size());
int len = points.size(); {
PoolVector<Vector2>::Read points_read = _points.read();
for(int i = 0; i < len; ++i) {
points[i] = points_read[i];
}
}

// TODO Maybe have it as member rather than copying parameters and allocating memory?
LineBuilder lb;
lb.points = points;
lb.default_color = _default_color;
lb.gradient = *_gradient;
lb.texture_mode = _texture_mode;
lb.joint_mode = _joint_mode;
lb.begin_cap_mode = _begin_cap_mode;
lb.end_cap_mode = _end_cap_mode;
lb.round_precision = _round_precision;
lb.sharp_limit = _sharp_limit;
lb.width = _width;

lb.build();

RID texture_rid;
if(_texture.is_valid())
texture_rid = (**_texture).get_rid();

VS::get_singleton()->canvas_item_add_triangle_array(
get_canvas_item(),
lb.indices,
lb.vertices,
lb.colors,
lb.uvs,
texture_rid);

// DEBUG
// Draw wireframe
// if(lb.indices.size() % 3 == 0) {
// Color col(0,0,0);
// for(int i = 0; i < lb.indices.size(); i += 3) {
// int vi = lb.indices[i];
// int lbvsize = lb.vertices.size();
// Vector2 a = lb.vertices[lb.indices[i]];
// Vector2 b = lb.vertices[lb.indices[i+1]];
// Vector2 c = lb.vertices[lb.indices[i+2]];
// draw_line(a, b, col);
// draw_line(b, c, col);
// draw_line(c, a, col);
// }
// for(int i = 0; i < lb.vertices.size(); ++i) {
// Vector2 p = lb.vertices[i];
// draw_rect(Rect2(p.x-1, p.y-1, 2, 2), Color(0,0,0,0.5));
// }
// }
}

void Line2D::_gradient_changed() {
update();
}

// static
void Line2D::_bind_methods() {

ClassDB::bind_method(_MD("set_points","points"), &Line2D::set_points);
ClassDB::bind_method(_MD("get_points"), &Line2D::get_points);

ClassDB::bind_method(_MD("set_point_pos","i", "pos"), &Line2D::set_point_pos);
ClassDB::bind_method(_MD("get_point_pos", "i"), &Line2D::get_point_pos);

ClassDB::bind_method(_MD("get_point_count"), &Line2D::get_point_count);

ClassDB::bind_method(_MD("add_point", "pos"), &Line2D::add_point);
ClassDB::bind_method(_MD("remove_point", "i"), &Line2D::remove_point);

ClassDB::bind_method(_MD("set_width","width"), &Line2D::set_width);
ClassDB::bind_method(_MD("get_width"), &Line2D::get_width);

ClassDB::bind_method(_MD("set_default_color", "color"), &Line2D::set_default_color);
ClassDB::bind_method(_MD("get_default_color"), &Line2D::get_default_color);

ClassDB::bind_method(_MD("set_gradient", "color"), &Line2D::set_gradient);
ClassDB::bind_method(_MD("get_gradient"), &Line2D::get_gradient);

ClassDB::bind_method(_MD("set_texture", "texture"), &Line2D::set_texture);
ClassDB::bind_method(_MD("get_texture"), &Line2D::get_texture);

ClassDB::bind_method(_MD("set_texture_mode", "mode"), &Line2D::set_texture_mode);
ClassDB::bind_method(_MD("get_texture_mode"), &Line2D::get_texture_mode);

ClassDB::bind_method(_MD("set_joint_mode", "mode"), &Line2D::set_joint_mode);
ClassDB::bind_method(_MD("get_joint_mode"), &Line2D::get_joint_mode);

ClassDB::bind_method(_MD("set_begin_cap_mode", "mode"), &Line2D::set_begin_cap_mode);
ClassDB::bind_method(_MD("get_begin_cap_mode"), &Line2D::get_begin_cap_mode);

ClassDB::bind_method(_MD("set_end_cap_mode", "mode"), &Line2D::set_end_cap_mode);
ClassDB::bind_method(_MD("get_end_cap_mode"), &Line2D::get_end_cap_mode);

ClassDB::bind_method(_MD("set_sharp_limit", "limit"), &Line2D::set_sharp_limit);
ClassDB::bind_method(_MD("get_sharp_limit"), &Line2D::get_sharp_limit);

ClassDB::bind_method(_MD("set_round_precision", "precision"), &Line2D::set_round_precision);
ClassDB::bind_method(_MD("get_round_precision"), &Line2D::get_round_precision);

ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "points"), _SCS("set_points"), _SCS("get_points"));
ADD_PROPERTY(PropertyInfo(Variant::REAL, "width"), _SCS("set_width"), _SCS("get_width"));
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "default_color"), _SCS("set_default_color"), _SCS("get_default_color"));
ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "ColorRamp"), _SCS("set_gradient"), _SCS("get_gradient" ) );
ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"), _SCS("get_texture" ) );
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "texture_mode", PROPERTY_HINT_ENUM, "None,Tile" ), _SCS("set_texture_mode"),_SCS("get_texture_mode" ) );
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "joint_mode", PROPERTY_HINT_ENUM, "Sharp,Bevel,Round" ), _SCS("set_joint_mode"),_SCS("get_joint_mode" ) );
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "begin_cap_mode", PROPERTY_HINT_ENUM, "None,Box,Round" ), _SCS("set_begin_cap_mode"),_SCS("get_begin_cap_mode" ) );
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "end_cap_mode", PROPERTY_HINT_ENUM, "None,Box,Round" ), _SCS("set_end_cap_mode"),_SCS("get_end_cap_mode" ) );
ADD_PROPERTY(PropertyInfo(Variant::REAL, "sharp_limit"), _SCS("set_sharp_limit"), _SCS("get_sharp_limit"));
ADD_PROPERTY(PropertyInfo(Variant::INT, "round_precision"), _SCS("set_round_precision"), _SCS("get_round_precision"));

BIND_CONSTANT(LINE_JOINT_SHARP);
BIND_CONSTANT(LINE_JOINT_BEVEL);
BIND_CONSTANT(LINE_JOINT_ROUND);

BIND_CONSTANT(LINE_CAP_NONE);
BIND_CONSTANT(LINE_CAP_BOX);
BIND_CONSTANT(LINE_CAP_ROUND);

BIND_CONSTANT(LINE_TEXTURE_NONE);
BIND_CONSTANT(LINE_TEXTURE_TILE);

ClassDB::bind_method(_MD("_gradient_changed"), &Line2D::_gradient_changed);

}


80 changes: 80 additions & 0 deletions scene/2d/line_2d.h
@@ -0,0 +1,80 @@
#ifndef LINE2D_H
#define LINE2D_H

#include "node_2d.h"
#include "line_builder.h"


class Line2D : public Node2D {

GDCLASS(Line2D, Node2D)

public:
Line2D();

void set_points(const PoolVector<Vector2> & p_points);
PoolVector<Vector2> get_points() const;

void set_point_pos(int i, Vector2 pos);
Vector2 get_point_pos(int i) const;

int get_point_count() const;

void add_point(Vector2 pos);
void remove_point(int i);

void set_width(float width);
float get_width() const;

void set_default_color(Color color);
Color get_default_color() const;

void set_gradient(const Ref<ColorRamp>& gradient);
Ref<ColorRamp> get_gradient() const;

void set_texture(const Ref<Texture>& texture);
Ref<Texture> get_texture() const;

void set_texture_mode(const LineTextureMode mode);
LineTextureMode get_texture_mode() const;

void set_joint_mode(LineJointMode mode);
LineJointMode get_joint_mode() const;

void set_begin_cap_mode(LineCapMode mode);
LineCapMode get_begin_cap_mode() const;

void set_end_cap_mode(LineCapMode mode);
LineCapMode get_end_cap_mode() const;

void set_sharp_limit(float limit);
float get_sharp_limit() const;

void set_round_precision(int precision);
int get_round_precision() const;

protected:
void _notification(int p_what);
void _draw();

static void _bind_methods();

private:
void _gradient_changed();

private:
PoolVector<Vector2> _points;
LineJointMode _joint_mode;
LineCapMode _begin_cap_mode;
LineCapMode _end_cap_mode;
float _width;
Color _default_color;
Ref<ColorRamp> _gradient;
Ref<Texture> _texture;
LineTextureMode _texture_mode;
float _sharp_limit;
int _round_precision;

};

#endif // LINE2D_H