aboutsummaryrefslogtreecommitdiff
path: root/src/RoundedRectangle.cpp
blob: f9b79c4cf4103a6dbc5681e4bd3c5e00c323c93d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "../include/RoundedRectangle.hpp"
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <assert.h>

namespace QuickMedia {
    RoundedRectangle::RoundedRectangle(sf::Vector2f size, float radius, sf::Color color, sf::Shader *rounded_rectangle_shader) :
        radius(radius), pos(0.0f, 0.0f), size(size), rounded_rectangle_shader(rounded_rectangle_shader), band_color(sf::Color::Transparent)
    {
        assert(rounded_rectangle_shader);
        set_color(color);
        vertices[0].texCoords = sf::Vector2f(0.0f, 0.0f);
        vertices[1].texCoords = sf::Vector2f(1.0f, 0.0f);
        vertices[2].texCoords = sf::Vector2f(1.0f, 1.0f);
        vertices[3].texCoords = sf::Vector2f(0.0f, 1.0f);

        const sf::Color shadow_color(0, 0, 0, 50);

        // Sides
        for(size_t i = 0; i < 16; i += 4) {
            drop_shadow_vertices[i + 0].color = sf::Color(shadow_color.r, shadow_color.g, shadow_color.b, 0);
            drop_shadow_vertices[i + 1].color = sf::Color(shadow_color.r, shadow_color.g, shadow_color.b, 0);
            drop_shadow_vertices[i + 2].color = shadow_color;
            drop_shadow_vertices[i + 3].color = shadow_color;
        }

        // Corners
        for(size_t i = 16; i < 32; i += 4) {
            drop_shadow_vertices[i + 0].color = sf::Color(shadow_color.r, shadow_color.g, shadow_color.b, 0);
            drop_shadow_vertices[i + 1].color = sf::Color(shadow_color.r, shadow_color.g, shadow_color.b, 0);
            drop_shadow_vertices[i + 2].color = sf::Color(shadow_color.r, shadow_color.g, shadow_color.b, 0);
            drop_shadow_vertices[i + 3].color = sf::Color(shadow_color.r, shadow_color.g, shadow_color.b, 100);
        }
    }

    void RoundedRectangle::set_position(sf::Vector2f pos) {
        this->pos = pos;
        vertices[0].position = pos;
        vertices[1].position = pos + sf::Vector2f(size.x, 0.0f);
        vertices[2].position = pos + sf::Vector2f(size.x, size.y);
        vertices[3].position = pos + sf::Vector2f(0.0f, size.y);

        const float shadow_radius = 5.0f;

        // Top
        drop_shadow_vertices[0].position = pos + sf::Vector2f(radius*0.5f, 0.0f) - sf::Vector2f(0.0f, shadow_radius);
        drop_shadow_vertices[1].position = pos + sf::Vector2f(size.x - radius*0.5f, 0.0f) - sf::Vector2f(0.0f, shadow_radius);
        drop_shadow_vertices[2].position = pos + sf::Vector2f(size.x - radius*0.5f, 0.0f);
        drop_shadow_vertices[3].position = pos + sf::Vector2f(radius*0.5f, 0.0f);

        // Bottom
        drop_shadow_vertices[4].position = pos + sf::Vector2f(size.x - radius*0.5f, size.y + shadow_radius);
        drop_shadow_vertices[5].position = pos + sf::Vector2f(radius*0.5f, size.y + shadow_radius);
        drop_shadow_vertices[6].position = pos + sf::Vector2f(radius*0.5f, size.y);
        drop_shadow_vertices[7].position = pos + sf::Vector2f(size.x - radius*0.5f, size.y);

        // Left
        drop_shadow_vertices[8].position = pos + sf::Vector2f(-shadow_radius, size.y - radius*0.5f);
        drop_shadow_vertices[9].position = pos + sf::Vector2f(-shadow_radius, radius*0.5f);
        drop_shadow_vertices[10].position = pos + sf::Vector2f(0.0f, radius*0.5f);
        drop_shadow_vertices[11].position = pos + sf::Vector2f(0.0f, size.y - radius*0.5f);

        // Right
        drop_shadow_vertices[12].position = pos + sf::Vector2f(size.x + shadow_radius, radius*0.5f);
        drop_shadow_vertices[13].position = pos + sf::Vector2f(size.x + shadow_radius, size.y - radius*0.5f);
        drop_shadow_vertices[14].position = pos + sf::Vector2f(size.x, size.y - radius*0.5f);
        drop_shadow_vertices[15].position = pos + sf::Vector2f(size.x, radius*0.5f);

        const float overshoot = 1.7f;

        // Top left
        drop_shadow_vertices[16].position = pos + sf::Vector2f(-shadow_radius, radius*0.5f);
        drop_shadow_vertices[17].position = pos + sf::Vector2f(-shadow_radius*overshoot, -shadow_radius*overshoot);
        drop_shadow_vertices[18].position = pos + sf::Vector2f(radius*0.5f, -shadow_radius);
        drop_shadow_vertices[19].position = pos + sf::Vector2f(radius*0.5f, radius*0.5f);

        // Top right
        drop_shadow_vertices[20].position = pos + sf::Vector2f(size.x - radius*0.5f, -shadow_radius);
        drop_shadow_vertices[21].position = pos + sf::Vector2f(size.x + shadow_radius*overshoot, -shadow_radius*overshoot);
        drop_shadow_vertices[22].position = pos + sf::Vector2f(size.x + shadow_radius, radius*0.5f);
        drop_shadow_vertices[23].position = pos + sf::Vector2f(size.x - radius*0.5f, radius*0.5f);

        // Bottom right
        drop_shadow_vertices[24].position = pos + sf::Vector2f(size.x + shadow_radius, size.y - radius*0.5f);
        drop_shadow_vertices[25].position = pos + sf::Vector2f(size.x + shadow_radius*overshoot, size.y + shadow_radius*overshoot);
        drop_shadow_vertices[26].position = pos + sf::Vector2f(size.x - radius*0.5f, size.y + shadow_radius);
        drop_shadow_vertices[27].position = pos + sf::Vector2f(size.x - radius*0.5f, size.y - radius*0.5f);

        // Bottom left
        drop_shadow_vertices[28].position = pos + sf::Vector2f(radius*0.5f, size.y + shadow_radius);
        drop_shadow_vertices[29].position = pos + sf::Vector2f(-shadow_radius*overshoot, size.y + shadow_radius*overshoot);
        drop_shadow_vertices[30].position = pos + sf::Vector2f(-shadow_radius, size.y - radius*0.5f);
        drop_shadow_vertices[31].position = pos + sf::Vector2f(radius*0.5f, size.y - radius*0.5f);
    }

    void RoundedRectangle::set_size(sf::Vector2f size) {
        this->size = size;
        set_position(pos);
    }

    void RoundedRectangle::set_color(sf::Color color) {
        for(size_t i = 0; i < 4; ++i)
            vertices[i].color = color;
    }

    sf::Vector2f RoundedRectangle::get_position() const {
        return pos;
    }

    sf::Vector2f RoundedRectangle::get_size() const {
        return size;
    }

    void RoundedRectangle::set_band(sf::Vector2f pos, sf::Vector2f size) {
        band_pos = pos;
        band_size = size;
    }

    void RoundedRectangle::set_band_color(sf::Color color) {
        band_color = color;
    }

    void RoundedRectangle::draw(sf::RenderTarget &target) {
        if(drop_shadow_enabled)
            target.draw(drop_shadow_vertices, 32, sf::Quads);

        // TODO: Remove these for optimizations. Also do the same in other places where setUniform is called
        rounded_rectangle_shader->setUniform("radius", radius);
        rounded_rectangle_shader->setUniform("band_pos", band_pos);
        rounded_rectangle_shader->setUniform("band_size", band_size);
        rounded_rectangle_shader->setUniform("band_color", sf::Glsl::Vec4(band_color.r/255.0f, band_color.g/255.0f, band_color.b/255.0f, band_color.a/255.0f));
        rounded_rectangle_shader->setUniform("resolution", size);
        target.draw(vertices, 4, sf::Quads, rounded_rectangle_shader);
    }
}