Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
6

Transforming 2D point to 2D object-space [closed]

Asked by
MrNicNac 855 Moderation Voter
10 years ago

I have a plugin, GUI Studio, and I want to add support for rotated GUIs. Right now, I'm trying to position pseudo-resize handles (just other GUIs) on the left/top/bottom/right sides of the GUI no matter it's rotation.

I will present the Left handle code. The issue I am having is that it is slightly below the center of the left side (imagine the left side of a GUI and it rotated and now imagine where you could see a resize-handle at the center of that side). It's not there, and always ends up slightly below the correct point.

Here is how I find the direction from the rotation

function GetGuiDirection(x, gui)
    local rotation;
    if x == "Left" then
        rotation = math.rad(gui.Rotation+270)
    elseif x == "Top" then
        rotation = math.rad(gui.Rotation)
    elseif x == "Right" then
        rotation = math.rad(gui.Rotation+90)
    elseif x == "Bottom" then
        rotation = math.rad(180+gui.Rotation)
    end
    return Vector2.new((math.sin(rotation)), (math.cos(rotation)))
end

And here is how I am positioning the LEFT resize handle:

local left_direction = GetGuiDirection("Left", gui_x)

local solvedx = ((posx+sizex/2)-rhandle.AbsoluteSize.X) + ((sizex/2) * left_direction.x)
local solvedy = ((posy+sizey/2)-rhandle.AbsoluteSize.Y/2) - ((sizex/2) * left_direction.y)
print(((posy+sizey/2)-rhandle.AbsoluteSize.Y/2), " - ", ((sizex/2) * left_direction.y))

left.Position = UDim2.new(0,solvedx,0,solvedy);

Just notice that the math in the first set of parenthesis on the solve_ variables is just to get the center of whatever GUI is currently selected. In general, everything is correct and it gets positioned in the same relative-coordinates no matter the rotation/size. It's just that it is slightly below (on the Y axis) where it should be.

Does anyone have any experience with this sort of math and can explain a solution - or the problem?

Locked by Thewsomeguy and Articulating

This question has been locked to preserve its current state and prevent spam and unwanted comments and answers.

Why was this question closed?

1 answer

Log in to vote
6
Answered by
blocco 185
10 years ago

GUI objects in ROBLOX are positioned based on their top-left coordinates when they're not rotated, and they're rotated based on their center coordinates. This can cause some problems when figuring out where things are rendered.

Center Coordinates

Since GUI objects are rotated around their center coordinates, I decided to make a function that told me where the center coordinates are:

local function GetCenterOfGuiObject(guiObject)
    return Vector2.new(
        guiObject.AbsolutePosition.x + guiObject.AbsoluteSize.x/2,
        guiObject.AbsolutePosition.y + guiObject.AbsoluteSize.y/2
    )
end

Center of Edges

Having this function, we can now focus on finding the centers of the edges, which we can then use to determine the placements of the handles. Things to note:

  • The rotations go clockwise instead of the natural counterclockwise.
  • The y axis is flipped; as you go down, the y-ordinate gets bigger instead of smaller.
  • As a GUI object rotates, the center of each edge stays the same distance away from the center of the GUI object; the center of each edge draws a circle around the GUI object as it moves.

Keeping these things in mind, I wrote a simple function to help me determine where the edges of any GUI object would be:

local function GetCenterOfEdge(guiObject, edge)
    local center = GetCenterOfGuiObject(guiObject);
    local size = guiObject.AbsoluteSize;
    local rotation = math.rad(guiObject.Rotation);
    if edge == "Left" then
        size = Vector2.new(size.x, size.x) -- moves like a circle
        rotation = rotation - math.pi;
    elseif edge == "Top" then
        size = Vector2.new(size.y, size.y)
        rotation = rotation - math.pi/2;
    elseif edge == "Right" then
        size = Vector2.new(size.x, size.x)
        rotation = rotation;
    elseif edge == "Bottom" then
        size = Vector2.new(size.y, size.y)
        rotation = rotation + math.pi/2;
    end
    rotation = -rotation; -- clockwise
    return center + (size/2) * Vector2.new(
        math.cos(rotation),
        -math.sin(rotation) -- to fix flipped y-axis
    )
end

Now that we know the centers of any edge, we can easily position the top-left of our handles relative to that. I'm sure you can figure out how to do that, however. :P

1
The results I'm getting are not very close to the center of any of the edges using your code. With the Y value being the most "off." MrNicNac 855 — 10y
0
My bad. The X coordinate seems rather fine (mine was as well); but, again like mine, the Y coordinate is very off. MrNicNac 855 — 10y
0
How are you using my code? I'm getting the center of the edge each time I call the function. blocco 185 — 10y
0
UDim2.new(0,centerofedge.x-rhandle.AbsoluteSize.X/2,0,centerofedge.y-rhandle.AbsoluteSize.Y/2); -> As the GUI's size increases, the accuracy of the Y coordinate decreases. What factor am I missing? MrNicNac 855 — 10y
View all comments (13 more)
0
Ah yes... I was testing my code on a square. I should have tested it on a rectangle. I see what's going on. I'll try to figure it out. blocco 185 — 10y
0
I have fixed it, and edited my answer accordingly. blocco 185 — 10y
0
Heh....I still regret to say that I am getting the _exact_ same result as my code gave me. The position of the handle (I am testing the left face) is still slightly below where it show be. Could this be a rounding error or something similar? MrNicNac 855 — 10y
0
Here (http://i.imgur.com/lnH7IgW.png) is an image of what is happening (only pay attention to the left-side handle at the moment) MrNicNac 855 — 10y
0
Is your image centered? blocco 185 — 10y
0
Yes. I have actually found a temporary solution of adding/subtracting (depending on which handle) 5 pixels. Works flawlessly. I just don't know where the 5 pixel amount comes from. The image is centered and takes up the entire canvas. MrNicNac 855 — 10y
0
I lied :( It only worked when the GUI rotation was < 90 or >-90 MrNicNac 855 — 10y
0
I tried the code and I got [this](http://i.imgur.com/Sxz0H0K.png). I used handle.Position = UDim2.new(0, centerOfEdge.x - handle.AbsoluteSize.x/2, 0, centerOfEdge.y - handle.AbsoluteSize.y/2); too. Maybe you're doing something with the result that is changing the way it looks for you. blocco 185 — 10y
0
Have you tried using your code at 90 degrees? (http://i.imgur.com/EY1EzLl.png?1) I am adjusting nothing and using the exact code you gave me this time. MrNicNac 855 — 10y
0
I'm to the point where I'll go ahead and give you the whole RBXM plugin if you think you could fix it. This issue is beyond my frustration threshold. MrNicNac 855 — 10y
0
I tried it at 90 degrees http://imgur.com/M0I7Toy blocco 185 — 10y
0
I quit MrNicNac 855 — 10y
0
frickedy frick stephan. Why cant anyone talk to you D: ConnorVIII 448 — 10y
Ad