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

Applying images to a surface, rotation and different surfaces?

Asked by
Edenojack 171
8 years ago

Visual example, youtube

Brief: We click on an object's front surface, and it applies a ImageLabel centered around the mouse. The size is constant on all different sizes.

Problem 2: I can't apply this to all surfaces, I've already got the Surface's Normal being returned, but from there on, I don't know how to apply this information.

Here is me code:

local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local Texture = "http://www.roblox.com/asset/?id=82021756"
local Sizer = 20


function Positioning(part,hitpos)
    local PixelRef = part.CFrame:toObjectSpace(CFrame.new(hitpos))--*CFrame.new(-part.Size.X/2,-part.Size.Y/2,0)
    local XRef = -PixelRef.p.X-- -math.ceil(PixelRef.X) If we want this to be applied on a stud=pixel scale (Messes up positions)
    local YRef = -PixelRef.p.Y-- -math.ceil(PixelRef.Y)
    return XRef,YRef
end

function click()
    local target = mouse.Target
    if target then
        local mRay = mouse.UnitRay
        local ray = Ray.new( mRay.Origin, mRay.Direction * 100 )
        local part, pos, normal = game.Workspace:FindPartOnRay( ray, player.Character )
        if part then
            print(part.Name,pos,normal)
            local surface
            local frame
            if part:findFirstChild("SurfaceGui") then
                surface = part:findFirstChild("SurfaceGui")
                frame = surface.Framey
            else
                print("Found none")
                surface = Instance.new( "SurfaceGui", part)
                surface.CanvasSize = Vector2.new(part.Size.X*10,part.Size.Y*10)
                frame = Instance.new("Frame", surface)
                frame.Name = "Framey"
                frame.Size = UDim2.new(1,0,1,0)
                frame.ClipsDescendants = true
                frame.BackgroundTransparency =1 
            end
            local Tex = Instance.new("ImageLabel",frame)
            Tex.Image = Texture
            Tex.Size = UDim2.new(0,Sizer,0,Sizer)
            Tex.BackgroundTransparency = 1
            local X,Y = Positioning(part,pos)
            print(X,Y)
            Tex.Position = UDim2.new(.5+(X/(part.Size.X)),-Sizer/2,.5+(Y/(part.Size.Y)),-Sizer/2)
        end
    end
end

mouse.Button1Down:connect(click)

I've figured out where I was going wrong with the application, but I don't understand how I need to edit this to apply to other surfaces.

1 answer

Log in to vote
0
Answered by
Edenojack 171
8 years ago

Kept running into problems, but this one works, all Parts (Including wedges and corners, however it will only work on the FLAT parts of this surface, it does not produce a Face value for the slopes)

Hopefully I'll be able to add more things to this, such as removing overlapping pictures and converting them into one big image, similairly, this would be cool for growing puddles. This would look really cool for explosions

I'm also fairly interested in getting these to wrap around corners, or be spread over multiple moving bricks (pretty sure there was a Snack Break problem about this).

In the meantime however, feel free to use the code. First applications I can think of are bullet holes and splats, but I'm sure someone can think of some more interesting applications. Here ya go!

local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local Texture = "http://www.roblox.com/asset/?id=82021756"--<Your image or whatever
local PicSize = 20 --How many "pixels" the image is (Always square shape)
local CanSize = 10 --10 pixels offset, unless replacing the Picture for something made of frames, not necessary to change


function Positioning(part,hitpos)
    local PixelRef
    return -PixelRef.p
end

function ReturnNormal(PartCF,RayNorm)
    if PartCF.lookVector - RayNorm == Vector3.new(0,0,0) then
        return "Front",5
    elseif PartCF.lookVector + RayNorm == Vector3.new(0,0,0) then
        return "Back",2
    else
        local x, y, z, R00, R01, R02, R10, R11, R12, R20, R21, R22 = PartCF:components()
        if Vector3.new(R01,R11,R21) == RayNorm then
            return"Top", 1
        elseif Vector3.new(-R01,-R11,-R21) == RayNorm then
            return "Bottom",4
        elseif Vector3.new(-R00,-R10,-R20) == RayNorm then
            return "Left",3
        elseif Vector3.new(R00,R10,R20) == RayNorm then
            return "Right",0
        end
    end
end

function click()
    local target = mouse.Target
    if target then
        local mRay = mouse.UnitRay
        local ray = Ray.new( mRay.Origin, mRay.Direction * 100 )
        local part, pos, normal = game.Workspace:FindPartOnRay( ray, player.Character )
        if part then
            local SizeWidth = part.Size.X
            local SizeHeight = part.Size.Y
            local Face,Val = ReturnNormal(part.CFrame,normal)
            print(Face,Val)
            if Face == nil then
                return
            end
            if Face == "Top" or Face == "Bottom" then
                SizeWidth = part.Size.Z
                SizeHeight = part.Size.X
            elseif Face == "Right" or Face == "Left" then
                SizeWidth = part.Size.Z
                SizeHeight = part.Size.Y
            end
            local surface
            local frame
                for _,i in pairs(part:GetChildren()) do
                    if i:IsA("SurfaceGui") then
                        if i.Face == Val then
                            surface = part:findFirstChild("SurfaceGui")
                            frame = surface.Framey
                        end
                    end
                end
            if surface == nil then
                surface = Instance.new("SurfaceGui", part)
                surface.CanvasSize = Vector2.new(SizeWidth*CanSize,SizeHeight*CanSize)
                surface.Face = Val
                frame = Instance.new("Frame", surface)
                frame.Name = "Framey"
                frame.Size = UDim2.new(1,0,1,0)
                frame.ClipsDescendants = true
                frame.BackgroundTransparency =1 
            end
            local Tex = Instance.new("ImageLabel",frame)
            Tex.Image = Texture
            Tex.Size = UDim2.new(0,PicSize,0,PicSize)
            Tex.BackgroundTransparency = 1
            local Size = -(part.CFrame:toObjectSpace(CFrame.new(pos))).p
            if Face == "Front" then
                Tex.Position = UDim2.new(.5+(Size.X/(SizeWidth)),-PicSize/2,.5+(Size.Y/(SizeHeight)),-PicSize/2)
            elseif Face == "Back" then
                Tex.Position = UDim2.new(.5+(-Size.X/(SizeWidth)),-PicSize/2,.5+(Size.Y/(SizeHeight)),-PicSize/2)
            elseif Face == "Right" then
                Tex.Position = UDim2.new(.5+(Size.Z/(SizeWidth)),-PicSize/2,.5+(Size.Y/(SizeHeight)),-PicSize/2)
            elseif Face == "Left" then
                Tex.Position = UDim2.new(.5+(-Size.Z/(SizeWidth)),-PicSize/2,.5+(Size.Y/(SizeHeight)),-PicSize/2)
            elseif Face == "Top" then
                Tex.Position = UDim2.new(.5+(Size.Z/(SizeWidth)),-PicSize/2,.5+(-Size.X/(SizeHeight)),-PicSize/2)
            elseif Face == "Bottom" then
                Tex.Position = UDim2.new(.5+(Size.Z/(SizeWidth)),-PicSize/2,.5+(Size.X/(SizeHeight)),-PicSize/2)
            end
        end
    end
end

mouse.Button1Down:connect(click)
Ad

Answer this question