Download CommonLua/X/XCurveEditor.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 21.2 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/X/XCurveEditor.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/X/XCurveEditor.lua
-
curl -L -o XCurveEditor.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/X/XCurveEditor.lua
21.2 kB
| local max_curve_points = 8 | |
| DefineClass.XCurveEditor = { | |
| __parents = { "XControl", "XActionsHost" }, | |
| properties = { | |
| { category = "General", id = "ControlPoints", editor = "number", default = 4, min = 2, max = max_curve_points, }, | |
| { category = "General", id = "MaxX", editor = "number", default = 1000, min = 1 }, | |
| { category = "General", id = "MinX", editor = "number", default = 0, min = 1 }, | |
| { category = "General", id = "MaxY", editor = "number", default = 1000, min = 1 }, | |
| { category = "General", id = "MinY", editor = "number", default = 0 }, | |
| { category = "General", id = "DisplayScaleX", editor = "number", default = 1000, min = 1, help = "Used for displaying numbers around the graph" }, | |
| { category = "General", id = "DisplayScaleY", editor = "number", default = 1000, min = 1, help = "Used for displaying numbers around the graph"}, | |
| { category = "General", id = "SnapX", editor = "number", default = 1, min = 1 }, | |
| { category = "General", id = "SnapY", editor = "number", default = 1, min = 1 }, | |
| { category = "General", id = "FixedX", editor = "bool", default = false }, | |
| { category = "General", id = "PushPointsOnMove", editor = "bool", default = true, }, | |
| { category = "General", id = "CurveColor", editor = "color", default = RGB(0,0,0), }, | |
| { category = "General", id = "ControlPointMaxDist", editor = "number", default = 25, }, | |
| { category = "General", id = "ControlPointColor", editor = "color", default = RGB(80, 80, 80), }, | |
| { category = "General", id = "ControlPointCaptureColor", editor = "color", default = RGB(0,0,0), }, | |
| { category = "General", id = "ControlPointHoverColor", editor = "color", default = RGB(130, 130, 130), }, | |
| { category = "General", id = "GridUnitX", editor = "number", default = 100, }, | |
| { category = "General", id = "GridUnitY", editor = "number", default = 100, }, | |
| { category = "General", id = "GridColor", editor = "color", default = RGB(180, 180, 180), }, | |
| { category = "General", id = "Smooth", editor = "bool", default = true, }, | |
| { category = "General", id = "ReadOnly", editor = "bool", default = false, }, | |
| { category = "General", id = "MinMaxRangeMode", editor = "bool", defalt = false, help = "Stores the /Min/ Value in point.z" }, | |
| }, | |
| OnCurveChanged = false, | |
| point_handles = false, | |
| capture_handle = false, | |
| hover_handle = false, | |
| points = false, | |
| scale_texts = false, | |
| font_id = false, | |
| text_space_required = false, | |
| MinMaxRangeMode = false, | |
| } | |
| -- debug helpers | |
| for i = 1, max_curve_points do | |
| local xname = "x" .. i | |
| local yname = "y" .. i | |
| table.insert(XCurveEditor.properties, { | |
| category = "General", id = xname, editor = "number", min = 0, default = 0, | |
| max = function(obj) return obj.MaxX end, slider = true, --read_only = true, | |
| no_edit = function(obj) return i > obj.ControlPoints end, | |
| }) | |
| table.insert(XCurveEditor.properties, { | |
| category = "General", id = yname, editor = "number", min = 0, default = 0, | |
| max = function(obj) return obj.MaxY end, slider = true, --read_only = true, | |
| no_edit = function(obj) return i > obj.ControlPoints end, | |
| }) | |
| XCurveEditor["Get" .. xname] = function(obj) return obj.points[i]:x() end | |
| XCurveEditor["Get" .. yname] = function(obj) return obj.points[i]:y() end | |
| XCurveEditor["Set" .. xname] = function(obj, value) obj:MovePoint(i, obj.points[i]:SetX(value)) end | |
| XCurveEditor["Set" .. yname] = function(obj, value) obj:MovePoint(i, obj.points[i]:SetY(value)) end | |
| end | |
| function XCurveEditor:GeneratePointUIElements() | |
| self.point_handles = {} | |
| for idx, pt in pairs(self.points) do | |
| local main_handle = XCurveEditorHandle:new({ | |
| point_idx = idx, | |
| curve_editor = self, | |
| }) | |
| table.insert(self.point_handles, main_handle) | |
| if self.MinMaxRangeMode then | |
| local handle = XCurveEditorMinHandle:new({ | |
| point_idx = idx, | |
| curve_editor = self, | |
| parent = main_handle, | |
| }) | |
| table.insert(self.point_handles, handle) | |
| handle = XCurveEditorMaxHandle:new({ | |
| point_idx = idx, | |
| curve_editor = self, | |
| parent = main_handle, | |
| }) | |
| table.insert(self.point_handles, handle) | |
| end | |
| end | |
| end | |
| function XCurveEditor:GetRange() | |
| return point(self.MaxX - self.MinX, self.MaxY - self.MinY, self.MaxY - self.MinY) | |
| end | |
| function XCurveEditor:GetRangeMin() | |
| return point(self.MinX, self.MinY, self.MinY) | |
| end | |
| function XCurveEditor:GetRangeMax() | |
| return point(self.MaxX, self.MaxY, self.MaxY) | |
| end | |
| function XCurveEditor:Init() | |
| self.points = { } | |
| local max_points = self.ControlPoints - 1 | |
| local range = self:GetRange() | |
| assert(range:x() > 0 and range:y() > 0) | |
| for i = 0, max_points do | |
| local y = i * range:y() / max_points | |
| table.insert(self.points, point(i * range:x() / max_points, y, y)) | |
| end | |
| self:GeneratePointUIElements() | |
| end | |
| function XCurveEditor:GetControlPointSize() | |
| return point(ScaleXY(self.scale, 10, 10)) | |
| end | |
| function XCurveEditor:GetGraphBox() | |
| local control_size = self:GetControlPointSize() | |
| local topleft_padding = control_size / 2 | |
| local bottomright_padding = control_size / 2 | |
| local text_space_required = self.text_space_required | |
| if text_space_required then | |
| bottomright_padding = point(Max(text_space_required:x(), bottomright_padding:x()), Max(text_space_required:y(), bottomright_padding:y())) | |
| end | |
| return box(self.content_box:min() + topleft_padding, self.content_box:max() - bottomright_padding) | |
| end | |
| function XCurveEditor:TransformPoint(pos) | |
| local draw_box = self:GetGraphBox() | |
| local ranges = self:GetRange() | |
| local base = point(draw_box:minx(), draw_box:maxy()) | |
| pos = pos - self:GetRangeMin() | |
| pos = point(pos:x(), -pos:y()) | |
| return base + MulDivRoundPoint(draw_box:size(), pos, ranges) | |
| end | |
| local function FitScaleTexts(min_value, max_value, display_scale, size_getter, available_space, min_space_between) | |
| local begin_text = FormatNumberProp(min_value, display_scale, 2) | |
| local end_text = FormatNumberProp(max_value, display_scale, 2) | |
| local text_list = {} | |
| local secondary_axis_length = 0 | |
| local function subdivide(left_value, right_value, left_pos, right_pos) | |
| left_pos = left_pos + min_space_between | |
| right_pos = right_pos - min_space_between | |
| local diff = right_pos - left_pos | |
| if diff <= 10 then -- do not attempt to add text if we have less than 10 pixels | |
| return | |
| end | |
| local target_value = (left_value + right_value) / 2 | |
| local text = FormatNumberProp(target_value, display_scale, 2) | |
| local size, secondary_len = size_getter(text) | |
| if size > diff then | |
| return | |
| end | |
| secondary_axis_length = Max(secondary_axis_length, secondary_len) | |
| table.insert(text_list, text) | |
| local mid = left_pos + diff / 2 | |
| table.insert(text_list, mid - size / 2) | |
| subdivide(left_value, target_value, left_pos, mid - size / 2) | |
| subdivide(target_value, right_value, mid + size / 2, right_pos) | |
| end | |
| local begin_text_size, secondary_len1 = size_getter(begin_text) | |
| local end_text_size, secondary_len2 = size_getter(end_text) | |
| secondary_axis_length = Max(secondary_axis_length, Max(secondary_len1, secondary_len2)) | |
| table.insert(text_list, begin_text) | |
| table.insert(text_list, 0) | |
| subdivide(min_value, max_value, 0, available_space) | |
| table.insert(text_list, end_text) | |
| table.insert(text_list, available_space - end_text_size) | |
| return text_list, secondary_axis_length | |
| end | |
| function XCurveEditor:Layout(x, y, width, height) | |
| local ret = XWindow.Layout(self, x, y, width, height) | |
| self:GenerateTexts() | |
| return ret | |
| end | |
| function XCurveEditor:GenerateTexts() | |
| self.font_id = TextStyles.GedDefault:GetFontIdHeightBaseline(self.scale:y()) | |
| self.text_space_required = point(0, 0) | |
| local _, font_height = UIL.MeasureText("AQj", self.font_id) | |
| local vertical_texts, min_width = FitScaleTexts(self.MinY, self.MaxY, self.DisplayScaleY, function(str) | |
| local width, height = UIL.MeasureText(str, self.font_id) | |
| return height, width | |
| end, self.content_box:sizey() - font_height, 10) | |
| local horizontal_texts = FitScaleTexts(0, self.MaxX, self.DisplayScaleX, function(str) | |
| local width, height = UIL.MeasureText(str, self.font_id) | |
| return width, height | |
| end, self.content_box:sizex() - min_width, 10) | |
| self.text_space_required = point(min_width, font_height) | |
| local graph_box = self:GetGraphBox() | |
| local content_box_min = self.content_box:min() | |
| self.scale_texts = {} | |
| for i = 2, #vertical_texts, 2 do | |
| local start_pos = point(graph_box:maxx(), graph_box:maxy() - vertical_texts[i] - font_height) - content_box_min | |
| vertical_texts[i] = sizebox(start_pos, point(UIL.MeasureText(vertical_texts[i - 1], self.font_id))) | |
| end | |
| for i = 2, #horizontal_texts, 2 do | |
| local start_pos = point(graph_box:minx() + horizontal_texts[i], graph_box:maxy()) - content_box_min | |
| horizontal_texts[i] = sizebox(start_pos, point(UIL.MeasureText(horizontal_texts[i - 1], self.font_id))) | |
| end | |
| table.iappend(vertical_texts, horizontal_texts) | |
| self.scale_texts = vertical_texts | |
| end | |
| local function min_point(a, b) | |
| return point(Min(a:x(), b:x()), Min(a:y(), b:y()), Min(a:z(), b:z())) | |
| end | |
| local function max_point(a, b) | |
| return point(Max(a:x(), b:x()), Max(a:y(), b:y()), Max(a:z(), b:z())) | |
| end | |
| function XCurveEditor:MovePoint(index, pos) | |
| local z = pos:z() | |
| assert(z and type(z) == "number") | |
| local points = self.points | |
| assert(index >= 1 and index <= self.ControlPoints and index <= #points) | |
| local old_pos = points[index] | |
| local min_pos = self:GetRangeMin() | |
| local max_pos = self:GetRangeMax() | |
| if self.FixedX or index == 1 or index == #points then | |
| min_pos = min_pos:SetX(old_pos:x()) | |
| max_pos = max_pos:SetX(old_pos:x()) | |
| end | |
| if not self.PushPointsOnMove then | |
| if index > 1 then | |
| min_pos = max_point(min_pos, points[index - 1]) | |
| end | |
| if index < #point then | |
| max_pos = min_point(max_pos, points[index + 1]) | |
| end | |
| end | |
| pos = point((pos:x() + self.SnapX / 2) / self.SnapX * self.SnapX, | |
| (pos:y() + self.SnapY / 2) / self.SnapY * self.SnapY, | |
| (pos:z() + self.SnapY / 2) / self.SnapY * self.SnapY) | |
| pos = min_point(max_point(pos, min_pos), max_pos) | |
| points[index] = pos | |
| if self.PushPointsOnMove and not self.FixedX then | |
| for i = 1, index - 1 do | |
| if points[i]:x() > pos:x() then | |
| points[i] = points[i]:SetX(pos:x()) | |
| end | |
| end | |
| for i = index + 1, #points do | |
| if points[i]:x() < pos:x() then | |
| points[i] = points[i]:SetX(pos:x()) | |
| end | |
| end | |
| end | |
| if self.OnCurveChanged and old_pos ~= pos then | |
| self.OnCurveChanged(self) | |
| self:Invalidate() | |
| end | |
| return pos | |
| end | |
| function XCurveEditor:OnMouseButtonDown(pt, button) | |
| if button == "L" then | |
| self.capture_handle = self.hover_handle | |
| self:SetFocus() | |
| self.desktop:SetMouseCapture(self) | |
| self:OnMousePos(pt) | |
| return "break" | |
| end | |
| end | |
| function XCurveEditor:OnSetRollover(rollover) | |
| XControl.OnSetRollover(self, rollover) | |
| if not rollover then | |
| self.hover_handle = false | |
| self:Invalidate() | |
| end | |
| end | |
| function XCurveEditor:OnMouseButtonUp(pt, button) | |
| if button == "L" then | |
| self.capture_handle = false | |
| self:OnMousePos(pt) | |
| self.desktop:SetMouseCapture() | |
| self:Invalidate() | |
| return "break" | |
| end | |
| end | |
| function XCurveEditor:GetHoveredHandle(pt) | |
| local handles = self.point_handles | |
| local best_handle = -1 | |
| local best_dist = 999999 | |
| for i, handle in ipairs(handles) do | |
| local dist = handle:HoverScore(self:TransformPoint(handle:GetPos()), pt) | |
| if dist < best_dist then | |
| best_handle = handle | |
| best_dist = dist | |
| end | |
| end | |
| local max_dist = ScaleXY(self.scale, self.ControlPointMaxDist) | |
| if best_dist < max_dist * max_dist then | |
| return best_handle | |
| end | |
| return false | |
| end | |
| function XCurveEditor:OnMousePos(pt) | |
| local old_hover = self.hover_handle | |
| self.hover_handle = self:GetHoveredHandle(pt) | |
| if old_hover ~= self.hover_handle then | |
| self:Invalidate() | |
| end | |
| if self.desktop:GetMouseCapture() ~= self then | |
| self.capture_handle = false | |
| return "break" | |
| end | |
| if not self.capture_handle then | |
| return "break" | |
| end | |
| if self.ReadOnly then | |
| return "break" | |
| end | |
| local content_box = self:GetGraphBox() | |
| local pos = self:GetRangeMin() + MulDivRoundPoint(point(pt:x() - content_box:minx(), content_box:maxy() - pt:y()), self:GetRange(), content_box:size()) | |
| self.capture_handle:SetPos(pos) | |
| return "break" | |
| end | |
| local function RoundUp(x, alignment) | |
| if x % alignment == 0 then return x end | |
| return (x / alignment) * alignment + alignment | |
| end | |
| function XCurveEditor:DrawGrid() | |
| local range = self:GetRange() | |
| local max_values = self:GetRangeMax() | |
| local min_values = self:GetRangeMin() | |
| if self.GridUnitX > 0 then | |
| for x = RoundUp(min_values:x(), self.GridUnitX), max_values:x(), self.GridUnitX do | |
| UIL.DrawLine(self:TransformPoint(point(x, min_values:y())), self:TransformPoint(point(x, max_values:y())), self.GridColor) | |
| end | |
| end | |
| if self.GridUnitY > 0 then | |
| for y = RoundUp(min_values:y(), self.GridUnitY), max_values:y(), self.GridUnitY do | |
| UIL.DrawLine(self:TransformPoint(point(min_values:x(), y)), self:TransformPoint(point(max_values:x(), y)), self.GridColor) | |
| end | |
| end | |
| end | |
| function XCurveEditor:DrawControlPoints() | |
| local graph_box = self:GetGraphBox() | |
| local base = point(graph_box:minx(), graph_box:maxy()) | |
| local points = self.points | |
| local size = self:GetControlPointSize() / 2 | |
| for idx = 1, #self.point_handles do | |
| local handle = self.point_handles[idx] | |
| local color = self.ControlPointColor | |
| if handle:IsCaptured() then | |
| color = self.ControlPointCaptureColor | |
| elseif handle:IsHovered() then | |
| color = self.ControlPointHoverColor | |
| end | |
| local pixel_pos = self:TransformPoint(handle:GetPos(true)) | |
| handle:Draw(graph_box, base, size, color, pixel_pos) | |
| end | |
| end | |
| function XCurveEditor:DrawGraphBackground(graph_box, points) | |
| end | |
| function XCurveEditor:DrawScaleTexts() | |
| --display current value whiel dragging | |
| if self.capture_handle then | |
| local pos = self.capture_handle:GetPos() | |
| local graph_box = self:GetGraphBox() | |
| local x_pos_text = FormatNumberProp(pos:x(), self.DisplayScaleX, 2) | |
| local x_pos_text_size = point(UIL.MeasureText(x_pos_text, self.font_id)) | |
| local y_pos_text = FormatNumberProp(pos:y(), self.DisplayScaleY, 2) | |
| local y_pos_text_size = point(UIL.MeasureText(y_pos_text, self.font_id)) | |
| local pixel_pos = self:TransformPoint(pos) | |
| local draw_text_x = Min(Max(pixel_pos:x() - x_pos_text_size:x() / 2, 0), graph_box:maxx() - x_pos_text_size:x()) | |
| UIL.StretchText(x_pos_text, sizebox(point(draw_text_x, graph_box:maxy()), x_pos_text_size), self.font_id, self.CurveColor) | |
| local draw_text_y = Min(Max(pixel_pos:y() - x_pos_text_size:y() / 2, 0), graph_box:maxy() - x_pos_text_size:y()) | |
| UIL.StretchText(y_pos_text, sizebox(point(graph_box:maxx(), draw_text_y), y_pos_text_size), self.font_id, self.CurveColor) | |
| return | |
| end | |
| local content_box_min = self.content_box:min() | |
| -- draw static texts. Cached and recalcualted only when needed as we might need to do more complex logic to decide out what to render and where | |
| local texts = self.scale_texts | |
| if not texts then | |
| self:GenerateTexts() | |
| texts = self.scale_texts | |
| end | |
| if texts then | |
| local StretchText = UIL.StretchText | |
| for i = 1, #texts, 2 do | |
| StretchText(texts[i], Offset(texts[i + 1], content_box_min), self.font_id, self.CurveColor) | |
| end | |
| end | |
| end | |
| local function DrawCurveWithPoints(smooth, points, color) | |
| if smooth then | |
| local step = 3 | |
| local last_pt = points[1] | |
| for i = 1, #points - 1 do | |
| local left_pt_prev = points[i - 1] or points[i] | |
| local left_pt = points[i] | |
| local right_pt = points[i + 1] | |
| local diff_x = right_pt:x() - left_pt:x() | |
| local right_pt_next = points[i + 2] or points[i + 1] | |
| for x = left_pt:x() + step, right_pt:x(), step do | |
| --TODO: Use some other sample func | |
| local pt = CatmullRomSpline(left_pt_prev, left_pt, right_pt, right_pt_next, MulDivRound(x - left_pt:x(), 1000, diff_x ), 1000) | |
| pt = pt:SetX(x) | |
| UIL.DrawLine(last_pt, pt, color) | |
| last_pt = pt | |
| end | |
| end | |
| else | |
| local last_pt = points[1] | |
| for i = 2, #points do | |
| local pt = points[i] | |
| UIL.DrawLine(last_pt, pt, color) | |
| last_pt = pt | |
| end | |
| end | |
| end | |
| function XCurveEditor:DrawCurve() | |
| assert(self.points[1]:z()) | |
| local graph = self:GetGraphBox() | |
| local points = {} | |
| for key, value in ipairs(self.points) do | |
| points[key] = self:TransformPoint(value) | |
| end | |
| DrawCurveWithPoints(self.Smooth, points, self.CurveColor) | |
| if self.MinMaxRangeMode then | |
| points = {} | |
| for key, value in ipairs(self.points) do | |
| points[key] = self:TransformPoint(point(value:x(), value:z())) | |
| end | |
| DrawCurveWithPoints(self.Smooth, points, self.CurveColor) | |
| end | |
| UIL.DrawLine(point(graph:maxx(), graph:miny()), graph:max(), self.CurveColor) | |
| UIL.DrawLine(point(graph:minx(), graph:maxy()), graph:max(), self.CurveColor) | |
| end | |
| function XCurveEditor:DrawContent() | |
| local graph_box = self:GetGraphBox() | |
| self:DrawGraphBackground(graph_box, self.points) | |
| self:DrawGrid() | |
| self:DrawCurve() | |
| self:DrawControlPoints() | |
| self:DrawScaleTexts() | |
| end | |
| function XCurveEditor:ValidatePoints() | |
| for i = 1, #self.points do | |
| local pt = self.points[i] | |
| self.points[i] = max_point(min_point(pt, self:GetRangeMax()), self:GetRangeMin()) | |
| end | |
| self.points[1] = self.points[1]:SetX(self.MinX) | |
| self.points[#self.points] = self.points[#self.points]:SetX(self.MaxX) | |
| end | |
| ------------ XCurveEditorHandle ------------- | |
| -- Spec of movable UI elements in the graph | |
| DefineClass.XCurveEditorHandle = { | |
| __parents = {"PropertyObject"}, | |
| type = false, | |
| point_idx = false, | |
| curve_editor = false, | |
| box = false, | |
| parent = false, | |
| } | |
| function XCurveEditorHandle:SetPos(pt) | |
| local old_pt = self.curve_editor.points[self.point_idx] | |
| local height = (old_pt:z() - old_pt:y()) / 2 | |
| local new_point = point(pt:x(), pt:y() - height, pt:y() + height) | |
| self.curve_editor:MovePoint(self.point_idx, new_point) | |
| return self:GetPos("refetch") | |
| end | |
| function XCurveEditorHandle:GetPos(refetch) | |
| local pt = self.curve_editor.points[self.point_idx] | |
| return point(pt:x(), (pt:y() + pt:z()) / 2) | |
| end | |
| function XCurveEditorHandle:GetBox() | |
| local old_pt = self.curve_editor.points[self.point_idx] | |
| if self.curve_editor.MinMaxRangeMode then | |
| local height = (old_pt:z() - old_pt:y()) | |
| local height_in_pixels = MulDivRound(height, self.curve_editor:GetGraphBox():sizey(), self.curve_editor:GetRange():y()) | |
| local half_control_point_width = self.curve_editor:GetControlPointSize():x() / 4 | |
| local pixel_pos = self.curve_editor:TransformPoint(old_pt) | |
| self.box = box(point(pixel_pos:x() - half_control_point_width, pixel_pos:y() - height_in_pixels), | |
| point(pixel_pos:x() + half_control_point_width, pixel_pos:y())) | |
| else | |
| local half_control_point_width = self.curve_editor:GetControlPointSize():x() / 2 | |
| local pixel_pos = self.curve_editor:TransformPoint(old_pt) | |
| self.box = box(point(pixel_pos:x() - half_control_point_width, pixel_pos:y() - half_control_point_width), | |
| point(pixel_pos:x() + half_control_point_width, pixel_pos:y() + half_control_point_width)) | |
| end | |
| return self.box | |
| end | |
| function XCurveEditorHandle:HoverScore(self_pt, mouse_pt) | |
| if terminal.IsKeyPressed(const.vkShift) then | |
| return 1000000 | |
| end | |
| local is = self:GetBox():Intersect(box(mouse_pt - point(10, 10), mouse_pt + point(10, 10))) | |
| if is ~= const.irOutside then | |
| return 0 | |
| end | |
| return mouse_pt:Dist2(self_pt) | |
| end | |
| function XCurveEditorHandle:Draw(graph_box, base, size, color, pixel_pos) | |
| UIL.DrawSolidRect(self:GetBox(), color) | |
| end | |
| DefineClass.XCurveEditorMinHandle = { | |
| __parents = {"XCurveEditorHandle"}, | |
| } | |
| function XCurveEditorMinHandle:SetPos(pt) | |
| local old_pt = self.curve_editor.points[self.point_idx] | |
| local new_pt = point(pt:x(), Min(pt:y(), old_pt:z()), old_pt:z()) | |
| self.curve_editor:MovePoint(self.point_idx, new_pt) | |
| return self:GetPos("refetch") | |
| end | |
| function XCurveEditorHandle:IsCaptured() | |
| local capture = self.curve_editor.capture_handle | |
| local current = self | |
| while current do | |
| if capture == current then return true end | |
| current = current.parent | |
| end | |
| return false | |
| end | |
| function XCurveEditorHandle:IsHovered() | |
| local capture = self.curve_editor.hover_handle | |
| local current = self | |
| while current do | |
| if capture == current then return true end | |
| current = current.parent | |
| end | |
| return false | |
| end | |
| function XCurveEditorMinHandle:GetPos(refetch) | |
| local pt = self.curve_editor.points[self.point_idx] | |
| return point(pt:x(), pt:y()) | |
| end | |
| function XCurveEditorMinHandle:HoverScore(self_pt, mouse_pt) | |
| return mouse_pt:Dist2(self_pt) | |
| end | |
| function XCurveEditorMinHandle:Draw(graph_box, base, size, color, pixel_pos) | |
| UIL.DrawSolidRect(box(pixel_pos - size, pixel_pos + size), color) | |
| end | |
| DefineClass.XCurveEditorMaxHandle = { | |
| __parents = {"XCurveEditorHandle"}, | |
| } | |
| function XCurveEditorMaxHandle:SetPos(pt) | |
| local old_pt = self.curve_editor.points[self.point_idx] | |
| local new_pt = point(pt:x(), old_pt:y(), Max(pt:y(), old_pt:y())) | |
| self.curve_editor:MovePoint(self.point_idx, new_pt) | |
| return self:GetPos("refetch") | |
| end | |
| function XCurveEditorMaxHandle:GetPos(refetch) | |
| local pt = self.curve_editor.points[self.point_idx] | |
| return point(pt:x(), pt:z()) | |
| end | |
| function XCurveEditorMaxHandle:HoverScore(self_pt, mouse_pt) | |
| return mouse_pt:Dist2(self_pt) | |
| end | |
| function XCurveEditorMaxHandle:Draw(graph_box, base, size, color, pixel_pos) | |
| UIL.DrawSolidRect(box(pixel_pos - size, pixel_pos + size), color) | |
| end | |
| DefineClass.TestPicker = { | |
| __parents = {"PropertyObject"}, | |
| properties = { | |
| {id = "test1", editor = "packedcurve", default = PackCurveParams(point(0, 127000), point(40000, 0), point(80000, 255000), point(255000, 0)),} | |
| } | |
| } | |