godot-cpp icon indicating copy to clipboard operation
godot-cpp copied to clipboard

class Gradient is missing a function 'get_color_at_offset'.

Open RonYanDaik opened this issue 2 years ago • 3 comments

Function get_color_at_offset exists in gradient.h of engine but is missing in gradient.hpp of extension.

RonYanDaik avatar Apr 26 '23 06:04 RonYanDaik

Also _update_sorting() is missing.

RonYanDaik avatar Apr 26 '23 06:04 RonYanDaik

I see why its missing. Struct Point is unexposed. I had to recreate function like this:

class Gradient2 : public Gradient
{
	GDCLASS(Gradient2 , Gradient)
public:
	static void _bind_methods(){};

	struct Point
	{
		Color color;
		double offset;
	};
	
    _FORCE_INLINE_ Color get_color_at_offset(float p_offset) {
    	
		if (!get_point_count()) {
			return Color(0, 0, 0, 1);
		}
    	
		//_update_sorting();

		// Binary search.
		int low = 0;
		int high = get_point_count() - 1;
		int middle = 0;

#ifdef DEBUG_ENABLED
		if (low > high) {
			ERR_PRINT("low > high, this may be a bug");
		}
#endif

		while (low <= high) {
			middle = (low + high) / 2;
			const double &offset = get_offset(middle);
			if (offset > p_offset) {
				high = middle - 1; //search low end of array
			} else if (offset < p_offset) {
				low = middle + 1; //search high end of array
			} else {
				return get_color(middle);
			}
		}

		// Return sampled value.
		if (get_offset(middle) > p_offset) {
			middle--;
		}
		int first = middle;
		int second = middle + 1;
		if (second >= get_point_count()) {
			return get_color(get_point_count() - 1);
		}
		if (first < 0) {
			return get_color(0);
		}
    	
		const Point &pointFirst = GetPoint(first);
		const Point &pointSecond = GetPoint(second);

		switch (get_interpolation_mode()) {
			case GRADIENT_INTERPOLATE_LINEAR: {
				return pointFirst.color.lerp(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset));
			} break;
			case GRADIENT_INTERPOLATE_CONSTANT: {
				return pointFirst.color;
			} break;
			case GRADIENT_INTERPOLATE_CUBIC: {
				int p0 = first - 1;
				int p3 = second + 1;
				if (p3 >= get_point_count()) {
					p3 = second;
				}
				if (p0 < 0) {
					p0 = first;
				}
				const Point &pointP0 = GetPoint(p0);
				const Point &pointP3 = GetPoint(p3);

				float x = (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset);
				float r = Math::cubic_interpolate(pointFirst.color.r, pointSecond.color.r, pointP0.color.r, pointP3.color.r, x);
				float g = Math::cubic_interpolate(pointFirst.color.g, pointSecond.color.g, pointP0.color.g, pointP3.color.g, x);
				float b = Math::cubic_interpolate(pointFirst.color.b, pointSecond.color.b, pointP0.color.b, pointP3.color.b, x);
				float a = Math::cubic_interpolate(pointFirst.color.a, pointSecond.color.a, pointP0.color.a, pointP3.color.a, x);

				return Color(r, g, b, a);
			} break;
			default: {
				// Fallback to linear interpolation.
				return pointFirst.color.lerp(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset));
			}
		}
	}
	Point GetPoint(int32_t p)
    {
	    return {get_color(p),get_offset(p)};
    }
};

RonYanDaik avatar Apr 26 '23 07:04 RonYanDaik

Maybe Struct Point could be moved to public field and then exposed?

RonYanDaik avatar Jun 30 '23 12:06 RonYanDaik