Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
stravant committed Sep 5, 2023
0 parents commit 48bd9bc
Show file tree
Hide file tree
Showing 78 changed files with 9,159 additions and 0 deletions.
6 changes: 6 additions & 0 deletions default.project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "draggerframework",
"tree": {
"$path": "src"
}
}
97 changes: 97 additions & 0 deletions src/Components/AnimatedHoverBox.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
--[[
Displays an animated SelectionBox adornment on the hovered Workspace object.
]]

-- Services
local RunService = game:GetService("RunService")
local HttpService = game:GetService("HttpService")

local DraggerFramework = script.Parent.Parent
local Packages = DraggerFramework.Parent
local Roact = require(Packages.Roact)

local ANIMATED_HOVER_BOX_UPDATE_BIND_NAME = "AnimatedHoverBoxUpdate"
local MODEL_LINE_THICKNESS_SCALE = 2.5

local getFFlagDraggerFrameworkFixes = require(DraggerFramework.Flags.getFFlagDraggerFrameworkFixes)

--[[
Return a hover color that is a blend between the Studio settings HoverOverColor
and SelectColor, based on the current time and HoverAnimateSpeed.
]]
local function getHoverColorForTime(color1, color2, animatePeriod, currentTime)
local alpha = 0.5 + 0.5 * math.sin(currentTime / animatePeriod * math.pi)
return color2:lerp(color1, alpha)
end

local AnimatedHoverBox = Roact.PureComponent:extend("AnimatedHoverBox")

function AnimatedHoverBox:init(initialProps)
assert(initialProps.HoverTarget, "Missing required property 'HoverTarget'.")
assert(initialProps.SelectColor, "Missing required property 'SelectColor'.")
assert(initialProps.HoverColor, "Missing required property 'HoverColor'.")
assert(initialProps.LineThickness, "Missing required property 'LineThickness'.")
assert(initialProps.SelectionBoxComponent, "Missing required property 'SelectionBoxComponent'.")

self:setState({
currentColor = getHoverColorForTime(
self.props.SelectColor, self.props.HoverColor, self.props.AnimatePeriod or math.huge, 0),
})

self._isMounted = false
self._startTime = 0

if getFFlagDraggerFrameworkFixes() then
local guid = HttpService:GenerateGUID(false)
self._bindName = ANIMATED_HOVER_BOX_UPDATE_BIND_NAME .. "_" .. guid
end
end

function AnimatedHoverBox:didMount()
self._isMounted = true
self._startTime = tick()

local bindName = getFFlagDraggerFrameworkFixes() and self._bindName or ANIMATED_HOVER_BOX_UPDATE_BIND_NAME
RunService:BindToRenderStep(bindName, Enum.RenderPriority.First.Value, function()
if self._isMounted then
local deltaT = tick() - self._startTime
self:setState({
currentColor = getHoverColorForTime(
self.props.SelectColor, self.props.HoverColor, self.props.AnimatePeriod or math.huge, deltaT)
})
end
end)
end

function AnimatedHoverBox:willUnmount()
self._isMounted = false

local bindName = getFFlagDraggerFrameworkFixes() and self._bindName or ANIMATED_HOVER_BOX_UPDATE_BIND_NAME
RunService:UnbindFromRenderStep(bindName)
end

function AnimatedHoverBox:render()
if not self.props.HoverTarget then
return nil
end

local lineThickness = self.props.LineThickness
if self.props.HoverTarget:IsA("Model") then
lineThickness = lineThickness * MODEL_LINE_THICKNESS_SCALE
end

--return Roact.createElement(self.props.SelectionBoxComponent, {
-- Adornee = self.props.HoverTarget,
-- Color3 = self.state.currentColor,
-- LineThickness = lineThickness,
--})
return Roact.createElement("Highlight", {
Adornee = self.props.HoverTarget,
OutlineColor = self.state.currentColor,
OutlineTransparency = 0,
FillColor = self.state.currentColor,
FillTransparency = 1,
})
end

return AnimatedHoverBox
75 changes: 75 additions & 0 deletions src/Components/DragSelectionView.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
--[[
Component that displays a rubber band-style selection frame.
]]

local GuiService = game:GetService("GuiService")

local DraggerFramework = script.Parent.Parent
local Packages = DraggerFramework.Parent
local Roact = require(Packages.Roact)

-- Utilities
local Colors = require(DraggerFramework.Utility.Colors)

local DragSelectionView = Roact.PureComponent:extend("DragSelectionView")

DragSelectionView.defaultProps = {
BackgroundColor3 = Colors.BLACK,
BackgroundTransparency = 1,
BorderColor3 = Colors.GRAY,
}

function DragSelectionView:init(initialProps)
assert(initialProps.DragStartLocation, "Missing required property 'DragStartLocation'.")
assert(initialProps.DragEndLocation, "Missing required property 'DragEndLocation'.")
end

function DragSelectionView:render()
local min = self.props.DragStartLocation
local max = self.props.DragEndLocation
if not min or not max then
return nil
end

-- Adjust by GUI inset
local topInset = GuiService:GetGuiInset()

local rect = Rect.new(min - topInset, max - topInset)

return Roact.createElement("ScreenGui", {}, {
Roact.createElement("Frame", {
Position = UDim2.new(0, rect.Min.X, 0, rect.Min.Y),
Size = UDim2.new(0, rect.Width, 0, rect.Height),
BackgroundColor3 = self.props.BackgroundColor3,
BackgroundTransparency = self.props.BackgroundTransparency,
BorderSizePixel = 0,
}, {
Left = Roact.createElement("Frame", {
Size = UDim2.new(0, 1, 1, 0),
BackgroundColor3 = self.props.BorderColor3,
BorderSizePixel = 0,
}),
Top = Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 0, 1),
BackgroundColor3 = self.props.BorderColor3,
BorderSizePixel = 0,
}),
Right = Roact.createElement("Frame", {
AnchorPoint = Vector2.new(1, 0),
Position = UDim2.new(1, 0, 0, 0),
Size = UDim2.new(0, 1, 1, 0),
BackgroundColor3 = self.props.BorderColor3,
BorderSizePixel = 0,
}),
Bottom = Roact.createElement("Frame", {
AnchorPoint = Vector2.new(0, 1),
Position = UDim2.new(0, 0, 1, 0),
Size = UDim2.new(1, 0, 0, 1),
BackgroundColor3 = self.props.BorderColor3,
BorderSizePixel = 0,
}),
})
})
end

return DragSelectionView
21 changes: 21 additions & 0 deletions src/Components/DraggedPivot.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
local Workspace = game:GetService("Workspace")

local DraggerFramework = script.Parent.Parent
local Plugin = DraggerFramework.Parent.Parent
local Roact = require(Plugin.Packages.Roact)

local MAIN_SPHERE_RADIUS = 0.4
local MAIN_SPHERE_TRANSPARENCY = 0.5

return function(props)
local handleScale = props.DraggerContext:getHandleScale(props.CFrame.Position)
return Roact.createElement("SphereHandleAdornment", {
Adornee = Workspace.Terrain,
CFrame = props.CFrame,
Radius = handleScale * MAIN_SPHERE_RADIUS,
ZIndex = 0,
AlwaysOnTop = false,
Transparency = MAIN_SPHERE_TRANSPARENCY,
Color3 = props.DraggerContext:getSelectionBoxColor(props.IsActive),
})
end
115 changes: 115 additions & 0 deletions src/Components/LocalSpaceIndicator.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
--[[
Component that displays an "L" label near the bottom-right corner of the
passed in bounding volume.
]]

local DraggerFramework = script.Parent.Parent
local Packages = DraggerFramework.Parent
local Roact = require(Packages.Roact)

local PADDING = 3

local LocalSpaceIndicator = Roact.Component:extend("LocalSpaceIndicator")

LocalSpaceIndicator.defaultProps = {
BackgroundTransparency = 1,
Font = Enum.Font.ArialBold,
TextSize = 16,
TextColor3 = Color3.new(1, 1, 1),
TextStrokeColor3 = Color3.new(0, 0, 0),
TextStrokeTransparency = 0,
}

function LocalSpaceIndicator:init(initialProps)
assert(initialProps.CFrame, "Missing required proprty CFrame")
assert(initialProps.Size, "Missing required proprty Size")
assert(initialProps.DraggerContext, "Missing required proprty DraggerContext")
end

function LocalSpaceIndicator:render()
local props = self.props

local draggerContext = props.DraggerContext
local cframe = props.CFrame
local halfSize = props.Size / 2

-- Compute the bounding box corners in object space.
local max = halfSize
local min = -halfSize

local corners = {
Vector3.new(min.X, min.Y, min.Z),
Vector3.new(min.X, max.Y, min.Z),
Vector3.new(min.X, max.Y, max.Z),
Vector3.new(min.X, min.Y, max.Z),
Vector3.new(max.X, min.Y, min.Z),
Vector3.new(max.X, max.Y, min.Z),
Vector3.new(max.X, max.Y, max.Z),
Vector3.new(max.X, min.Y, max.Z),
}

local projectedCorners = {}
local optimalX, optimalY = -math.huge, -math.huge

-- Find the optimal screen position for the label. This will be the maximum
-- of all the points.
for i = 1, #corners do
-- For each projected corner record whether it is onscreen, but use the
-- point for the optimal point calculation regardless. Not using all of
-- the bounding volume corners can cause the "L" indicator to jump around
-- when the bounding volume is partly outside the viewport.
local worldPoint = cframe:PointToWorldSpace(corners[i])
local screenPoint, onScreen = draggerContext:worldToViewportPoint(worldPoint)
local point = Vector2.new(screenPoint.X, screenPoint.Y)

table.insert(projectedCorners, {
point = point,
onScreen = onScreen,
})

optimalX = math.max(optimalX, point.X)
optimalY = math.max(optimalY, point.Y)
end

-- Take the projected point closest to the optimal point to use as the
-- position of the label.
local optimalPoint = Vector2.new(optimalX, optimalY)
local minDistanceToOptimal = math.huge
local isProjectedCornerOnScreen = false
local position

for i = 1, #projectedCorners do
local screenPoint = projectedCorners[i].point
local distanceToOptimal = (screenPoint - optimalPoint).Magnitude
if distanceToOptimal < minDistanceToOptimal then
minDistanceToOptimal = distanceToOptimal
position = screenPoint
isProjectedCornerOnScreen = projectedCorners[i].onScreen
end
end

if not isProjectedCornerOnScreen then
return nil
end

-- Label size calculation is an approximation to avoid using TextService
-- to measure a single-character string.
local labelSize = props.TextSize + PADDING * 2

return Roact.createElement("ScreenGui", {}, {
Roact.createElement("TextLabel", {
BackgroundTransparency = props.BackgroundTransparency,
Position = UDim2.fromOffset(position.X, position.Y),
Size = UDim2.fromOffset(labelSize, labelSize),
Font = props.Font,
TextSize = props.TextSize,
Text = "L",
TextColor3 = props.TextColor3,
TextStrokeColor3 = props.TextStrokeColor3,
TextStrokeTransparency = props.TextStrokeTransparency,
Selectable = false,
})
})
end

return LocalSpaceIndicator
Loading

0 comments on commit 48bd9bc

Please sign in to comment.