File: //opt/resolve/Developer/Fusion Fuse/Arrow.fuse
-- Cut From Here
--[[--
Arrow.Fuse
Draws an Arrow between 2 points.
--]]--
FuRegisterClass("Arrow", CT_Tool, { --Minimal Fu Registry class definition
REGS_Category = "Fuses\\Examples",
REGS_OpIconString = "Arw",
REGS_OpDescription = "Arrow Shape Tool",
})
function Create()
-- Point controls are 2D used for on screen manipulation returning 2 values X and Y
InHead = self:AddInput("Head", "Head", { --UI Label, Internal Ref
LINKID_DataType = "Point", -- Retrurns 2 values X and Y
INPID_InputControl = "OffsetControl", -- Type of Control
INPID_PreviewControl = "CrosshairControl", -- Display Control Type
INP_DefaultX = 0.5,
INP_DefaultY = 0.5,
})
InTail = self:AddInput("Tail", "Tail", { --UI Label, Internal Ref
LINKID_DataType = "Point",
INPID_InputControl = "OffsetControl", -- Type of Control
INPID_PreviewControl = "CrosshairControl",
-- CHC_Style = "DiagonalCross", -- Change the Crosshair to a X diagonal cross
PC_GrabPriority = -1, -- When multiple crosshair are togther in the view, Grab Priority is used to choose which gets picked. The higher the priority is picked first
INP_DefaultX = 0.75,
INP_DefaultY = 0.75,
})
InHPosition = self:AddInput( "Head Position", "HPos", {
LINKID_DataType = "Number",
INPID_InputControl = "SliderControl",
INP_MaxAllowed = 1.0, -- Sets the default Maximum scale of the slider
INP_MinAllowed = 0.0, --Sets the default Minimum scale for the slider
INP_Default = 1.0, -- Sets default value for the slider
INP_MinScale = 0.2,
})
self:BeginControlNest("Shading", "ShadingNest", true); -- Control Nests group controls with a togglable collapse/expand function
InR = self:AddInput("Arrow Red", "Red", { --UI Label, Internal Ref
ICS_Name = "Arrow Color",
LINKID_DataType = "Number",
INPID_InputControl = "ColorControl", -- Type of Control
INP_Default = 1.0,
INP_MaxScale = 1.0,
CLRC_ShowWheel = false,
IC_ControlGroup = 2, --Groups Controls together. Make Group number it 2
IC_ControlID = 0,
})
InG = self:AddInput("Arrow Green", "Green", { --UI Label, Internal Ref
LINKID_DataType = "Number",
INPID_InputControl = "ColorControl", -- Type of Control
INP_Default = 0.9,
IC_ControlGroup = 2, -- Put this into a Group and number it 2
IC_ControlID = 1,
})
InB = self:AddInput("Arrow Blue", "Blue", {--UI Label, Internal Ref
LINKID_DataType = "Number",
INPID_InputControl = "ColorControl", -- Type of Control
INP_Default = 0.6,
IC_ControlGroup = 2, -- Put this into a Group and number it 2
IC_ControlID = 2,
})
-- Notify change is a seperate class function that will be called when controls are changed, see below for the Notify change function.
InNotifyOutline = self:AddInput("Outline On", "NotifyO", {
LINKID_DataType = "Number",
INPID_InputControl = "CheckboxControl",
INP_Integer = true,
INP_Default = 1.0,
INP_DoNotifyChanged = true, -- We want to hear about changes on this control
})
InRo = self:AddInput("Outline Red", "Redout", { --UI Label, Internal Ref
ICS_Name = "Outline Color",
LINKID_DataType = "Number",
INPID_InputControl = "ColorControl", -- Type of Control
INP_Default = 1.0,
INP_MaxScale = 1.0,
CLRC_ShowWheel = false,
IC_ControlGroup = 3, --Groups Controls together. Make Group number it 2
IC_ControlID = 0,
})
InGo = self:AddInput("Outline Green", "Greenout", { --UI Label, Internal Ref
LINKID_DataType = "Number",
INPID_InputControl = "ColorControl", -- Type of Control
INP_Default = 1.0,
IC_ControlGroup = 3, -- Put this into a Group and number it 2
IC_ControlID = 1,
})
InBo = self:AddInput("Outline Blue", "Blueout", {--UI Label, Internal Ref
LINKID_DataType = "Number",
INPID_InputControl = "ColorControl", -- Type of Control
INP_Default = 1.0,
IC_ControlGroup = 3, -- Put this into a Group and number it 2
IC_ControlID = 2,
})
InNotifyShadow = self:AddInput("Shadow On", "NotifyS", {
LINKID_DataType = "Number",
INPID_InputControl = "CheckboxControl",
INP_Integer = true,
INP_Default = 1.0,
INP_DoNotifyChanged = true, -- We want to hear about changes on this control
})
InRs = self:AddInput("Shadow Red", "Reds", { --UI Label, Internal Ref
ICS_Name = "Shadow Color",
LINKID_DataType = "Number",
INPID_InputControl = "ColorControl", -- Type of Control
INP_Default = 0.0,
INP_MaxScale = 1.0,
CLRC_ShowWheel = false,
IC_ControlGroup = 4, --Groups Controls together. Make Group number it 2
IC_ControlID = 0,
})
InGs = self:AddInput("Shadow Green", "Greens", { --UI Label, Internal Ref
LINKID_DataType = "Number",
INPID_InputControl = "ColorControl", -- Type of Control
INP_Default = 0.0,
IC_ControlGroup = 4, -- Put this into a Group and number it 2
IC_ControlID = 1,
})
InBs = self:AddInput("Shadow Blue", "Blues", {--UI Label, Internal Ref
LINKID_DataType = "Number",
INPID_InputControl = "ColorControl", -- Type of Control
INP_Default = 0.0,
IC_ControlGroup = 4, -- Put this into a Group and number it 2
IC_ControlID = 2,
})
InAs = self:AddInput("Shadow Alpha", "Alphas", {--UI Label, Internal Ref
LINKID_DataType = "Number",
INPID_InputControl = "ColorControl", -- Type of Control
INP_Default = 0.5,
IC_ControlGroup = 4, -- Put this into a Group and number it 2
IC_ControlID = 3,
})
self:EndControlNest()
self:AddControlPage("Arrow") -- Name the new Tab Control page
self:BeginControlNest("Arrow Shape", "ArrowShape", true); -- Control Nests group controls with a togglable collapse/expand function
InArrowWidth = self:AddInput( "Arrow Width", "ArrowWidth", {
LINKID_DataType = "Number",
INPID_InputControl = "SliderControl",
INP_MaxAllowed = 1.0, -- Sets the default Maximum scale of the slider
INP_MinAllowed = 0.0, --Sets the default Minimum scale for the slider
INP_MaxScale = 0.02,
INP_Default = 0.01, -- Sets default value for the slider
})
InArrowHeight = self:AddInput( "Arrow Height", "ArrowHeight", {
LINKID_DataType = "Number",
INPID_InputControl = "SliderControl",
INP_MaxAllowed = 1.0, -- Sets the default Maximum scale of the slider
INP_MinAllowed = 0.0, --Sets the default Minimum scale for the slider
INP_MaxScale = 0.1,
INP_Default = 0.04, -- Sets default value for the slider
})
InShaftWidth = self:AddInput( "Shaft Width", "ShaftWidth", {
LINKID_DataType = "Number",
INPID_InputControl = "SliderControl",
INP_MaxAllowed = 1.0, -- Sets the default Maximum scale of the slider
INP_MinAllowed = 0.0, --Sets the default Minimum scale for the slider
INP_MaxScale = 0.01,
INP_Default = 0.005, -- Sets default value for the slider
})
self:EndControlNest()
self:BeginControlNest("Outline Settings", "Outlinesettings", true); -- Control Nests group controls with a togglable collapse/expand function
InThickness = self:AddInput("Outline Thickness", "Thickness", {
LINKID_DataType = "Number",
INPID_InputControl = "SliderControl",
INP_MaxAllowed = 0.1, -- Sets the default Maximum scale of the slider
INP_MinAllowed = 0.0, --Sets the default Minimum scale for the slider
INP_MaxScale = 0.004,
INP_Default = 0.002, -- Sets default value for the slider
})
-- Notify change is a seperate class function that will be called when controls are changed, see below for the Notify change function.
InNotifyOutline2 = self:AddInput("Outline Solid", "NotifyO2", {
LINKID_DataType = "Number",
INPID_InputControl = "CheckboxControl",
INP_Integer = true,
INP_Default = 1.0,
INP_DoNotifyChanged = true, -- We want to hear about changes on this control
})
self:EndControlNest()
self:BeginControlNest("Shadow Settings", "ShadowSettings", true); -- Control Nests group controls with a togglable collapse/expand function
InShadowOff = self:AddInput("Shadow Offset", "ShadowOff", {
LINKID_DataType = "Number",
INPID_InputControl = "SliderControl",
INP_MaxAllowed = 0.1, -- Sets the default Maximum scale of the slider
INP_MinAllowed = 0.0, --Sets the default Minimum scale for the slider
INP_MaxScale = 0.02,
INP_Default = 0.01, -- Sets default value for the slider
})
InShadowTilt = self:AddInput("Shadow Tilt", "ShadowTilt", {
LINKID_DataType = "Number",
INPID_InputControl = "SliderControl",
INP_MaxAllowed = 90, -- Sets the default Maximum scale of the slider
INP_MinAllowed = 0.0, --Sets the default Minimum scale for the slider
INP_MaxScale = 45,
INP_Default = 0.0, -- Sets default value for the slider
})
self:EndControlNest()
InImage = self:AddInput("Input", "Input", {
LINKID_DataType = "Image",
LINK_Main = 1,
})
OutImage = self:AddOutput("Output", "Output", {
LINKID_DataType = "Image",
LINK_Main = 1,
})
end
-- Notify Changed is used to Hide or Show controls when options are selected in the Tool's control inspector
function NotifyChanged(inp, param, time)
if inp == InNotifyOutline then -- If Notify Change check box is changed, then rename the Control names and Un/Hide sliders
local locked = (param.Value > 0.5)
if locked then
InRo:SetAttrs({ IC_Visible = true })
InGo:SetAttrs({ IC_Visible = true })
InBo:SetAttrs({ IC_Visible = true })
InNotifyOutline:SetAttrs({ LINKS_Name = "Outline On" })
else
InRo:SetAttrs({ IC_Visible = false })
InGo:SetAttrs({ IC_Visible = false })
InBo:SetAttrs({ IC_Visible = false })
InNotifyOutline:SetAttrs({ LINKS_Name = "Outline Off" })
end
end
if inp == InNotifyShadow then -- If Notify Change check box is changed, then rename the Control names and Un/Hide sliders
local locked = (param.Value > 0.5)
if locked then
InRs:SetAttrs({ IC_Visible = true })
InGs:SetAttrs({ IC_Visible = true })
InBs:SetAttrs({ IC_Visible = true })
InAs:SetAttrs({ IC_Visible = true })
InNotifyShadow:SetAttrs({ LINKS_Name = "Shadow On" })
else
InRs:SetAttrs({ IC_Visible = false })
InGs:SetAttrs({ IC_Visible = false })
InBs:SetAttrs({ IC_Visible = false })
InAs:SetAttrs({ IC_Visible = false })
InNotifyShadow:SetAttrs({ LINKS_Name = "Shadow Off" })
end
end
if inp == InNotifyOutline2 then -- If Notify Change check box is changed, then rename the Control names and Un/Hide sliders
local locked = (param.Value > 0.5)
if locked then
InNotifyOutline2:SetAttrs({ LINKS_Name = "Outline Solid" })
else
InNotifyOutline2:SetAttrs({ LINKS_Name = "Outline Dotted" })
end
end
end
function Process(req)
local img = InImage:GetValue(req)
local out = img:CopyOf()
local thickness = InThickness:GetValue(req).Value
local shadow = InShadowOff:GetValue(req).Value
local headoffset = InHPosition:GetValue(req).Value
local shadowtilt = InShadowTilt:GetValue(req).Value
local r = InR:GetValue(req).Value
local g = InG:GetValue(req).Value
local b = InB:GetValue(req).Value
local ro = InRo:GetValue(req).Value
local go = InGo:GetValue(req).Value
local bo = InBo:GetValue(req).Value
local rs = InRs:GetValue(req).Value
local gs = InGs:GetValue(req).Value
local bs = InBs:GetValue(req).Value
local as = InAs:GetValue(req).Value
local notifyo = InNotifyOutline:GetValue(req).Value
local notifyo2 = InNotifyOutline2:GetValue(req).Value
local notifys = InNotifyShadow:GetValue(req).Value
local ic = ImageChannel(out, 8) -- Image Channel
local fs = FillStyle() -- Fill Style Object
local cs = ChannelStyle() -- Channel Style
local mat = Matrix4() -- Matrix to transform the shapes
local csrect=cs -- copy of the basic ChannelStyle
local fsrect=fs -- copy of the basic FillStyle
local icrect = ic
local head = InHead:GetValue(req) -- This has 2 Outputs X & Y
local tail = InTail:GetValue(req) -- This has 2 Outputs X & Y
--Calculate Image aspect ratio to apply to coordinates
local hx=head.X
local tx=tail.X
local hy=head.Y
local ty=tail.Y
local aspect = img.Height / img.Width
hy = hy * aspect
ty = ty * aspect
-- Calculate Vector length and Angle
local length = math.sqrt(((hx-tx) ^2)+ ((hy-ty) ^2))
-- local angle = math.atan((hx-tx) / (hy-ty)) * -57.2957795 -- 360/ 2 Pi
local angle = (math.atan2((hy-ty),(hx-tx)) * 57.2957795) + 90-- 360/ 2 Pi
--Get Arrow measurements
local AW = InArrowWidth:GetValue(req).Value
local AH = InArrowHeight:GetValue(req).Value
local SW = InShaftWidth:GetValue(req).Value
local HO = (1.0 - headoffset) * length
-- Shape made of a group of line segments
local sh = Shape()
sh:MoveTo(0.0, HO)
sh:LineTo(AW, AH+HO)
sh:LineTo(SW, AH+HO)
sh:LineTo(SW, length)
sh:LineTo(-SW, length)
sh:LineTo(-SW, AH+HO)
sh:LineTo(-AW, AH+HO)
sh:LineTo(0.0, HO)
sh:Close() -- Close shape to the origin point
-- end shape
local sh2 = sh
local sh3 = sh -- make copies of the shape
--Drop Shadow Render
if notifys > 0 then
mat:Identity() -- Set the matrix to zero
mat:Scale(1.0, 1.0, 1.0) --Scale
mat:RotZ(angle) -- Rotate, Note the order of Matrix operations, Move has been applied before Rotation
mat:RotX(shadowtilt)
mat:Move(hx+shadow, hy-shadow, 0.0) -- Translate the Shape
cs.Color = Pixel{R=rs , G=gs , B=bs, A = as} -- Set the Color
cs.BlurType = "BT_Bartlett" -- BT_Box, BT_Bartlett, BT_MultiBox, BT_Gaussian
cs.SoftnessX = 1000.0 * shadow
cs.SoftnessY = 1000.0 * shadow
ic:SetStyleFill(fs) -- Set the Drawing application styles.
sh2 = sh2:TransformOfShape(mat) -- Transform Shape using the Matrix
ic:ShapeFill(sh2) --
ic:PutToImage("CM_Merge", cs)
end
--Main Arrow Render
mat:Identity() -- Set the matrix to zero
mat:Scale(1.0, 1.0, 1.0) --Scale
mat:RotZ(angle) -- Rotate, Note the order of Matrix operations, Move has been applied before Rotation
mat:Move(hx, hy, 0.0) -- Translate the Shape
cs.Color = Pixel{R=r , G=g , B=b, A = 1} -- Set the Color
cs.BlurType = "BT_Box" -- BT_Box, BT_Bartlett, BT_MultiBox, BT_Gaussian
cs.SoftnessX = 0.0
cs.SoftnessY = 0.0
ic:SetStyleFill(fs) -- Set the Drawing application styles.
sh = sh:TransformOfShape(mat) -- Transform Shape using the Matrix
ic:ShapeFill(sh) --
ic:PutToImage("CM_Merge", cs)
--Outline Render
if notifyo >0 then
if notifyo2 >0 then
sh3 = sh3:OutlineOfShape(thickness, "OLT_Solid", "OJT_Round", 8, "SWM_Normal", 8) -- Make the shape an outline
cs.Color = Pixel{R=ro , G=go , B=bo, A = 1} -- Set the Color
cs.BlurType = "BT_Box" -- BT_Box, BT_Bartlett, BT_MultiBox, BT_Gaussian
cs.SoftnessX = 0.0
cs.SoftnessY = 0.0
else
sh3 = sh3:OutlineOfShape(thickness, "OLT_Dot", "OJT_Round", 8, "SWM_Normal", 8) -- Make the shape an outline
cs.Color = Pixel{R=ro , G=go , B=bo, A = 1} -- Set the Color
cs.BlurType = "BT_Bartlett" -- BT_Box, BT_Bartlett, BT_MultiBox, BT_Gaussian
cs.SoftnessX = 0.0
cs.SoftnessY = 0.0
-- cs.SoftnessGlow = 0.95
-- cs.SoftnessBlend = 0.3
end
ic:SetStyleFill(fs) -- Set the Drawing application styles.
sh3 = sh3:TransformOfShape(mat) -- Transform Shape using the Matrix
ic:ShapeFill(sh3) --
ic:PutToImage("CM_Merge", cs)
end
OutImage:Set(req, out)
end
--End Cut
--
--