Created
July 22, 2013 20:13
-
-
Save eXpl0it3r/6057215 to your computer and use it in GitHub Desktop.
Stroke - A dirty port to SFML 2.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SFML/Graphics.hpp> | |
#include "Stroke.hpp" | |
int main() | |
{ | |
sf::RenderWindow window(sf::VideoMode(800, 600), "Stroke"); | |
window.setFramerateLimit(60); | |
Stroke my_stroke; | |
my_stroke.SetJointLinearSpeed(0, -20); | |
int i = 0; | |
sf::Clock clock; | |
while(window.isOpen()) | |
{ | |
float dt = clock.restart().asSeconds(); | |
sf::Event event; | |
while(window.pollEvent(event)) | |
{ | |
if(event.type == sf::Event::Closed) | |
window.close(); | |
} | |
my_stroke.AddJoint(400, 300); | |
my_stroke.Calculate(dt); | |
window.clear(); | |
window.draw(my_stroke); | |
window.display(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////////////// | |
// Headers | |
//////////////////////////////////////////////////////////// | |
#include "Stroke.hpp" | |
#include <SFML/OpenGL.hpp> | |
const float myRand(float low, float high) | |
{ | |
return static_cast<float>(std::rand()) / RAND_MAX * (high - low) + low; | |
} | |
// Constructeur | |
//////////////////////////////////////////////////////////// | |
Stroke::Joint::Joint() : | |
birth_time(0), | |
thickness_scale(1), | |
angle(0), | |
thickness(0) | |
{ | |
} | |
//////////////////////////////////////////////////////////// | |
Stroke::Stroke() : | |
time(0), | |
max_joints(0), | |
max_length(0), | |
min_segment_length(0), | |
joint_lifetime(0), | |
thickness(3), | |
random_thickness(1, 1), | |
start_thickness(1), | |
end_thickness(1), | |
stroke_offset(0), | |
start_sweep(0), | |
end_sweep(0), | |
start_sweep_style(Soft), | |
end_sweep_style(Soft), | |
stippling(0), | |
shaking(0), | |
loop(false), | |
draw_mode(Solid), | |
start_inner_color(sf::Color::White), | |
start_outer_color(sf::Color::White), | |
end_inner_color(sf::Color::White), | |
end_outer_color(sf::Color::White), | |
sub_rect(0,0,1,1), | |
symetric(true), | |
texture_offset(0), | |
texture_pan(1), | |
is_length_compiled(false), | |
length(0), | |
is_bounding_box_compiled(false), | |
is_compiled(false) | |
{ | |
} | |
// Accesseurs | |
//////////////////////////////////////////////////////////// | |
const sf::Vector2f & Stroke::GetJointLinearSpeed() const | |
{ | |
return joint_linear_speed; | |
} | |
//////////////////////////////////////////////////////////// | |
unsigned int Stroke::GetMaxJoints() const | |
{ | |
return max_joints; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetMaxLength() const | |
{ | |
return max_length; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetMinSegmentLength() const | |
{ | |
return min_segment_length; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetJointLifetime() const | |
{ | |
return joint_lifetime; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetThickness() const | |
{ | |
return thickness; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetMaxRandomThickness() const | |
{ | |
return random_thickness.y; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetMinRandomThickness() const | |
{ | |
return random_thickness.x; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetStartThickness() const | |
{ | |
return start_thickness; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetEndThickness() const | |
{ | |
return end_thickness; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetOffset() const | |
{ | |
return stroke_offset; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetStartSweep() const | |
{ | |
return start_sweep; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetEndSweep() const | |
{ | |
return end_sweep; | |
} | |
//////////////////////////////////////////////////////////// | |
Stroke::SweepStyle Stroke::GetStartSweepStyle() const | |
{ | |
return start_sweep_style; | |
} | |
//////////////////////////////////////////////////////////// | |
Stroke::SweepStyle Stroke::GetEndSweepStyle() const | |
{ | |
return end_sweep_style; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetStippling() const | |
{ | |
return stippling; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetShaking() const | |
{ | |
return shaking; | |
} | |
//////////////////////////////////////////////////////////// | |
const sf::Color & Stroke::GetStartInnerColor() const | |
{ | |
return start_inner_color; | |
} | |
//////////////////////////////////////////////////////////// | |
const sf::Color & Stroke::GetStartOuterColor() const | |
{ | |
return start_outer_color; | |
} | |
//////////////////////////////////////////////////////////// | |
const sf::Color & Stroke::GetEndInnerColor() const | |
{ | |
return end_inner_color; | |
} | |
//////////////////////////////////////////////////////////// | |
const sf::Color & Stroke::GetEndOuterColor() const | |
{ | |
return end_outer_color; | |
} | |
//////////////////////////////////////////////////////////// | |
const sf::Texture & Stroke::GetTexture() const | |
{ | |
return texture; | |
} | |
//////////////////////////////////////////////////////////// | |
const sf::IntRect & Stroke::GetSubRect() const | |
{ | |
return sub_rect; | |
} | |
//////////////////////////////////////////////////////////// | |
bool Stroke::IsSymetric() const | |
{ | |
return symetric; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetTextureOffset() const | |
{ | |
return texture_offset; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetTexturePan() const | |
{ | |
return texture_pan; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::GetLength() | |
{ | |
if(!is_length_compiled) | |
CompileLength(); | |
return length; | |
} | |
//////////////////////////////////////////////////////////// | |
const sf::FloatRect & Stroke::GetBoundingBox() | |
{ | |
if(!is_bounding_box_compiled) | |
CompileBoundingBox(); | |
return bounding_box; | |
} | |
//////////////////////////////////////////////////////////// | |
bool Stroke::IsDrawable() const | |
{ | |
if(joints.size() < 2 || thickness == 0.f || stippling == 1.f) | |
return false; | |
return true; | |
} | |
// Modificateurs de l'objet | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetJointLinearSpeed(float x, float y) | |
{ | |
SetJointLinearSpeed(sf::Vector2f(x, y)); | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetJointLinearSpeed(const sf::Vector2f & joint_linear_speed) | |
{ | |
this->joint_linear_speed = joint_linear_speed; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetMaxJoints(unsigned int max_joints) | |
{ | |
this->max_joints = max_joints; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetMaxLength(float max_length) | |
{ | |
this->max_length = max_length; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetMinSegmentLength(float min_segment_length) | |
{ | |
this->min_segment_length = min_segment_length; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetJointLifetime(float joint_lifetime) | |
{ | |
this->joint_lifetime = joint_lifetime; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetThickness(float thickness) | |
{ | |
this->thickness = thickness; | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetRandomThickness(float min, float max) | |
{ | |
random_thickness.x = min; | |
random_thickness.y = max; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetStartThickness(float start_thickness) | |
{ | |
this->start_thickness = ToRange(start_thickness); | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetEndThickness(float end_thickness) | |
{ | |
this->end_thickness = ToRange(end_thickness); | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetOffset(float stroke_offset) | |
{ | |
this->stroke_offset = ToRange(stroke_offset, -1.f); | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetSweep(float sweep) | |
{ | |
SetStartSweep(sweep); | |
SetEndSweep(sweep); | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetStartSweep(float start_sweep) | |
{ | |
this->start_sweep = ToRange(start_sweep); | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetEndSweep(float end_sweep) | |
{ | |
this->end_sweep = ToRange(end_sweep); | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetSweepStyle(Stroke::SweepStyle sweep_style) | |
{ | |
this->start_sweep_style = sweep_style; | |
this->end_sweep_style = sweep_style; | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetStartSweepStyle(Stroke::SweepStyle start_sweep_style) | |
{ | |
this->start_sweep_style = start_sweep_style; | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetEndSweepStyle(Stroke::SweepStyle end_sweep_style) | |
{ | |
this->end_sweep_style = end_sweep_style; | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetStippling(float stippling) | |
{ | |
this->stippling = ToRange(stippling); | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetShaking(float shaking) | |
{ | |
this->shaking = shaking; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetLoop(bool loop) | |
{ | |
this->loop = loop; | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetDrawMode(Stroke::DrawMode draw_mode) | |
{ | |
this->draw_mode = draw_mode; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetInnerColor(const sf::Color & inner_color) | |
{ | |
this->start_inner_color = inner_color; | |
this->end_inner_color = inner_color; | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetOuterColor(const sf::Color & outer_color) | |
{ | |
this->start_outer_color = outer_color; | |
this->end_outer_color = outer_color; | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetStartInnerColor(const sf::Color & start_inner_color) | |
{ | |
this->start_inner_color = start_inner_color; | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetStartOuterColor(const sf::Color & start_outer_color) | |
{ | |
this->start_outer_color = start_outer_color; | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetEndInnerColor(const sf::Color & end_inner_color) | |
{ | |
this->end_inner_color = end_inner_color; | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetEndOuterColor(const sf::Color & end_outer_color) | |
{ | |
this->end_outer_color = end_outer_color; | |
is_compiled = false; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetTexture(const sf::Texture & texture, bool adjust_to_new_size) | |
{ | |
if(adjust_to_new_size && (texture.getSize().x > 0) && (texture.getSize().y > 0)) | |
SetSubRect(sf::IntRect(0, 0, texture.getSize().x, texture.getSize().y)); | |
this->texture = texture; | |
draw_mode = Textured; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetSubRect(const sf::IntRect & sub_rect) | |
{ | |
this->sub_rect = sub_rect; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetSymetric(bool symetric) | |
{ | |
this->symetric = symetric; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetTextureOffset(float texture_offset) | |
{ | |
this->texture_offset = texture_offset; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::MoveTexture(float texture_offset) | |
{ | |
this->texture_offset += texture_offset; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::SetTexturePan(float texture_pan) | |
{ | |
if(texture_pan < 1) | |
this->texture_pan = 1; | |
this->texture_pan = texture_pan; | |
} | |
//////////////////////////////////////////////////////////// | |
bool Stroke::AddJoint(float x, float y, bool precompile) | |
{ | |
return AddJoint(sf::Vector2f(x, y), precompile); | |
} | |
//////////////////////////////////////////////////////////// | |
bool Stroke::AddJoint(const sf::Vector2f & position, bool precompile) | |
{ | |
Joint joint; | |
joint.position = position; | |
joint.birth_time = time; | |
joint.thickness_scale = myRand(random_thickness.x, random_thickness.y); | |
if(joints.empty()) | |
{ | |
joints.push_back(joint); | |
is_length_compiled = false; | |
return true; | |
} | |
bool joint_added = false; | |
// Adding joints | |
if(min_segment_length) | |
{ | |
float angle = Angle(joints[joints.size()-1].position, position); | |
sf::Vector2f last_point_position = joints[joints.size()-1].position; | |
int i = 0; | |
while(Distance(joints[joints.size()-1].position, position) >= min_segment_length) | |
{ | |
joint.position = last_point_position + ToVector(angle, (i + 1) * min_segment_length); | |
joint.thickness_scale = myRand(random_thickness.x, random_thickness.y); | |
joints.push_back(joint); | |
is_compiled = false; | |
is_length_compiled = false; | |
joint_added = true; | |
++i; | |
} | |
} | |
else | |
{ | |
if(joints[joints.size()-1].position != position) | |
{ | |
joints.push_back(joint); | |
is_compiled = false; | |
is_length_compiled = false; | |
joint_added = true; | |
} | |
} | |
if(precompile && joints.size() >= 3) | |
Compile(); | |
return joint_added; | |
} | |
//////////////////////////////////////////////////////////// | |
bool Stroke::AddJoint(float x, float y, float thickness_scale, bool precompile) | |
{ | |
return AddJoint(sf::Vector2f(x, y), thickness_scale, precompile); | |
} | |
//////////////////////////////////////////////////////////// | |
bool Stroke::AddJoint(const sf::Vector2f & position, float thickness_scale, bool precompile) | |
{ | |
Joint joint; | |
joint.position = position; | |
joint.birth_time = time; | |
joint.thickness_scale = thickness_scale; | |
if(joints.empty()) | |
{ | |
joints.push_back(joint); | |
is_length_compiled = false; | |
return true; | |
} | |
bool joint_added = false; | |
// Adding joints | |
if(min_segment_length) | |
{ | |
float angle = Angle(joints[joints.size()-1].position, position); | |
sf::Vector2f last_point_position = joints[joints.size()-1].position; | |
int i = 0; | |
while(Distance(joints[joints.size()-1].position, position) >= min_segment_length) | |
{ | |
joint.position = last_point_position + ToVector(angle, (i + 1) * min_segment_length); | |
joints.push_back(joint); | |
is_compiled = false; | |
is_length_compiled = false; | |
joint_added = true; | |
++i; | |
} | |
} | |
else | |
{ | |
if(joints[joints.size()-1].position != position) | |
{ | |
joints.push_back(joint); | |
is_compiled = false; | |
is_length_compiled = false; | |
joint_added = true; | |
} | |
} | |
if(precompile) | |
Compile(); | |
return joint_added; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::Clear() | |
{ | |
joints.clear(); | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::Calculate(float time_interval) | |
{ | |
// Deleting unwanted points | |
if(!joints.empty()) | |
/* Removing if | |
- max joint counter is reached | |
- max length is reached | |
- points life is passed*/ | |
while((joints.size() > max_joints && max_joints) || (GetLength() > max_length && max_length) || (time - joints[0].birth_time > joint_lifetime && joint_lifetime > 0)) | |
{ | |
joints.pop_front(); | |
is_compiled = false; | |
is_length_compiled = false; | |
if(joints.empty()) | |
break; | |
} | |
// Moving lefting points | |
if(joint_linear_speed != sf::Vector2f(0.f, 0.f)) | |
{ | |
for(unsigned int i = 0; i < joints.size(); i++) | |
{ | |
joints[i].position += joint_linear_speed * time_interval; | |
joints[i].upper_point += joint_linear_speed * time_interval; | |
joints[i].lower_point += joint_linear_speed * time_interval; | |
} | |
} | |
time += time_interval; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::draw(sf::RenderTarget& target, sf::RenderStates states) const | |
{ | |
if(!is_compiled) | |
if(!const_cast<Stroke*>(this)->Compile()) | |
return; | |
if(shaking) | |
const_cast<Stroke*>(this)->ComputeOffset(); | |
switch(draw_mode) | |
{ | |
case Solid: | |
DrawSolid(target, states); | |
return; | |
case Textured: | |
DrawTexture(target, states); | |
return; | |
case Monochrome: | |
DrawMonochrome(target, states); | |
return; | |
case WireFrame: | |
DrawWireframe(target, states); | |
return; | |
default: | |
DrawMonochrome(target, states); | |
return; | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::DrawSolid(sf::RenderTarget& target, sf::RenderStates states) const | |
{ | |
states.texture = nullptr; | |
for(unsigned int i = 1; i < joints.size(); i++) | |
DrawSolidBloc(target, states, i, i-1); | |
if(loop) | |
DrawSolidBloc(target, states, 0, joints.size()-1); | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::DrawSolidBloc(sf::RenderTarget& target, sf::RenderStates states, unsigned int current_joint, unsigned int previous_joint) const | |
{ | |
sf::Vector2f center_previous = ((stippling)? joints[previous_joint].position * (1.f - stippling/2.f) + joints[current_joint].position * (stippling/2.f) : joints[previous_joint].position) + joints[previous_joint].offset; | |
sf::Vector2f center_next = ((stippling)? joints[current_joint].position * (1.f - stippling/2.f) + joints[previous_joint].position * (stippling/2.f) : joints[current_joint].position) + joints[current_joint].offset; | |
sf::Vector2f upper_previous = ((stippling)? joints[previous_joint].upper_point * (1.f - stippling/2.f) + joints[current_joint].upper_point * (stippling/2.f) : joints[previous_joint].upper_point) + joints[previous_joint].offset; | |
sf::Vector2f upper_next = ((stippling)? joints[current_joint].upper_point * (1.f - stippling/2.f) + joints[previous_joint].upper_point * (stippling/2.f) : joints[current_joint].upper_point) + joints[current_joint].offset; | |
sf::Vector2f lower_previous = ((stippling)? joints[previous_joint].lower_point * (1.f - stippling/2.f) + joints[current_joint].lower_point * (stippling/2.f) : joints[previous_joint].lower_point) + joints[previous_joint].offset; | |
sf::Vector2f lower_next = ((stippling)? joints[current_joint].lower_point * (1.f - stippling/2.f) + joints[previous_joint].lower_point * (stippling/2.f) : joints[current_joint].lower_point) + joints[current_joint].offset; | |
// First Side | |
sf::VertexArray first(sf::TrianglesStrip, 4); | |
first[0].position = center_previous; | |
first[0].color = joints[previous_joint].inner_color; | |
first[1].position = center_next; | |
first[1].color = joints[current_joint].inner_color; | |
first[2].position = upper_previous; | |
first[2].color = joints[previous_joint].outer_color; | |
first[3].position = upper_next; | |
first[3].color = joints[current_joint].outer_color; | |
// Second Side | |
sf::VertexArray second(sf::TrianglesStrip, 4); | |
second[0].position = center_previous; | |
second[0].color = joints[previous_joint].inner_color; | |
second[1].position = center_next; | |
second[1].color = joints[current_joint].inner_color; | |
second[2].position = lower_previous; | |
second[2].color = joints[previous_joint].outer_color; | |
second[3].position = lower_next; | |
second[3].color = joints[current_joint].outer_color; | |
target.draw(first, states); | |
target.draw(second, states); | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::DrawTexture(sf::RenderTarget& target, sf::RenderStates states) const | |
{ | |
if(texture.getSize().x > 0) | |
{ | |
const sf::FloatRect coords(sub_rect.left / texture.getSize().x, sub_rect.top / texture.getSize().y, | |
sub_rect.width / texture.getSize().x, sub_rect.height / texture.getSize().y); | |
states.texture = &texture; | |
// We repeat the texture to ensure no gap will appear between two blocs | |
if(texture.isSmooth()) | |
{ | |
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); | |
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); | |
} | |
float offset = std::fmod(texture_offset, 1.f); | |
if(offset < 0.f) | |
offset += 1.f; | |
float previous_accumulator = offset; | |
float offset_accumulator = offset; | |
bool is_integer = (texture_pan == (int)texture_pan); | |
for(unsigned int i = 1; i < joints.size(); i++) | |
{ | |
sf::Vector2f center_previous = ((stippling)? joints[i-1].position * (1.f - stippling/2.f) + joints[i].position * (stippling/2.f) : joints[i-1].position) + joints[i-1].offset; | |
sf::Vector2f center_next = ((stippling)? joints[i].position * (1.f - stippling/2.f) + joints[i-1].position * (stippling/2.f) : joints[i].position) + joints[i].offset; | |
sf::Vector2f upper_previous = ((stippling)? joints[i-1].upper_point * (1.f - stippling/2.f) + joints[i].upper_point * (stippling/2.f) : joints[i-1].upper_point) + joints[i-1].offset; | |
sf::Vector2f upper_next = ((stippling)? joints[i].upper_point * (1.f - stippling/2.f) + joints[i-1].upper_point * (stippling/2.f) : joints[i].upper_point) + joints[i].offset; | |
sf::Vector2f lower_previous = ((stippling)? joints[i-1].lower_point * (1.f - stippling/2.f) + joints[i].lower_point * (stippling/2.f) : joints[i-1].lower_point) + joints[i-1].offset; | |
sf::Vector2f lower_next = ((stippling)? joints[i].lower_point * (1.f - stippling/2.f) + joints[i-1].lower_point * (stippling/2.f) : joints[i].lower_point) + joints[i].offset; | |
previous_accumulator = offset_accumulator; | |
offset_accumulator += 1/texture_pan; | |
float alpha = (1.f - previous_accumulator) / (offset_accumulator - previous_accumulator); | |
// Testing if the bloc is split by the texture | |
if(offset_accumulator > 1.f) | |
{ | |
sf::Vector2f lower_separator = lower_next * alpha + lower_previous * (1.f - alpha); | |
sf::Vector2f center_separator = center_next * alpha + center_previous * (1.f - alpha); | |
sf::Vector2f upper_separator = upper_next * alpha + upper_previous * (1.f - alpha); | |
sf::FloatRect left_bloc_coords = coords; | |
left_bloc_coords.width = coords.width / texture_pan * alpha; | |
left_bloc_coords.left += coords.width * previous_accumulator; | |
sf::FloatRect right_bloc_coords = coords; | |
right_bloc_coords.width = coords.width / texture_pan * (1.f - alpha); | |
// Splitting | |
// First part | |
DrawTexturedBloc(target, states, upper_previous, upper_separator, center_previous, center_separator, lower_previous, lower_separator, left_bloc_coords); | |
// Second part | |
DrawTexturedBloc(target, states, upper_separator, upper_next, center_separator, center_next, lower_separator, lower_next, right_bloc_coords); | |
offset_accumulator -= 1.f; | |
} | |
else | |
{ | |
sf::FloatRect bloc_coords = coords; | |
bloc_coords.width = coords.width / texture_pan; | |
if(previous_accumulator >= 1.f) | |
bloc_coords.left += coords.width * (previous_accumulator - 1.f); | |
else | |
bloc_coords.left += coords.width * previous_accumulator; | |
// Normal rendering | |
DrawTexturedBloc(target, states, upper_previous, upper_next, center_previous, center_next, lower_previous, lower_next, bloc_coords); | |
} | |
} | |
if(loop) | |
{ | |
unsigned int current_joint = 0; | |
unsigned int previous_joint = joints.size()-1; | |
sf::Vector2f center_previous = ((stippling)? joints[previous_joint].position * (1.f - stippling/2.f) + joints[current_joint].position * (stippling/2.f) : joints[previous_joint].position) + joints[previous_joint].offset; | |
sf::Vector2f center_next = ((stippling)? joints[current_joint].position * (1.f - stippling/2.f) + joints[previous_joint].position * (stippling/2.f) : joints[current_joint].position) + joints[current_joint].offset; | |
sf::Vector2f upper_previous = ((stippling)? joints[previous_joint].upper_point * (1.f - stippling/2.f) + joints[current_joint].upper_point * (stippling/2.f) : joints[previous_joint].upper_point) + joints[previous_joint].offset; | |
sf::Vector2f upper_next = ((stippling)? joints[current_joint].upper_point * (1.f - stippling/2.f) + joints[previous_joint].upper_point * (stippling/2.f) : joints[current_joint].upper_point) + joints[current_joint].offset; | |
sf::Vector2f lower_previous = ((stippling)? joints[previous_joint].lower_point * (1.f - stippling/2.f) + joints[current_joint].lower_point * (stippling/2.f) : joints[previous_joint].lower_point) + joints[previous_joint].offset; | |
sf::Vector2f lower_next = ((stippling)? joints[current_joint].lower_point * (1.f - stippling/2.f) + joints[previous_joint].lower_point * (stippling/2.f) : joints[current_joint].lower_point) + joints[current_joint].offset; | |
previous_accumulator = offset_accumulator; | |
offset_accumulator += 1/texture_pan; | |
float alpha = (1.f - previous_accumulator) / (offset_accumulator - previous_accumulator); | |
// Testing if the bloc is split by the texture | |
if(offset_accumulator > 1.f) | |
{ | |
sf::Vector2f lower_separator = lower_next * alpha + lower_previous * (1.f - alpha); | |
sf::Vector2f center_separator = center_next * alpha + center_previous * (1.f - alpha); | |
sf::Vector2f upper_separator = upper_next * alpha + upper_previous * (1.f - alpha); | |
sf::FloatRect left_bloc_coords = coords; | |
left_bloc_coords.width = coords.width / texture_pan * alpha; | |
left_bloc_coords.left += coords.width * previous_accumulator; | |
sf::FloatRect right_bloc_coords = coords; | |
right_bloc_coords.width = coords.width / texture_pan * (1.f - alpha); | |
// Splitting | |
// First part | |
DrawTexturedBloc(target, states, upper_previous, upper_separator, center_previous, center_separator, lower_previous, lower_separator, left_bloc_coords); | |
// Second part | |
DrawTexturedBloc(target, states, upper_separator, upper_next, center_separator, center_next, lower_separator, lower_next, right_bloc_coords); | |
offset_accumulator -= 1.f; | |
} | |
else | |
{ | |
sf::FloatRect bloc_coords = coords; | |
bloc_coords.width = coords.width / texture_pan; | |
if(previous_accumulator >= 1.f) | |
bloc_coords.left += coords.width * (previous_accumulator - 1.f); | |
else | |
bloc_coords.left += coords.width * previous_accumulator; | |
// Normal rendering | |
DrawTexturedBloc(target, states, upper_previous, upper_next, center_previous, center_next, lower_previous, lower_next, bloc_coords); | |
} | |
} | |
} | |
else | |
{ | |
DrawMonochrome(target, states); | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::DrawTexturedBloc(sf::RenderTarget & target, sf::RenderStates states, const sf::Vector2f & TopLeft, const sf::Vector2f & TopRight, const sf::Vector2f & CenterLeft, const sf::Vector2f & CenterRight, const sf::Vector2f & BottomLeft, const sf::Vector2f & BottomRight, const sf::FloatRect & TexCoords) const | |
{ | |
if(symetric) | |
{ | |
sf::VertexArray first(sf::TrianglesStrip, 4); | |
first[0].position = CenterLeft; | |
first[0].texCoords = sf::Vector2f(TexCoords.left, TexCoords.height + TexCoords.top); | |
first[1].position = CenterRight; | |
first[1].texCoords = sf::Vector2f(TexCoords.width + TexCoords.left, TexCoords.height + TexCoords.top); | |
first[2].position = TopLeft; | |
first[2].texCoords = sf::Vector2f(TexCoords.left, TexCoords.top); | |
first[3].position = TopRight; | |
first[3].texCoords = sf::Vector2f(TexCoords.width + TexCoords.left, TexCoords.top); | |
sf::VertexArray second(sf::TrianglesStrip, 4); | |
second[0].position = CenterLeft; | |
second[0].texCoords = sf::Vector2f(TexCoords.left, TexCoords.height + TexCoords.top); | |
second[1].position = CenterRight; | |
second[1].texCoords = sf::Vector2f(TexCoords.width + TexCoords.left, TexCoords.height + TexCoords.top); | |
second[2].position = BottomLeft; | |
second[2].texCoords = sf::Vector2f(TexCoords.left, TexCoords.top); | |
second[3].position = BottomRight; | |
second[3].texCoords = sf::Vector2f(TexCoords.width + TexCoords.left, TexCoords.top); | |
target.draw(first, states); | |
target.draw(second, states); | |
} | |
else | |
{ | |
sf::VertexArray first(sf::TrianglesStrip, 4); | |
first[0].position = TopLeft; | |
first[0].texCoords = sf::Vector2f(TexCoords.left, TexCoords.height + TexCoords.top); | |
first[1].position = TopRight; | |
first[1].texCoords = sf::Vector2f(TexCoords.width + TexCoords.left, TexCoords.height + TexCoords.top); | |
first[2].position = BottomLeft; | |
first[2].texCoords = sf::Vector2f(TexCoords.left, TexCoords.top); | |
first[3].position = BottomRight; | |
first[3].texCoords = sf::Vector2f(TexCoords.width + TexCoords.left, TexCoords.top); | |
target.draw(first, states); | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::DrawMonochrome(sf::RenderTarget& target, sf::RenderStates states) const | |
{ | |
states.texture = nullptr; | |
for(unsigned int i = 1; i < joints.size(); i++) | |
DrawMonochromeBloc(target, states, i, i-1); | |
if(loop) | |
DrawMonochromeBloc(target, states, 0, joints.size()-1); | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::DrawMonochromeBloc(sf::RenderTarget & target, sf::RenderStates states, unsigned int current_joint, unsigned int previous_joint) const | |
{ | |
sf::Vector2f center_previous = ((stippling)? joints[previous_joint].position * (1.f - stippling/2.f) + joints[current_joint].position * (stippling/2.f) : joints[previous_joint].position) + joints[previous_joint].offset; | |
sf::Vector2f center_next = ((stippling)? joints[current_joint].position * (1.f - stippling/2.f) + joints[previous_joint].position * (stippling/2.f) : joints[current_joint].position) + joints[current_joint].offset; | |
sf::Vector2f upper_previous = ((stippling)? joints[previous_joint].upper_point * (1.f - stippling/2.f) + joints[current_joint].upper_point * (stippling/2.f) : joints[previous_joint].upper_point) + joints[previous_joint].offset; | |
sf::Vector2f upper_next = ((stippling)? joints[current_joint].upper_point * (1.f - stippling/2.f) + joints[previous_joint].upper_point * (stippling/2.f) : joints[current_joint].upper_point) + joints[current_joint].offset; | |
sf::Vector2f lower_previous = ((stippling)? joints[previous_joint].lower_point * (1.f - stippling/2.f) + joints[current_joint].lower_point * (stippling/2.f) : joints[previous_joint].lower_point) + joints[previous_joint].offset; | |
sf::Vector2f lower_next = ((stippling)? joints[current_joint].lower_point * (1.f - stippling/2.f) + joints[previous_joint].lower_point * (stippling/2.f) : joints[current_joint].lower_point) + joints[current_joint].offset; | |
// First Side | |
sf::VertexArray first(sf::TrianglesStrip, 4); | |
first[0].position = center_previous; | |
first[1].position = center_next; | |
first[2].position = upper_previous; | |
first[3].position = upper_next; | |
// Second Side | |
sf::VertexArray second(sf::TrianglesStrip, 4); | |
first[0].position = center_previous; | |
first[1].position = center_next; | |
first[2].position = lower_previous; | |
first[3].position = lower_next; | |
target.draw(first, states); | |
target.draw(second, states); | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::DrawWireframe(sf::RenderTarget& target, sf::RenderStates states) const | |
{ | |
states.texture = nullptr; | |
std::size_t size = joints.size(); | |
if(loop) | |
++size; | |
sf::VertexArray first(sf::LinesStrip, size); | |
for(unsigned int i = 0; i < joints.size(); i++) | |
first[i].position = sf::Vector2f(joints[i].position.x + joints[i].offset.x, joints[i].position.y + joints[i].offset.y); | |
if(loop) | |
first[size-1].position = first[0].position; | |
sf::VertexArray second(sf::LinesStrip, size); | |
for(unsigned int i = 0; i < joints.size(); i++) | |
{ | |
second[i].position = sf::Vector2f(joints[i].upper_point.x + joints[i].offset.x, joints[i].upper_point.y + joints[i].offset.y); | |
second[i].color = sf::Color(128, 128, 128); | |
} | |
if(loop) | |
{ | |
second[size-1].position = second[0].position; | |
second[size-1].color = second[0].color; | |
} | |
sf::VertexArray third(sf::LinesStrip, size); | |
for(unsigned int i = 0; i < joints.size(); i++) | |
{ | |
third[i].position = sf::Vector2f(joints[i].lower_point.x + joints[i].offset.x, joints[i].lower_point.y + joints[i].offset.y); | |
third[i].color = sf::Color(128, 128, 128); | |
} | |
if(loop) | |
{ | |
third[size-1].position = third[0].position; | |
third[size-1].color = third[0].color; | |
} | |
sf::VertexArray forth(sf::Lines, 2*joints.size()); | |
for(unsigned int i = 0; i < joints.size(); i++) | |
{ | |
forth[i].position = sf::Vector2f(joints[i].upper_point.x + joints[i].offset.x, joints[i].upper_point.y + joints[i].offset.y); | |
forth[i].color = sf::Color(128, 128, 128); | |
forth[i+1].position = sf::Vector2f(joints[i].lower_point.x + joints[i].offset.x, joints[i].lower_point.y + joints[i].offset.y); | |
forth[i+1].color = sf::Color(128, 128, 128); | |
} | |
const_cast<Stroke*>(this)->GetBoundingBox(); | |
sf::VertexArray fifth(sf::LinesStrip, 5); | |
fifth[0].position = sf::Vector2f(bounding_box.left, bounding_box.top); | |
fifth[0].color = sf::Color(32, 164, 32); | |
fifth[1].position = sf::Vector2f(bounding_box.left, bounding_box.top + bounding_box.height); | |
fifth[1].color = sf::Color(32, 164, 32); | |
fifth[2].position = sf::Vector2f(bounding_box.top + bounding_box.height, bounding_box.top + bounding_box.height); | |
fifth[2].color = sf::Color(32, 164, 32); | |
fifth[3].position = sf::Vector2f(bounding_box.left + bounding_box.width, bounding_box.top); | |
fifth[3].color = sf::Color(32, 164, 32); | |
fifth[4].position = fifth[0].position; | |
fifth[4].color = fifth[0].color; | |
target.draw(first, states); | |
target.draw(second, states); | |
target.draw(third, states); | |
target.draw(forth, states); | |
target.draw(fifth, states); | |
} | |
//////////////////////////////////////////////////////////// | |
bool Stroke::Compile() | |
{ | |
if(joints.size() < 2) | |
return false; | |
float total_length = GetLength(); | |
// Determining joints' angles | |
if(loop) | |
{ | |
{ | |
// First joint | |
joints[0].angle = Angle(joints[0].position, joints[1].position); | |
// Calculating in and out angles | |
float angle1 = Angle(joints[joints.size()-1].position, joints[0].position); | |
float angle2 = Angle(joints[0].position, joints[1].position); | |
// Calculating joint angle | |
joints[0].angle = (angle1 + angle2)/2.f; | |
// In certain cases, previous line give the opposite of the wanted angle, applying correction if so | |
if(Sign(angle1) != Sign(angle2) && ((angle1 > 90 || angle1 < -90) || (angle2 > 90 || angle2 < -90)) && (Norm(angle1) + Norm(angle2) > 180)) | |
{ | |
if(Sign(joints[0].angle) == 1) | |
joints[0].angle -= 180; | |
else | |
joints[0].angle += 180; | |
} | |
} | |
{ | |
// Last joint | |
joints[joints.size()-1].angle = Angle(joints[joints.size()-2].position, joints[joints.size()-1].position); | |
// Calculating in and out angles | |
float angle1 = Angle(joints[joints.size()-2].position, joints[joints.size()-1].position); | |
float angle2 = Angle(joints[joints.size()-1].position, joints[0].position); | |
// Calculating joint angle | |
joints[joints.size()-1].angle = (angle1 + angle2)/2.f; | |
// In certain cases, previous line give the opposite of the wanted angle, applying correction if so | |
if(Sign(angle1) != Sign(angle2) && ((angle1 > 90 || angle1 < -90) || (angle2 > 90 || angle2 < -90)) && (Norm(angle1) + Norm(angle2) > 180)) | |
{ | |
if(Sign(joints[joints.size()-1].angle) == 1) | |
joints[joints.size()-1].angle -= 180; | |
else | |
joints[joints.size()-1].angle += 180; | |
} | |
} | |
} | |
else | |
{ | |
// First joint | |
joints[0].angle = Angle(joints[0].position, joints[1].position); | |
// Last joint | |
joints[joints.size()-1].angle = Angle(joints[joints.size()-2].position, joints[joints.size()-1].position); | |
} | |
// other joints | |
for(unsigned int i = 1; i < joints.size()-1; i++) | |
{ | |
// Calculating in and out angles | |
float angle1 = Angle(joints[i-1].position, joints[i].position); | |
float angle2 = Angle(joints[i].position, joints[i+1].position); | |
// Calculating joint angle | |
joints[i].angle = (angle1 + angle2)/2.f; | |
// In certain cases, previous line give the opposite of the wanted angle, applying correction if so | |
if(Sign(angle1) != Sign(angle2) && ((angle1 > 90 || angle1 < -90) || (angle2 > 90 || angle2 < -90)) && (Norm(angle1) + Norm(angle2) > 180)) | |
{ | |
if(Sign(joints[i].angle) == 1) | |
joints[i].angle -= 180; | |
else | |
joints[i].angle += 180; | |
} | |
} | |
// Compiling outer points, inner points, thickness and color of each joint | |
float l = 0; | |
for(unsigned int i = 0; i < joints.size(); i++) | |
{ | |
if(i > 0) | |
l += Distance(joints[i-1].position, joints[i].position); | |
float alpha = l / total_length; | |
float off = (stroke_offset + 1.f)/2.f; | |
float t = (thickness/2.f) * joints[i].thickness_scale; | |
joints[i].thickness = ComputeThickness(alpha, off, t); | |
joints[i].upper_point = joints[i].position + ToVector(joints[i].angle + 90, joints[i].thickness); | |
joints[i].lower_point = joints[i].position + ToVector(joints[i].angle - 90, joints[i].thickness); | |
if(draw_mode == Solid || draw_mode == Textured) | |
{ | |
joints[i].inner_color = ColorInterpolation(start_inner_color, end_inner_color, alpha); | |
joints[i].outer_color = ColorInterpolation(start_outer_color, end_outer_color, alpha); | |
} | |
} | |
is_bounding_box_compiled = false; | |
is_compiled = true; | |
return true; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::ComputeOffset() | |
{ | |
for(unsigned int i = 0; i < joints.size(); i++) | |
{ | |
float offset = myRand(-shaking, shaking); | |
joints[i].offset =ToVector(joints[i].angle + 90, offset); | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::CompileBoundingBox() | |
{ | |
// Compiling bounding box | |
float Left = joints[0].position.x; | |
float Right = joints[0].position.x; | |
float Top = joints[0].position.y; | |
float Bottom = joints[0].position.y; | |
for(unsigned int i = 0; i < joints.size(); i++) | |
{ | |
if(joints[i].lower_point.x < Left) | |
Left = joints[i].lower_point.x; | |
if(joints[i].upper_point.x < Left) | |
Left = joints[i].upper_point.x; | |
if(joints[i].lower_point.y < Top) | |
Top = joints[i].lower_point.y; | |
if(joints[i].upper_point.y < Top) | |
Top = joints[i].upper_point.y; | |
if(joints[i].lower_point.x > Right) | |
Right = joints[i].lower_point.x; | |
if(joints[i].upper_point.x > Right) | |
Right = joints[i].upper_point.x; | |
if(joints[i].lower_point.y > Bottom) | |
Bottom = joints[i].lower_point.y; | |
if(joints[i].upper_point.y > Bottom) | |
Bottom = joints[i].upper_point.y; | |
} | |
bounding_box.left = Left; | |
bounding_box.top = Top; | |
bounding_box.width = Right - Left; | |
bounding_box.height = Bottom - Top; | |
is_bounding_box_compiled = true; | |
} | |
//////////////////////////////////////////////////////////// | |
void Stroke::CompileLength() | |
{ | |
float temp_length = 0; | |
if(joints.size() > 1) | |
for(unsigned int i = 1; i < joints.size(); i++) | |
temp_length += Distance(joints[i-1].position, joints[i].position); | |
length = temp_length; | |
is_length_compiled = true; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::ComputeThickness(float alpha, float offset, float t) | |
{ | |
if(alpha <= offset) | |
{ | |
float a = (alpha * (1.f - end_thickness))/offset + end_thickness; | |
if(end_sweep) | |
{ | |
float b = ApplySweep(end_sweep_style, a); | |
t *= a * (1.f - end_sweep) + b * end_sweep; | |
} | |
else | |
t *= a; | |
} | |
else | |
{ | |
float a = ((alpha - 1.f) * (1.f - start_thickness))/(offset - 1.f) + start_thickness; | |
if(start_sweep) | |
{ | |
float b = ApplySweep(start_sweep_style, a); | |
t *= a * (1.f - start_sweep) + b * start_sweep; | |
} | |
else | |
t *= a; | |
} | |
return t; | |
} | |
//////////////////////////////////////////////////////////// | |
float Stroke::ApplySweep(int sweep_style, float a) | |
{ | |
switch(sweep_style) | |
{ | |
case Soft: | |
return sin(a/2.f * M_PI); | |
case Softer: | |
return sin(sin(a/2.f * M_PI)/2.f * M_PI); | |
case Sharp: | |
return sin(a/2.f * M_PI) * sin(a/2.f * M_PI); | |
default: | |
return a; | |
} | |
} | |
//////////////////////////////////////////////////////////// | |
inline float Stroke::ToRange(float value, float min, float max) | |
{ | |
if(value < min) value = min; | |
if(value > max) value = max; | |
return value; | |
} | |
//////////////////////////////////////////////////////////// | |
inline float Stroke::ToDeg(float angle) | |
{ | |
return angle * 180.f / M_PI; | |
} | |
//////////////////////////////////////////////////////////// | |
inline float Stroke::ToRad(float angle) | |
{ | |
return angle * M_PI / 180.f; | |
} | |
//////////////////////////////////////////////////////////// | |
inline float Stroke::Angle(const sf::Vector2f & P1, const sf::Vector2f & P2) | |
{ | |
if(P1 == P2) | |
return 0; | |
else | |
return ToDeg(atan2(P1.y - P2.y, P2.x - P1.x)); | |
} | |
//////////////////////////////////////////////////////////// | |
inline float Stroke::Distance(const sf::Vector2f & P1, const sf::Vector2f & P2) | |
{ | |
return sqrt((P1.x - P2.x) * (P1.x - P2.x) + (P1.y - P2.y) * (P1.y - P2.y)); | |
} | |
//////////////////////////////////////////////////////////// | |
inline sf::Vector2f Stroke::ToVector(float angle, float length) | |
{ | |
angle = ToRad(angle); | |
return sf::Vector2f(length * cos(angle), length * -sin(angle)); | |
} | |
//////////////////////////////////////////////////////////// | |
inline float Stroke::Sign(float value) | |
{ | |
if(value >= 0) | |
return 1; | |
else | |
return -1; | |
} | |
//////////////////////////////////////////////////////////// | |
inline float Stroke::Norm(float value) | |
{ | |
return value * Sign(value); | |
} | |
//////////////////////////////////////////////////////////// | |
inline sf::Color Stroke::ColorInterpolation(const sf::Color & color1, const sf::Color & color2, float alpha) | |
{ | |
return sf::Color(static_cast<sf::Uint8>(static_cast<float>(color1.r) * alpha + static_cast<float>(color2.r) * (1.f - alpha)), | |
static_cast<sf::Uint8>(static_cast<float>(color1.g) * alpha + static_cast<float>(color2.g) * (1.f - alpha)), | |
static_cast<sf::Uint8>(static_cast<float>(color1.b) * alpha + static_cast<float>(color2.b) * (1.f - alpha)), | |
static_cast<sf::Uint8>(static_cast<float>(color1.a) * alpha + static_cast<float>(color2.a) * (1.f - alpha))); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef STROKE_HPP | |
#define STROKE_HPP | |
//////////////////////////////////////////////////////////// | |
// Headers | |
//////////////////////////////////////////////////////////// | |
#include <SFML/Graphics.hpp> | |
#include <deque> | |
#include <cmath> | |
#ifndef M_PI | |
#define M_PI 3.14159265358979323846f | |
#endif | |
const float myRand(float low, float high); | |
//////////////////////////////////////////////////////////// | |
/// \brief A graphical stroke. | |
//////////////////////////////////////////////////////////// | |
class Stroke : public sf::Drawable | |
{ | |
public: | |
enum SweepStyle | |
{ | |
Soft = 0, | |
Softer, | |
Sharp | |
}; | |
enum DrawMode | |
{ | |
Solid = 0, | |
Textured, | |
Monochrome, | |
WireFrame | |
}; | |
private: | |
//////////////////////////////////////////////////////////// | |
/// \brief Define a joint of the stroke, with all its data members. | |
/// | |
//////////////////////////////////////////////////////////// | |
struct Joint | |
{ | |
Joint(); | |
sf::Vector2f position; | |
sf::Vector2f offset; | |
float birth_time; | |
float thickness; | |
float angle; | |
sf::Vector2f upper_point; | |
sf::Vector2f lower_point; | |
sf::Color inner_color; | |
sf::Color outer_color; | |
float thickness_scale; | |
}; | |
//////////////////////////////////////////////////////////// | |
// Member data | |
//////////////////////////////////////////////////////////// | |
// Bones | |
std::deque<Joint> joints; ///< The joints of the stroke | |
float time; ///< The lifetime elapsed, used with joints lifetime | |
// Body structure | |
unsigned int max_joints; ///< Maximum joints the stroke can have | |
float max_length; ///< Maximum length the stroke can have | |
float min_segment_length; ///< Minimum length between each segments | |
float joint_lifetime; ///< Maximum time the joints can stay | |
sf::Vector2f joint_linear_speed; ///< Linear speed the joints move | |
// Stroke option | |
float thickness; ///< Global thickness | |
sf::Vector2f random_thickness; ///< Random thickness applyed when adding joint | |
float start_thickness; ///< Thickness at the start of the stroke | |
float end_thickness; ///< Thickness at the end of the stroke | |
float stroke_offset; ///< Position of the separation between start and end | |
float start_sweep; ///< Amplitude of the sweep effect at the start | |
float end_sweep; ///< Amplitude of the sweep effect at the end | |
SweepStyle start_sweep_style; ///< Effect used at the start of the stroke | |
SweepStyle end_sweep_style; ///< Effect used at the end of the stroke | |
float stippling; ///< Amplitude of the stippling effect | |
float shaking; ///< Amplitude of the shaking effect | |
bool loop; ///< Loop the stroke by joining first and last joint | |
// Appearance | |
DrawMode draw_mode; ///< Drawing mode used to render the stroke | |
sf::Color start_inner_color; ///< Inner color at the start of the stroke (used by monochrome mode) | |
sf::Color start_outer_color; ///< Outer color at the start of the stroke | |
sf::Color end_inner_color; ///< Inner color at the end of the stroke | |
sf::Color end_outer_color; ///< Outer color at the end of the stroke | |
// Texture | |
sf::Texture texture; ///< Image used in Textured mode | |
sf::IntRect sub_rect; ///< Region drawn from the image | |
bool symetric; ///< Image drawn symetricaly around the stroke | |
float texture_offset; ///< Offset of the texture in the stroke | |
float texture_pan; ///< Pan (number of bloc) the texture will expand on | |
// Length | |
bool is_length_compiled; ///< Flag for lengh computation | |
float length; ///< Total length of the stroke | |
// Bonding Box | |
bool is_bounding_box_compiled; ///< Flag for bounding box computation | |
sf::FloatRect bounding_box; ///< Bounding box of the stroke | |
// State | |
bool is_compiled; ///< Flag for stroke computation | |
//////////////////////////////////////////////////////////// | |
/// \brief Draw the object to a render target | |
/// | |
/// Render the stroke according to the drawing mode choosed. | |
/// The function will compile the stroke and its length if needed. | |
/// | |
/// \param target Render target | |
/// \param renderer Renderer providing low-level rendering commands | |
/// | |
//////////////////////////////////////////////////////////// | |
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Draw the object to a render target | |
/// | |
/// DrawSolid draw the stroke with a solid style, meaning | |
/// the stroke is composed with gradiant polygones. | |
/// | |
/// \param target Render target | |
/// \param renderer Renderer providing low-level rendering commands | |
/// | |
//////////////////////////////////////////////////////////// | |
void DrawSolid(sf::RenderTarget& target, sf::RenderStates states) const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Draw a bloc in the DrawSolid function | |
/// | |
/// A 'bloc' is one of the polygone drawn to form the final stroke. | |
/// | |
/// \param target Render target | |
/// \param renderer Renderer providing low-level rendering commands | |
/// \param current_joint Identifier of the current joint | |
/// \param previous_joint Identifier of the previous joint | |
/// | |
//////////////////////////////////////////////////////////// | |
void DrawSolidBloc(sf::RenderTarget & target, sf::RenderStates states, unsigned int current_joint, unsigned int previous_joint) const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Draw the object to a render target | |
/// | |
/// DrawTexture draw the stroke using the image provided with | |
/// the SetImage() function. If no image is assigned, it call | |
/// the DrawMonochrome instead. | |
/// | |
/// \param target Render target | |
/// \param renderer Renderer providing low-level rendering commands | |
/// | |
//////////////////////////////////////////////////////////// | |
void DrawTexture(sf::RenderTarget & target, sf::RenderStates states) const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Draw a bloc in the DrawTexture function | |
/// | |
/// A 'bloc' is one of the polygone drawn to form the final stroke. | |
/// | |
/// \param target Render target | |
/// \param renderer Renderer providing low-level rendering commands | |
/// \param TopLeft Top-left coordinate of the bloc | |
/// \param TopRight Top-right coordinate of the bloc | |
/// \param CenterLeft Left coordinates of the stroke main line | |
/// \param CenterRight Right coordinates of the stroke main line | |
/// \param BottomLeft Bottom-left coordinates of the bloc | |
/// \param BottomRight Bottom-right coordinates of the bloc | |
/// \param TexCoords Coordinates of the region used as texture on the current image | |
/// | |
//////////////////////////////////////////////////////////// | |
void DrawTexturedBloc(sf::RenderTarget & target, sf::RenderStates states, const sf::Vector2f & TopLeft, const sf::Vector2f & TopRight, const sf::Vector2f & CenterLeft, const sf::Vector2f & CenterRight, const sf::Vector2f & BottomLeft, const sf::Vector2f & BottomRight, const sf::FloatRect & TexCoords) const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Draw the object to a render target | |
/// | |
/// DrawMonochrome draw the stroke only using the color provided | |
/// with the SetColor function. | |
/// | |
/// \param target Render target | |
/// \param renderer Renderer providing low-level rendering commands | |
/// | |
//////////////////////////////////////////////////////////// | |
void DrawMonochrome(sf::RenderTarget& target, sf::RenderStates states) const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Draw a bloc in the DrawMonochrome function | |
/// | |
/// A 'bloc' is one of the polygone drawn to form the final stroke. | |
/// | |
/// \param target Render target | |
/// \param renderer Renderer providing low-level rendering commands | |
/// \param current_joint Identifier of the current joint | |
/// \param previous_joint Identifier of the previous joint | |
/// | |
//////////////////////////////////////////////////////////// | |
void DrawMonochromeBloc(sf::RenderTarget & target, sf::RenderStates states, unsigned int current_joint, unsigned int previous_joint) const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Draw the object to a render target | |
/// | |
/// DrawWireframe draw the stroke with a wired style. The main line | |
/// of the stroke is drawn in white, while the other lines are in gray. | |
/// It is mainly made for debugging and benchmark usage. | |
/// | |
/// \param target Render target | |
/// \param renderer Renderer providing low-level rendering commands | |
/// | |
//////////////////////////////////////////////////////////// | |
void DrawWireframe(sf::RenderTarget& target, sf::RenderStates states) const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Compile the stroke | |
/// | |
/// This function precomputes all the internal parameters | |
/// needed to properly render the stroke (external points, thickness). | |
/// | |
//////////////////////////////////////////////////////////// | |
bool Compile(); | |
//////////////////////////////////////////////////////////// | |
/// \brief Compute the shaking effect | |
/// | |
/// This function precomputes the joints offset due to the | |
/// shaking effect. | |
/// It is called only if the shaking is not at 0. | |
/// | |
//////////////////////////////////////////////////////////// | |
void ComputeOffset(); | |
//////////////////////////////////////////////////////////// | |
/// \brief Compute the bounding box | |
/// | |
/// This function precomputes the bounding box of the stroke. | |
/// It is called only if a bounding box is asked using | |
/// the GetBoundingBox() function. | |
/// | |
//////////////////////////////////////////////////////////// | |
void CompileBoundingBox(); | |
//////////////////////////////////////////////////////////// | |
/// \brief Compute the length | |
/// | |
/// This function precomputes the total length of the stroke, | |
/// in pixels. It is called only if joints are added, moved or | |
/// removed. | |
/// | |
//////////////////////////////////////////////////////////// | |
void CompileLength(); | |
//////////////////////////////////////////////////////////// | |
/// \brief Compute the thickness | |
/// | |
/// This function precomputes the joints thickness regarding | |
/// the thickness parameters. | |
/// | |
/// \param alpha The alpha value of the current joint, | |
/// meaning the length of the joint divised by | |
/// the total length. (Its position on the stroke.) | |
/// \param offset The offset of the sweep. | |
/// \param t The base joint thickness multiplyed by | |
/// the global thickness. | |
/// | |
//////////////////////////////////////////////////////////// | |
float ComputeThickness(float alpha, float offset, float t); | |
//////////////////////////////////////////////////////////// | |
/// \brief Compute the sweep | |
/// | |
/// This function precomputes the stroke sweep effect for | |
/// the current joint, regarding the desired sweep style. | |
/// | |
/// \param sweep_style The wanted sweep style to apply | |
/// \param a The current thickness | |
/// | |
/// /return The new thickness regarding the sweep. | |
//////////////////////////////////////////////////////////// | |
float ApplySweep(int sweep_style, float a); | |
//////////////////////////////////////////////////////////// | |
/// \brief Check if a value is in range | |
/// | |
/// This function ensure the value of a desired variable is | |
/// in its correct range. If the value is out of the range, | |
/// it round the value to the min or max value. | |
/// | |
/// \param value The initial value | |
/// \param min The minimum wanted value | |
/// \param max The maximum wanted value | |
/// | |
/// \return The correct value regarding its range. | |
/// | |
//////////////////////////////////////////////////////////// | |
inline float ToRange(float value, float min = 0.f, float max = 1.f); | |
/**********************************************************/ | |
// Some mathematical functions | |
/**********************************************************/ | |
//////////////////////////////////////////////////////////// | |
/// \brief Angle convertion in degree | |
/// | |
/// \param angle The angle in radian | |
/// | |
/// \return The angle in degree | |
/// | |
//////////////////////////////////////////////////////////// | |
inline float ToDeg(float angle); | |
//////////////////////////////////////////////////////////// | |
/// \brief Angle convertion in radian | |
/// | |
/// \param angle The angle in degree | |
/// | |
/// \return The angle in radian | |
/// | |
//////////////////////////////////////////////////////////// | |
inline float ToRad(float angle); | |
//////////////////////////////////////////////////////////// | |
/// \brief Angle were the segment P1P2 point to | |
/// | |
/// \param P1 First point of the segment | |
/// \param P2 Second point of the segment | |
/// | |
/// \return The angle of the segment, in the range [-180, 180] | |
/// | |
//////////////////////////////////////////////////////////// | |
inline float Angle(const sf::Vector2f & P1, const sf::Vector2f & P2); | |
//////////////////////////////////////////////////////////// | |
/// \brief Distance between two points | |
/// | |
/// \param P1 First point | |
/// \param P2 Second point | |
/// | |
/// \return The distance between each point | |
/// | |
//////////////////////////////////////////////////////////// | |
inline float Distance(const sf::Vector2f & P1, const sf::Vector2f & P2); | |
//////////////////////////////////////////////////////////// | |
/// \brief Vector from an angle and length | |
/// | |
/// \param angle The angle of the vector | |
/// \param length The length of the vector | |
/// | |
/// \return The desired vector | |
/// | |
//////////////////////////////////////////////////////////// | |
inline sf::Vector2f ToVector(float angle, float length); | |
//////////////////////////////////////////////////////////// | |
/// \brief Sign of a number | |
/// | |
/// \param value The number we want the sign from | |
/// | |
/// \return 1 if positive, -1 if negative. value = 0 is considered positive. | |
/// | |
//////////////////////////////////////////////////////////// | |
inline float Sign(float value); | |
//////////////////////////////////////////////////////////// | |
/// \brief Norm of a number | |
/// | |
/// \param value The number we want the norm from | |
/// | |
/// \return The norm of the number | |
/// | |
//////////////////////////////////////////////////////////// | |
inline float Norm(float value); | |
//////////////////////////////////////////////////////////// | |
/// \brief Interpolate between two colors | |
/// | |
/// \param color1 First color | |
/// \param color2 Second color | |
/// \param alpha The alpha value, in the range [0, 1] | |
/// | |
/// \return The interpolated color | |
/// | |
//////////////////////////////////////////////////////////// | |
inline sf::Color ColorInterpolation(const sf::Color & color1, const sf::Color & color2, float alpha); | |
public: | |
//////////////////////////////////////////////////////////// | |
/// \brief Default constructor | |
/// | |
/// Creates an empty stroke (no joints). | |
/// | |
//////////////////////////////////////////////////////////// | |
Stroke(); | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the linear speed applied to the points | |
/// | |
/// \return Linear speed, in pixels/sec | |
/// | |
/// \see SetJointLinearSpeed | |
/// | |
//////////////////////////////////////////////////////////// | |
const sf::Vector2f & GetJointLinearSpeed() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the maximum joints the stroke can contain | |
/// | |
/// \return Maximum joints of the stroke | |
/// | |
/// \see SetMaxJoints | |
/// | |
//////////////////////////////////////////////////////////// | |
unsigned int GetMaxJoints() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the maximum length the stroke can have | |
/// | |
/// \return Maximum length of the stroke, in pixels | |
/// | |
/// \see SetMaxLength | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetMaxLength() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the minimum length between each joint | |
/// | |
/// \return Minimum length, in pixels | |
/// | |
/// \see SetMinSegmentLength | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetMinSegmentLength() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the lifetime of each new joint | |
/// | |
/// \return Lifetime, in seconds | |
/// | |
/// \see SetJointLifeTime | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetJointLifetime() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the global thickness of the stroke | |
/// | |
/// \return Global thickness, un pixels | |
/// | |
/// \see SetThickness | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetThickness() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the quotien of the minimum thickness that can | |
/// be randomly generated | |
/// | |
/// \return Minimum thickness | |
/// | |
/// \see SetMaxRandomThickness | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetMaxRandomThickness() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the quotien of the maximum thickness that can | |
/// be randomly generated | |
/// | |
/// \return Maximum thickness | |
/// | |
/// \see SetMinRandomThickness | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetMinRandomThickness() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the quotien of the thickness at the start of the stroke. | |
/// | |
/// \return Start thickness, in range [0, 1] | |
/// | |
/// \see SetStartThickness | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetStartThickness() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the quotien of the thickness at the end of the stroke. | |
/// | |
/// \return End thickness, in range [0,1] | |
/// | |
/// \see SetEndThickness | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetEndThickness() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the offset separating the start from the end of the stroke. | |
/// | |
/// \return Offset, in range [-1, 1] | |
/// | |
/// \see SetOffset | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetOffset() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the quotien of the sweep at the start of the stroke. | |
/// | |
/// \return Start sweep, in range [0, 1] | |
/// | |
/// \see SetStartSweep | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetStartSweep() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the quotien of the sweep at the end of the stroke. | |
/// | |
/// \return End sweep, in range [0, 1] | |
/// | |
/// \see SetEndSweep | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetEndSweep() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the style of the sweep at the start of the stroke. | |
/// | |
/// \return Sweep style | |
/// | |
/// \see SetStartSweepStyle | |
/// | |
//////////////////////////////////////////////////////////// | |
SweepStyle GetStartSweepStyle() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the style of the sweep at the end of the stroke. | |
/// | |
/// \return Sweep style | |
/// | |
/// \see SetEndSweepStyle | |
/// | |
//////////////////////////////////////////////////////////// | |
SweepStyle GetEndSweepStyle() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the quotien of the stippling effect | |
/// | |
/// \return Stippling, in range [0, 1] | |
/// | |
/// \see SetStippling | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetStippling() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the amplitude of the shaking effect | |
/// | |
/// \return Shaking amplitude, in pixels | |
/// | |
/// \see SetShaking | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetShaking() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the looping flag | |
/// | |
/// \return True if the stroke loop | |
/// | |
/// \see SetLoop | |
/// | |
//////////////////////////////////////////////////////////// | |
bool IsLooping() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the inner color at the start of the stroke | |
/// | |
/// \return Start inner color | |
/// | |
/// \see SetStartInnerColor, SetInnerColor | |
/// | |
//////////////////////////////////////////////////////////// | |
const sf::Color & GetStartInnerColor() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the outer color at the start of the stroke | |
/// | |
/// \return Start outer color | |
/// | |
/// \see SetStartOuterColor, SetOuterColor | |
/// | |
//////////////////////////////////////////////////////////// | |
const sf::Color & GetStartOuterColor() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the inner color at the end of the stroke | |
/// | |
/// \return End inner color | |
/// | |
/// \see SetEndInnerColor, SetInnerColor | |
/// | |
//////////////////////////////////////////////////////////// | |
const sf::Color & GetEndInnerColor() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the outer color at the end of the stroke | |
/// | |
/// \return End outer color | |
/// | |
/// \see SetEndOuterColor, SetOuterColor | |
/// | |
//////////////////////////////////////////////////////////// | |
const sf::Color & GetEndOuterColor() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get a pointer to the image used with the Textured style | |
/// | |
/// If the sprite has no source image, or if the image | |
/// doesn't exist anymore, a NULL pointer is returned. | |
/// The returned pointer is const, which means that you can't | |
/// modify the image when you retrieve it with this function. | |
/// | |
/// \return Pointer to the stroke's image | |
/// | |
/// \see SetImage | |
/// | |
//////////////////////////////////////////////////////////// | |
const sf::Texture & GetTexture() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the region of the image displayed by the stroke | |
/// | |
/// \return Rectangle defining the region of the image | |
/// | |
/// \see SetSubRect | |
/// | |
//////////////////////////////////////////////////////////// | |
const sf::IntRect & GetSubRect() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Indicate if the texture is symetric to the stroke | |
/// | |
/// \return True is the texture is symetric | |
/// | |
/// \see SetSymetric | |
/// | |
//////////////////////////////////////////////////////////// | |
bool IsSymetric() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the texture offset of the stroke | |
/// | |
/// \return Texture offset | |
/// | |
/// \see SetTextureOffset | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetTextureOffset() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the texture pan of the stroke | |
/// | |
/// \return Texture pan | |
/// | |
/// \see SetTexturePan | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetTexturePan() const; | |
//////////////////////////////////////////////////////////// | |
/// \brief Get total length of the stroke | |
/// | |
/// \return Total length | |
/// | |
//////////////////////////////////////////////////////////// | |
float GetLength(); | |
//////////////////////////////////////////////////////////// | |
/// \brief Get the bounding box of the stroke | |
/// | |
/// The bounding box is a rectangle incorporating all the points | |
/// created to draw the stroke. It is usefull for collision test. | |
/// For example, a stroke from wich the bounding box is out of the | |
/// current view isn't visible on the screen, and thus it don't need | |
/// to be drawn. | |
/// | |
/// \return Rectangle defining the bounding box of the stroke | |
/// | |
//////////////////////////////////////////////////////////// | |
const sf::FloatRect & GetBoundingBox(); | |
//////////////////////////////////////////////////////////// | |
/// \brief Indicate if the stroke will be appearent if we draw it | |
/// | |
/// This function indicate if the stroke have the minimum requierements | |
/// to be visible on screen. The requierements are: | |
/// - at least 3 joints | |
/// - a thickness different from 0 | |
/// | |
/// \return True if the stroke has enough joints | |
/// | |
//////////////////////////////////////////////////////////// | |
bool IsDrawable() const; | |
// Modificateurs de l'objet | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the joint's linear speed | |
/// | |
/// The linear speed allow the joints to move themselves. It requier | |
/// that the stroke is made dynamic and keep its joints free from | |
/// custom data, meaning the stroke isn't cleared at each frame. The | |
/// speed is expressed in pixel per second on each axis. | |
/// | |
/// Default value : 0 for each Axis | |
/// | |
/// \param x Horizontal velocity | |
/// \param y Vertical velocity | |
/// | |
/// \see GetJointLinearSpeed | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetJointLinearSpeed(float x, float y); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the joint's linear speed | |
/// | |
/// The linear speed allow the joints to move themselves. It requier | |
/// that the stroke is made dynamic and keep its joints free from | |
/// custom data, meaning the stroke isn't cleared at each frame. The | |
/// speed is expressed in pixel per second on each axis. | |
/// | |
/// Default value : 0 for each Axis | |
/// | |
/// \param linear_speed Linear speed in pixel/sec | |
/// | |
/// \see GetJointLinearSpeed | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetJointLinearSpeed(const sf::Vector2f & linear_speed); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the maximum joints the stroke can have | |
/// | |
/// Each stroke is composed of a number of joints. Having a | |
/// restriction on their number can avoid having a stroke | |
/// infinitely growing. It is a way to constraint the length | |
/// of a stroke. | |
/// | |
/// Default value : 0 | |
/// | |
/// Warning : if you want to use a dynamic stroke, be sure to | |
/// set a maximum value to at least one of the following functions: | |
/// - SetMaxJoints | |
/// - SetMaxLength | |
/// - SetJointLifetime | |
/// | |
/// \param max_joints The maximum joints the stroke can have | |
/// | |
/// \see GetMaxJoints, SetMaxJoints, SetMaxLength, SetJointLifetime | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetMaxJoints(unsigned int max_joints); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the maximum length the stroke can have | |
/// | |
/// Stroke don't have limits in length. This function allow | |
/// you to set a limit to the length. The length is basically | |
/// the sum of the distances between each joints, not the distance | |
/// between the first and last joint. | |
/// If the length of the stroke became too long when adding new joints | |
/// with \a AddJoint function, the \ Calculate function will remove | |
/// the last joints of the list until the length get back smaller than | |
/// the maximum length. | |
/// A maximum length of 0 let the stroke grow infinitely. | |
/// | |
/// Warning : if you want to use a dynamic stroke, be sure to | |
/// set a maximum value to at least one of the following functions: | |
/// - SetMaxJoints | |
/// - SetMaxLength | |
/// - SetJointLifetime | |
/// | |
/// Default value : 0 | |
/// | |
/// \param max_length The maximum length the stroke can have, in pixels | |
/// | |
/// \see GetMaxLength, SetMaxJoints, SetMaxLength, SetJointLifetime | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetMaxLength(float max_length); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the minimum length between each joint | |
/// | |
/// Having too few joints give to your stroke a sad polygonal look, | |
/// but too much can be a threat to your program performances. | |
/// The minimum length ensure a new joint placed with the /a AddJoint | |
/// function will have a minimum length with the previous one to | |
/// be added. If it is too close to the previous joint, the new joint | |
/// won't be added. If it is too far, intermediate joints will be added | |
/// forming a straight line. | |
/// A minimum length of 0 allow ANY new joints to be added. | |
/// | |
/// Default value : 0 | |
/// | |
/// \param min_segment_length The minimum length between each joint, in pixels | |
/// | |
/// \see GetMinSegmentLength | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetMinSegmentLength(float min_segment_length); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the lifetime of each joints | |
/// | |
/// This function give a maximum lifetime to your joints. Too | |
/// old joints will be removed by the \a Calculate function. | |
/// It is a cool way to create organic strokes depleting in time. | |
/// It is also a way to avoid infinitely growing strokes. | |
/// | |
/// Warning : if you want to use a dynamic stroke, be sure to | |
/// set a maximum value to at least one of the following functions: | |
/// - SetMaxJoints | |
/// - SetMaxLength | |
/// - SetJointLifetime | |
/// | |
/// Default value : 0 | |
/// | |
/// \param joint_lifetime The lifetime of each joint, in seconds | |
/// | |
/// \see GetJointLifetime | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetJointLifetime(float joint_lifetime); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the global thickness of the stroke | |
/// | |
/// The global thickness is the main thickness of the stroke. It | |
/// prevail over the overthickness, meaning a stroke with a thickness | |
/// of 0 won't be drawn. | |
/// | |
/// Default value : 3 pixels | |
/// | |
/// \param thickness The global thickness, in pixels | |
/// | |
/// \see GetThickness | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetThickness(float thickness); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the range of random thickness | |
/// | |
/// Each joint possess a thickness of it's own. Settings a thickness | |
/// with this function will give a randomly choosed thickness to each | |
/// new joint added with the \a AddJoint function. | |
/// The random thickness take multiples of the global thickness. | |
/// Example : | |
/// \code | |
/// mu_stroke.SetThickness(30.f); | |
/// my_stroke.SetRandomThickness(0.5f, 1.5f); | |
/// \endcode | |
/// With this code, each new joint will receive a thickness | |
/// between 15 and 45 pixels. | |
/// | |
/// Default value : 1 to min and max | |
/// | |
/// \param min Minimum possible value | |
/// \param max Maximim possible value | |
/// | |
/// \see GetMaxRandomThickness, GetMinRandomThickness | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetRandomThickness(float min, float max); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the thickness at the start of the stroke | |
/// | |
/// The stroke have a starting and ending thickness. It allow it | |
/// to have a smoothed shape, defined by both the start/end thickness, | |
/// sweep and sweep style. | |
/// A thickness of 0 will make the stroke tapered at the start, | |
/// a thickness of 1 will make it squared. | |
/// | |
/// Default value : 1 | |
/// | |
/// \param start_thickness Thickness at the start of the stroke, in range [0, 1] | |
/// | |
/// \see GetStartThickness | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetStartThickness(float start_thickness); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the thickness at the end of the stroke | |
/// | |
/// The stroke have a starting and ending thickness. It allow it | |
/// to have a smoothed shape, defined by both the start/end thickness, | |
/// sweep and sweep style. | |
/// A thickness of 0 will make the stroke tapered at the end, | |
/// a thickness of 1 will make it squared. | |
/// | |
/// Default value : 1 | |
/// | |
/// \param end_thickness Thickness at the end of the stroke, in range [0, 1] | |
/// | |
/// \see GetEndThickness | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetEndThickness(float end_thickness); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the offset of the stroke | |
/// | |
/// Having a stroke with tapered start and end give it a more | |
/// organic look. The offset allow you to move the separation | |
/// between each part of the stroke (start and end) along the strok. | |
/// An offset of 1 will move it to the start of the stroke, | |
/// an offset of -1 will move it at the end and an offset of | |
/// 0 keep it at midway of the stroke. | |
/// The offset is useless if neither of the start or end of the stroke | |
/// have a thickness lower that 1. | |
/// | |
/// Default value : 0 | |
/// | |
/// \param stroke_offset Offset of the stroke, in range [-1, 1] | |
/// | |
/// \see GetOffset | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetOffset(float stroke_offset); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the sweep of the stroke | |
/// | |
/// The default tapered stroke take a diamond shape. The sweep | |
/// allow to give your stroke a more swift and smooth shape. | |
/// A sweep of 0 will keep the stroke a diamond shape, while | |
/// a sweep of 1 will give it the full sweep shape defined with | |
/// the sweep style. | |
/// | |
/// SetSweep function set the sweep for both start and end of the stroke. | |
/// | |
/// Default value : 0 | |
/// | |
/// \param sweep Sweep of the stroke, in range [0, 1] | |
/// | |
/// \see GetStartSweep, GetEndSweep, SetStartSweep, SetEndSweep, SetSweepStyle | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetSweep(float sweep); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the start sweep of the stroke | |
/// | |
/// The default tapered stroke take a diamond shape. The sweep | |
/// allow to give your stroke a more swift and smooth shape. | |
/// A sweep of 0 will keep the stroke a diamond shape, while | |
/// a sweep of 1 will give it the full sweep shape defined with | |
/// the sweep style. | |
/// | |
/// Default value : 0 | |
/// | |
/// \param start_sweep Sweep of the start of the stroke, in range [0, 1] | |
/// | |
/// \see GetStartSweep, SetSweepStyle | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetStartSweep(float start_sweep); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the end sweep of the stroke | |
/// | |
/// The default tapered stroke take a diamond shape. The sweep | |
/// allow to give your stroke a more swift and smooth shape. | |
/// A sweep of 0 will keep the stroke a diamond shape, while | |
/// a sweep of 1 will give it the full sweep shape defined with | |
/// the sweep style. | |
/// | |
/// Default value : 0 | |
/// | |
/// \param end_sweep Sweep of the end of the stroke, in range [0, 1] | |
/// | |
/// \see GetEndSweep, SetSweepStyle | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetEndSweep(float end_sweep); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the sweep style of the stroke | |
/// | |
/// The sweep style is the shape the tapered stroke will take | |
/// with a sweep greater than 0. | |
/// | |
/// The sweep style allow the following style : | |
/// - Sin: the stroke will be lightly rounded | |
/// - Sin2: the stroke will be more rounded, | |
/// - Sin3: the stroke will be even more rounded, | |
/// - SquareSin : the stroke will have a piercing look, rounding | |
/// the more it get closer to the offset position | |
/// | |
/// SetSweepStyle set the sweep style for both start and end of the stroke. | |
/// | |
/// Default value : e_Sin for both side | |
/// | |
/// \param sweep_style Sweep style of the stroke | |
/// | |
/// \see SweepStyle, GetStartSweepStyle, GetEndSweepStyle | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetSweepStyle(SweepStyle sweep_style); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the sweep style at the start of the stroke | |
/// | |
/// The sweep style is the shape the tapered stroke will take | |
/// with a sweep greater than 0. | |
/// | |
/// The sweep style allow the following style : | |
/// - Sin: the stroke will be lightly rounded | |
/// - Sin2: the stroke will be more rounded, | |
/// - Sin3: the stroke will be even more rounded, | |
/// - SquareSin : the stroke will have a piercing look, rounding | |
/// the more it get closer to the offset position | |
/// | |
/// Default value : e_Sin | |
/// | |
/// \param start_sweep_style Sweep style at the start of the stroke | |
/// | |
/// \see SweepStyle, GetStartSweepStyle | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetStartSweepStyle(SweepStyle start_sweep_style); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the sweep style at the end of the stroke | |
/// | |
/// The sweep style is the shape the tapered stroke will take | |
/// with a sweep greater than 0. | |
/// | |
/// The sweep style allow the following style : | |
/// - Sin: the stroke will be lightly rounded | |
/// - Sin2: the stroke will be more rounded, | |
/// - Sin3: the stroke will be even more rounded, | |
/// - SquareSin : the stroke will have a piercing look, rounding | |
/// the more it get closer to the offset position | |
/// | |
/// Default value : e_Sin | |
/// | |
/// \param end_sweep_style Sweep style at the end of the stroke | |
/// | |
/// \see SweepStyle, GetEndSweepStyle | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetEndSweepStyle(SweepStyle end_sweep_style); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the stippling of the stroke | |
/// | |
/// This function allow you to set a stippling quotien for | |
/// your stroke. The stippling will give a dotted look to your | |
/// stroke. | |
/// | |
/// A stippling of 0 disable the stippling effect while | |
/// a stippling of 1 will make the stroke non-displayable. | |
/// | |
/// Default value : 0 | |
/// | |
/// \param stippling Stippling of the stroke, in range [0, 1] | |
/// | |
/// \see GetStippling | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetStippling(float stippling); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the shaking amplitude of the stroke | |
/// | |
/// The shaking is a simple distortion of the stroke. With | |
/// static stroke, the shaking will give a distorded look at | |
/// your stroke, with dynamic stroke, it will make the stroke | |
/// shake over the time. | |
/// | |
/// Default value : 0 | |
/// | |
/// \param shaking Shaking amplitude of the stroke, in pixels | |
/// | |
/// \see GetShaking | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetShaking(float shaking); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the shaking amplitude of the stroke | |
/// | |
/// Looping the stroke can be usefull to draw closed path like | |
/// circles or squares. Looping the stroke join the first and last | |
/// joint, computing their angles accordingly. | |
/// | |
/// Default value : false | |
/// | |
/// \param loop Set to true if you need to make the stroke looping | |
/// | |
/// \see GetShaking | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetLoop(bool loop); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the drawing mode for the stroke | |
/// | |
/// The drawing mode allow you to choose between several | |
/// behavior to render the stroke. The drawing mode can take | |
/// one of those modes : | |
/// - Solid: the basic mode, draw the stroke with gradiant colors. | |
/// - Textured: draw the stroke using an image (assigned with \a SetImage) | |
/// If no image is assigned, the stroke is drawn with | |
/// monochrome mode. | |
/// - Monochrome: draw the stroke with a uni color, wich is set | |
/// with \a SetColor | |
/// - Wireframe: draw the stroke with a wired style. The main line | |
/// of the stroke is drawn in white and the other lines | |
/// are drawn in gray. | |
/// | |
/// Default value : Solid | |
/// | |
/// \param draw_mode Drawing mode for the stroke | |
/// | |
/// \see DrawMode | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetDrawMode(DrawMode draw_mode); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the inner color of the stroke | |
/// | |
/// The stroke allow to use different color for both in the stroke | |
/// and out the stroke. It allow to create gradiant between the center | |
/// and extremities of the stroke. | |
/// | |
/// For both inner and outer color, you can also set the color at | |
/// the start and the end of the stroke. | |
/// | |
/// SetInnerColor set the inner color for both start and end of | |
/// the stroke. | |
/// | |
/// Default value : sf::Color(255, 255, 255) | |
/// | |
/// \param inner_color Inner color of the stroke | |
/// | |
/// \see GetStartInnerColor, GetEndInnerColor | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetInnerColor(const sf::Color & inner_color); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the outer color of the stroke | |
/// | |
/// The stroke allow to use different color for both in the stroke | |
/// and out the stroke. It allow to create gradiant between the center | |
/// and extremities of the stroke. | |
/// | |
/// For both inner and outer color, you can also set the color at | |
/// the start and the end of the stroke. | |
/// | |
/// SetOuterColor set the outer color for both start and end of | |
/// the stroke. | |
/// | |
/// Default value : sf::Color(255, 255, 255) | |
/// | |
/// \param outer_color Outer color of the stroke | |
/// | |
/// \see GetStartOuterColor, GetEndOuterColor | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetOuterColor(const sf::Color & outer_color); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the inner color at the start of the stroke | |
/// | |
/// The stroke allow to use different color for both in the stroke | |
/// and out the stroke. It allow to create gradiant between the center | |
/// and extremities of the stroke. | |
/// | |
/// For both inner and outer color, you can also set the color at | |
/// the start and the end of the stroke. | |
/// | |
/// Default value : sf::Color(255, 255, 255) | |
/// | |
/// \param start_inner_color Inner color at the start of the stroke | |
/// | |
/// \see GetStartInnerColor | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetStartInnerColor(const sf::Color & start_inner_color); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the outer color at the start of the stroke | |
/// | |
/// The stroke allow to use different color for both in the stroke | |
/// and out the stroke. It allow to create gradiant between the center | |
/// and extremities of the stroke. | |
/// | |
/// For both inner and outer color, you can also set the color at | |
/// the start and the end of the stroke. | |
/// | |
/// Default value : sf::Color(255, 255, 255) | |
/// | |
/// \param start_outer_color Outer color at the start of the stroke | |
/// | |
/// \see GetStartOuterColor | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetStartOuterColor(const sf::Color & start_outer_color); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the inner color at the end of the stroke | |
/// | |
/// The stroke allow to use different color for both in the stroke | |
/// and out the stroke. It allow to create gradiant between the center | |
/// and extremities of the stroke. | |
/// | |
/// For both inner and outer color, you can also set the color at | |
/// the start and the end of the stroke. | |
/// | |
/// Default value : sf::Color(255, 255, 255) | |
/// | |
/// \param end_inner_color Outer color at the end of the stroke | |
/// | |
/// \see GetStartInnerColor | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetEndInnerColor(const sf::Color & end_inner_color); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the outer color at the end of the stroke | |
/// | |
/// The stroke allow to use different color for both in the stroke | |
/// and out the stroke. It allow to create gradiant between the center | |
/// and extremities of the stroke. | |
/// | |
/// For both inner and outer color, you can also set the color at | |
/// the start and the end of the stroke. | |
/// | |
/// Default value : sf::Color(255, 255, 255) | |
/// | |
/// \param end_outer_color Outer color at the end of the stroke | |
/// | |
/// \see GetEndOuterColor | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetEndOuterColor(const sf::Color & end_outer_color); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the image used has texture of the stroke | |
/// | |
/// A colored stroke is good, a textured one is (often) better! | |
/// This function allow you to set an sf::Image as a texture for | |
/// the stroke. Adding an image automaticaly turn the drawing mode | |
/// to Textured. The image respond to the symetric, texture offset | |
/// and texture pan member data. If an invalid image is passed, | |
/// the stroke will be rendered in Monochrome mode. | |
/// | |
/// Default value : 0 (no image) | |
/// | |
/// \param image Image used has texture | |
/// \param adjust_to_new_size Set to True to adapt the sub rect to the size of the image | |
/// | |
/// \see GetImage, SetSubRect | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetTexture(const sf::Texture & texture, bool adjust_to_new_size = false); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the part of the image that the stroke will display | |
/// | |
/// The sub-rectangle is useful when you don't want to display | |
/// the whole image, but rather a part of it. | |
/// By default, the sub-rectangle covers the entire image. | |
/// | |
/// \param sub_rect Rectangle defining the region of the image to display | |
/// | |
/// \see GetSubRect, SetImage | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetSubRect(const sf::IntRect & sub_rect); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set symetry of the stroke | |
/// | |
/// By setting the symetry, you can choose whether the texture | |
/// is drawn once or twice on each sub-part of the stroke. | |
/// | |
/// \param symetric Set to True to use the symetry | |
/// | |
/// \see GetSubRect, SetImage | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetSymetric(bool symetric); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the texture offset | |
/// | |
/// The texture offset allow you to move the texture along | |
/// the stroke. It can take positive or negative value. | |
/// One stroke unit match to 'texture_pan' blocs. | |
/// | |
/// texture_move = texture_offset * texture_pan | |
/// | |
/// \param texture_offset The offset of the texture | |
/// | |
/// \see GetTextureOffset | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetTextureOffset(float texture_offset); | |
//////////////////////////////////////////////////////////// | |
/// \brief Move the texture | |
/// | |
/// The texture offset allow you to move the texture along | |
/// the stroke. It can take positive or negative value. | |
/// One stroke unit match to 'texture_pan' blocs. | |
/// | |
/// texture_move = texture_offset * texture_pan | |
/// | |
/// MoveTexture add the value to the existing offset | |
/// | |
/// \param texture_offset The offset of the texture | |
/// | |
/// \see GetTextureOffset | |
/// | |
//////////////////////////////////////////////////////////// | |
void MoveTexture(float texture_offset); | |
//////////////////////////////////////////////////////////// | |
/// \brief Set the texture pan | |
/// | |
/// The texture pan strech the texture over 'texture_pan' bloc. | |
/// The minimum pan is 1, meaning the texture will repeat at each | |
/// bloc. A pan of 3 will repeat the texture each 3 blocs. | |
/// | |
/// \param texture_pan The pan of the texture | |
/// | |
/// \see GetTexturePan | |
/// | |
//////////////////////////////////////////////////////////// | |
void SetTexturePan(float texture_pan); | |
//////////////////////////////////////////////////////////// | |
/// \brief Clear the joint array | |
/// | |
/// Remove all the joints from the stroke. | |
/// | |
//////////////////////////////////////////////////////////// | |
void Clear(); | |
//////////////////////////////////////////////////////////// | |
/// \brief Add a joint to the stroke | |
/// | |
/// Add a joint to the stroke, giving its position and if | |
/// a precompilation of the stroke is wanted. | |
/// | |
/// \param x Position of the joint on X Axis (relative position) | |
/// \param y Position of the joint on Y Axis (relative position) | |
/// \param precompile Set to true if a precompilation is needed | |
/// | |
/// \return True if the joint has been successfully added | |
/// | |
//////////////////////////////////////////////////////////// | |
bool AddJoint(float x, float y, bool precompile = false); | |
//////////////////////////////////////////////////////////// | |
/// \brief Add a joint to the stroke | |
/// | |
/// Add a joint to the stroke, giving its position and if | |
/// a precompilation of the stroke is wanted. | |
/// | |
/// \param position Position of the joint (relative position) | |
/// \param precompile Set to true if a precompilation is needed | |
/// | |
/// \return True if the joint has been successfully added | |
/// | |
//////////////////////////////////////////////////////////// | |
bool AddJoint(const sf::Vector2f & position, bool precompile = false); | |
//////////////////////////////////////////////////////////// | |
/// \brief Add a joint to the stroke | |
/// | |
/// Add a joint to the stroke, giving its position and if | |
/// a precompilation of the stroke is wanted. | |
/// | |
/// With the thickness scale, the randomness given by | |
/// the random Thickness parameter will be ignored. | |
/// | |
/// \param x Position of the joint on X Axis (relative position) | |
/// \param y Position of the joint on Y Axis (relative position) | |
/// \param thickness_scale Thickness of the joint | |
/// \param precompile Set to true if a precompilation is needed | |
/// | |
/// \return True if the joint has been successfully added | |
/// | |
//////////////////////////////////////////////////////////// | |
bool AddJoint(float x, float y, float thickness_scale, bool precompile = false); | |
//////////////////////////////////////////////////////////// | |
/// \brief Add a joint to the stroke | |
/// | |
/// Add a joint to the stroke, giving its position and if | |
/// a precompilation of the stroke is wanted. | |
/// | |
/// With the thickness scale, the randomness given by | |
/// the random Thickness parameter will be ignored. | |
/// | |
/// \param position Position of the joint (relative position) | |
/// \param thickness_scale Thickness of the joint | |
/// \param precompile Set to true if a precompilation is needed | |
/// | |
/// \return True if the joint has been successfully added | |
/// | |
//////////////////////////////////////////////////////////// | |
bool AddJoint(const sf::Vector2f & position, float thickness_scale, bool precompile = false); | |
//////////////////////////////////////////////////////////// | |
/// \brief Add a joint to the stroke | |
/// | |
/// Calculate must be called if you want to make your stroke | |
/// dynamic. It calculate the position of the joints according | |
/// to the linear speed and delete useless joints regarding | |
/// maximum length, maximum joint number and joint lifetime | |
/// parameters. | |
/// | |
/// \param time_interval Duration of the frame | |
/// | |
//////////////////////////////////////////////////////////// | |
void Calculate(float time_interval); | |
}; | |
#endif // STROKE_HPP | |
//////////////////////////////////////////////////////////// | |
/// \class Stroke | |
/// | |
/// The Stroke class allow to draw real-time animated strokes. | |
/// It give access to severals stroke parameter, different drawing | |
/// styles and is optimized wether the stroke is static (meaning all | |
/// its joints/points won't change) or dynamic. | |
/// | |
/// Stroke is a graphical class, meaning it is better to 'link' it | |
/// to other data structure, such as a list or vector of points if | |
/// you want a better control over it, for example, handling collision | |
/// with your stroke. | |
/// | |
/// Stroke inherit sf::Drawable, meaning all transformation properties | |
/// of the drawable works. It has a heavy interface as it is wanted to | |
/// be complete and suitable for a large panel of usage. | |
/// | |
/// Static stroke usage example : | |
/// \code | |
/// Stroke my_stroke; | |
/// // A stroke need at least 3 joints to be displayed. | |
/// my_stroke.AddJoint(40, 40); | |
/// my_stroke.AddJoint(200, 50); | |
/// // Set the precompile parameter to true if you want to | |
/// // precompile your stroke while loading your application. | |
/// my_stroke.AddJoint(230, 400, true); | |
/// | |
/// while(true) | |
/// { | |
/// App.Clear(); | |
/// App.Draw(my_stroke); | |
/// App.Display(); | |
/// } | |
/// \endcode | |
/// | |
/// Dynamic stroke usage example : | |
/// \code | |
/// Stroke my_stroke; | |
/// // We add some speed to the joints to make the stroke grow upward. | |
/// my_stroke.SetJointLinearSpeed(0, -200); | |
/// | |
/// while(true) | |
/// { | |
/// // Precompiling is useless because the stroke will change each frame. | |
/// my_stroke.AddJoint(400, 300); | |
/// | |
/// // We need to compute the joints to delete | |
/// // useless joints and move existing ones. | |
/// my_stroke.Calculate(App.GetFrameTime()); | |
/// | |
/// App.Clear(); | |
/// App.Draw(my_stroke); | |
/// App.Display(); | |
/// } | |
/// \endcode | |
//////////////////////////////////////////////////////////// |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment