aboutsummaryrefslogtreecommitdiff
path: root/extension/src/openvic-extension/classes/GFXButtonStateTexture.cpp
blob: e6dff1f718986af2b99442efec13b0cbb85aba9e (plain) (blame)
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
#include "GFXButtonStateTexture.hpp"

#include "openvic-extension/utility/ClassBindings.hpp"

using namespace OpenVic;
using namespace godot;

void GFXButtonStateTexture::_bind_methods() {
   OV_BIND_METHOD(GFXButtonStateTexture::set_button_state, { "new_button_state" });
   OV_BIND_METHOD(GFXButtonStateTexture::get_button_state);

   OV_BIND_SMETHOD(get_generate_state_image_func_name);

   OV_BIND_SMETHOD(button_state_to_theme_name, { "button_state" });
   OV_BIND_METHOD(GFXButtonStateTexture::get_button_state_theme);

   OV_BIND_METHOD(GFXButtonStateTexture::generate_state_image, { "source_image" });

   BIND_ENUM_CONSTANT(HOVER);
   BIND_ENUM_CONSTANT(PRESSED);
   BIND_ENUM_CONSTANT(DISABLED);
}

GFXButtonStateTexture::GFXButtonStateTexture() : button_state { HOVER } {}

Ref<GFXButtonStateTexture> GFXButtonStateTexture::make_gfx_button_state_texture(
   ButtonState button_state, Ref<Image> const& source_image
) {
   Ref<GFXButtonStateTexture> button_state_texture;
   button_state_texture.instantiate();
   ERR_FAIL_NULL_V(button_state_texture, nullptr);
   button_state_texture->set_button_state(button_state);
   if (source_image.is_valid()) {
      ERR_FAIL_COND_V(button_state_texture->generate_state_image(source_image) != OK, nullptr);
   }
   return button_state_texture;
}

void GFXButtonStateTexture::set_button_state(ButtonState new_button_state) {
   ERR_FAIL_COND(new_button_state != HOVER && new_button_state != PRESSED && new_button_state != DISABLED);
   button_state = new_button_state;
}

Error GFXButtonStateTexture::generate_state_image(Ref<Image> const& source_image) {
   ERR_FAIL_COND_V(source_image.is_null() || source_image->is_empty(), FAILED);
   /* Whether we've already set the ImageTexture to an image of the right dimensions and format,
   * and so can update it without creating and setting a new image, or not. */
   const bool can_update = state_image.is_valid() && state_image->get_size() == source_image->get_size()
      && state_image->get_format() == source_image->get_format();
   if (!can_update) {
      state_image = Image::create(source_image->get_width(), source_image->get_height(), false, source_image->get_format());
      ERR_FAIL_NULL_V(state_image, FAILED);
   }

   static constexpr auto hover_colour = [](Color const& colour) -> Color {
      return { std::min(colour.r + 0.1f, 1.0f), std::min(colour.g + 0.1f, 1.0f), std::min(colour.b + 0.1f, 1.0f), colour.a };
   };
   static constexpr auto pressed_colour = [](Color const& colour) -> Color {
      return { std::max(colour.r - 0.1f, 0.0f), std::max(colour.g - 0.1f, 0.0f), std::max(colour.b - 0.1f, 0.0f), colour.a };
   };
   static constexpr auto disabled_colour = [](Color const& colour) -> Color {
      const float luma = colour.get_luminance();
      return { luma, luma, luma, colour.a };
   };

   const auto colour_func = button_state == HOVER ? hover_colour : button_state == PRESSED ? pressed_colour : disabled_colour;

   for (Vector2i point { 0, 0 }; point.y < state_image->get_height(); ++point.y) {
      for (point.x = 0; point.x < state_image->get_width(); ++point.x) {
         state_image->set_pixelv(point, colour_func(source_image->get_pixelv(point)));
      }
   }

   if (can_update) {
      update(state_image);
   } else {
      set_image(state_image);
   }
   return OK;
}

StringName const& GFXButtonStateTexture::get_generate_state_image_func_name() {
   static const StringName generate_state_image_func_name = "generate_state_image";
   return generate_state_image_func_name;
}

StringName const& GFXButtonStateTexture::button_state_to_theme_name(ButtonState button_state) {
   static const StringName theme_name_hover = "hover";
   static const StringName theme_name_pressed = "pressed";
   static const StringName theme_name_disabled = "disabled";
   static const StringName theme_name_error = "";
   switch (button_state) {
      case HOVER:
         return theme_name_hover;
      case PRESSED:
         return theme_name_pressed;
      case DISABLED:
         return theme_name_disabled;
      default:
         return theme_name_error;
   }
}

StringName const& GFXButtonStateTexture::get_button_state_theme() const {
   return button_state_to_theme_name(button_state);
}