-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 48bd9bc
Showing
78 changed files
with
9,159 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"name": "draggerframework", | ||
"tree": { | ||
"$path": "src" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.