-- **************************************************
-- Provide Moho with the name of this script object
-- **************************************************

ScriptName = "MR_Guides"

-- **************************************************
-- General information about this script
-- **************************************************

MR_Guides = {}

function MR_Guides:Name()
	return self:Localize('UILabel')
end

function MR_Guides:Version()
	return '1.0'
end

function MR_Guides:UILabel()
	return self:Localize('UILabel')
end

function MR_Guides:Creator()
	return 'Eugene Babich'
end

function MR_Guides:Description()
	return self:Localize('Description')
end


-- **************************************************
-- Is Relevant / Is Enabled
-- **************************************************

function MR_Guides:IsRelevant(moho)
	return true
end

function MR_Guides:IsEnabled(moho)
	return true
end

function MR_Guides:SupportsGPUMode(moho)
	return false
end
-- **************************************************
-- Recurring Values
-- **************************************************

MR_Guides.createVGuidBtn = true
MR_Guides.createHGuidBtn = false
MR_Guides.moveGuideBtn = false
MR_Guides.deleteGuideBtn = false
MR_Guides.opacity = 100
MR_Guides.width = 1
MR_Guides.cursorVec = LM.Vector2:new_local()
MR_Guides.lastCursorVec = LM.Vector2:new_local()
MR_Guides.druggingMouse = false
MR_Guides.offset = LM.Vector2:new_local()
MR_Guides.guideColorR = 84
MR_Guides.guideColorG = 212
MR_Guides.guideColorB = 196
MR_Guides.guideColorA = 255
MR_Guides.guideStartPoint = nil
MR_Guides.guideEndPoint = nil
MR_Guides.direction = true

-- **************************************************
-- Prefs
-- **************************************************

function MR_Guides:LoadPrefs(prefs)
    self.createVGuidBtn = prefs:GetBool("MR_Guides.createVGuidBtn", true)
    self.createHGuidBtn = prefs:GetBool("MR_Guides.createHGuidBtn", false)
    self.moveGuideBtn = prefs:GetBool("MR_Guides.moveGuideBtn", false)
    self.deleteGuideBtn = prefs:GetBool("MR_Guides.deleteGuideBtn", false)
    self.opacity = prefs:GetInt("MR_Guides.opacity", 100)
    self.width = prefs:GetFloat("MR_Guides.width", 1)
	self.guideColorR = prefs:GetInt("MR_SelectedShapesOverlay.guideColorR", 84)
	self.guideColorG = prefs:GetInt("MR_SelectedShapesOverlay.guideColorG", 212)
	self.guideColorB = prefs:GetInt("MR_SelectedShapesOverlay.guideColorB", 196)
	self.guideColorB = prefs:GetInt("MR_SelectedShapesOverlay.guideColorA", 255)
end

function MR_Guides:SavePrefs(prefs)
    prefs:SetBool("MR_Guides.createVGuidBtn", self.createVGuidBtn)
    prefs:SetBool("MR_Guides.createHGuidBtn", self.createHGuidBtn)
    prefs:SetBool("MR_Guides.moveGuideBtn", self.moveGuideBtn)
    prefs:SetBool("MR_Guides.deleteGuideBtn", self.deleteGuideBtn)
    prefs:SetInt("MR_Guides.opacity", self.opacity)
    prefs:SetFloat("MR_Guides.width", self.width)
	prefs:SetInt("MR_SelectedShapesOverlay.strokeColorR", self.guideColorR)
	prefs:SetInt("MR_SelectedShapesOverlay.strokeColorG", self.guideColorG)
	prefs:SetInt("MR_SelectedShapesOverlay.strokeColorB", self.guideColorB)
	prefs:SetInt("MR_SelectedShapesOverlay.strokeColorA", self.guideColorA)
end

function MR_Guides:ResetPrefs()
    self.createVGuidBtn = true
    self.createHGuidBtn = false
    self.moveGuideBtn = false
    self.deleteGuideBtn = false
    self.opacity = 100
    self.width = 1
	self.guideColorR = 84
	self.guideColorG = 212
	self.guideColorB = 196
	self.guideColorA = 255
end

-- **************************************************
-- Keyboard/Mouse Control
-- **************************************************

function MR_Guides:OnMouseDown(moho, mouseEvent)
	self.curLayer = moho.layer
	self.curAction = moho.layer:CurrentAction()
	self.curFrame = moho.frame
	moho.document:PrepUndo(nil)
	moho.document:SetDirty()
	
	if self.moveGuideBtn then
		local topLayer = moho.document:Layer(moho.document:CountLayers()-1)
		local scriptData = topLayer:ScriptData()
		if (scriptData:HasKey("MR Guides Layer")) then
			self.guidesLayer = topLayer
			moho:SetSelLayer(self.guidesLayer)
			local mesh = moho:LayerAsVector(self.guidesLayer):Mesh()
			local shapesWidth = {}
			for i = 0, mesh:CountShapes() -1 do
				local shape = mesh:Shape(i)
				table.insert(shapesWidth, shape.fMyStyle.fLineWidth)
				shape.fMyStyle.fLineWidth = (10 / moho.document:Height())/moho.view:Graphics():CurrentScale()
			end
			local shapeID = mouseEvent.view:PickShape(mouseEvent.pt, -1, 5)
			for i = 0, mesh:CountShapes() -1 do
				local shape = mesh:Shape(i)
				shape.fMyStyle.fLineWidth = shapesWidth[i + 1]
			end	
			mesh:SelectNone()
			if shapeID >= 0 then
				local shape = mesh:Shape(shapeID)
				for i = 0, shape:CountEdges() - 1 do
					curveID, segID = shape:GetEdge(i, curveID, segID)
					local curve = mesh:Curve(curveID)
					curve:Point(0).fSelected = true
					curve:Point(1).fSelected = true
					self.guideStartPoint = curve:Point(0)
					self.guideEndPoint = curve:Point(1)
					self.guideStartPoint.fTempPos = self.guideStartPoint.fAnimPos:GetValue(0)
					self.guideEndPoint.fTempPos = self.guideEndPoint.fAnimPos:GetValue(0)
					if self.guideStartPoint.fAnimPos:GetValue(0).x ~= self.guideEndPoint.fAnimPos:GetValue(0).x then
						self.direction = false
					elseif self.guideStartPoint.fAnimPos:GetValue(0).y ~= self.guideEndPoint.fAnimPos:GetValue(0).y then
						self.direction = true
					end
					self:ReturnToAction(moho)
				end
			else
				self:ReturnToAction(moho)
				self.guideStartPoint = nil
				self.guideEndPoint = nil
				mesh:SelectNone()
				return
			end
		else
			return
		end
	end
	self.cursorVec:Set(self:GetGlobalPointPos(moho, mouseEvent.drawingVec, moho.layer))
end

function MR_Guides:OnMouseMoved(moho, mouseEvent)
	if self.createHGuidBtn or self.createVGuidBtn then
		self.druggingMouse = true
	end
	self.cursorVec:Set(self:GetGlobalPointPos(moho, mouseEvent.drawingVec, moho.layer))
	if self.moveGuideBtn then
		if self.guideStartPoint == nil or self.guideEndPoint == nil then
			return
		end
		self.offset:Set(self:GetGlobalPointPos(moho, mouseEvent.drawingVec, self.curLayer) - self:GetGlobalPointPos(moho, mouseEvent.drawingStartVec, self.curLayer))
		if self.direction then
			self.offset:Set(self.offset.x, 0)
		else
			self.offset:Set(0, self.offset.y)
		end	
		self.guideStartPoint.fPos = self.guideStartPoint.fTempPos + self.offset
		self.guideEndPoint.fPos = self.guideEndPoint.fTempPos + self.offset
		self.guideStartPoint.fAnimPos:SetValue(0, self.guideStartPoint.fTempPos + self.offset)
		self.guideEndPoint.fAnimPos:SetValue(0, self.guideEndPoint.fTempPos + self.offset)
	end
	mouseEvent.view:DrawMe()
end

function MR_Guides:OnMouseUp(moho, mouseEvent)
	local topLayer = moho.document:Layer(moho.document:CountLayers()-1)
	moho:SetSelLayer(topLayer)
	if self.createHGuidBtn or self.createVGuidBtn then
		self:CreateUpdateGuidsLayer(moho)
	elseif self.deleteGuideBtn then
		self:DeleteGuide(moho, mouseEvent)
	end
	self.druggingMouse = false
	if self.moveGuideBtn then
		self:ReturnToAction(moho)
	end
	self.lastCursorVec:Set(self.cursorVec)
	self.guidesLayer:UpdateCurFrame()
	self.curLayer:UpdateCurFrame()
	moho:UpdateUI()
	moho:UpdateSelectedChannels()
end

function MR_Guides:DrawMe(moho, view)
	local g = view:Graphics()
	local min = LM.Vector2:new_local()
	local max = LM.Vector2:new_local()
	local centerVec = LM.Vector2:new_local()
	local v = LM.Vector2:new_local()
	local color = LM.rgb_color:new_local()
	color.r = self.guideColorR
	color.g = self.guideColorG
	color.b = self.guideColorB
	color.a = self.guideColorA
	g:Push()
	if self.druggingMouse then
		local lineWidth = self.width
		lineWidth = LM.Clamp(lineWidth, 0.25, 256)
		g:SetPenWidth((lineWidth / 1.25) * g:CurrentScale())
		g:SetColor(color)
		g:SetSmoothing(true)
		if self.createVGuidBtn then
			g:DrawLine(-10/g:CurrentScale(), self.cursorVec.y, 10/g:CurrentScale(), self.cursorVec.y)
		elseif self.createHGuidBtn then
			g:DrawLine(self.cursorVec.x, -10/g:CurrentScale(), self.cursorVec.x, 10/g:CurrentScale())
		end	
	end
	g:Pop()
end

-- **************************************************
-- Tool Panel Layout
-- **************************************************

MR_Guides.CREATE_GUIDE_H = MOHO.MSG_BASE
MR_Guides.CREATE_GUIDE_V = MOHO.MSG_BASE + 1
MR_Guides.MOVE_GUIDE = MOHO.MSG_BASE + 2
MR_Guides.DELETE_GUIDE = MOHO.MSG_BASE + 3
MR_Guides.DELETE_LAST_GUIDE = MOHO.MSG_BASE + 4
MR_Guides.DELETE_GUIDES_LAYER = MOHO.MSG_BASE + 5
MR_Guides.OPACITY = MOHO.MSG_BASE + 6
MR_Guides.WIDTH = MOHO.MSG_BASE + 7
MR_Guides.COLOR = MOHO.MSG_BASE + 8
MR_Guides.VISIBILITY = MOHO.MSG_BASE + 9

function MR_Guides:DoLayout(moho, layout)
	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)

	self.createGuideHButton = LM.GUI.ImageButton('ScriptResources/mr_guides/mr_create_guide_h', self:Localize('Create Horizontal Guide'), true, self.CREATE_GUIDE_H, false)
    layout:AddChild(self.createGuideHButton, LM.GUI.ALIGN_LEFT, 0)

    self.createGuideVButton = LM.GUI.ImageButton('ScriptResources/mr_guides/mr_create_guide_v', self:Localize('Create Vertical Guide'), true, self.CREATE_GUIDE_V, false)
    layout:AddChild(self.createGuideVButton, LM.GUI.ALIGN_LEFT, 0)

    self.moveGuideButton = LM.GUI.ImageButton('ScriptResources/mr_guides/mr_move_guide', self:Localize('Move Existing Guide'), true, self.MOVE_GUIDE, false)
    layout:AddChild(self.moveGuideButton, LM.GUI.ALIGN_LEFT, 0)

    self.deleteGuideButton = LM.GUI.ImageButton('ScriptResources/mr_guides/mr_delete_guide', self:Localize('Delete Guide'), true, self.DELETE_GUIDE, false)
    layout:AddChild(self.deleteGuideButton, LM.GUI.ALIGN_LEFT, 0)

    self.deleteLastGuideButton = LM.GUI.ImageButton('ScriptResources/mr_guides/mr_delete_last_guide', self:Localize('Delete Last Guide'), false, self.DELETE_LAST_GUIDE, false)
    layout:AddChild(self.deleteLastGuideButton, LM.GUI.ALIGN_LEFT, 0)
	
	self.deleteGuidesLayerButton = LM.GUI.ImageButton('ScriptResources/mr_guides/mr_delete_guides_layer', self:Localize('Delete Guides Layer'), false, self.DELETE_GUIDES_LAYER, false)
    layout:AddChild(self.deleteGuidesLayerButton, LM.GUI.ALIGN_LEFT, 0)
	
    layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	self.guidesVisibilityButton = LM.GUI.ImageButton('ScriptResources/mr_guides/mr_visibility', self:Localize('Guides Visibility'), true, self.VISIBILITY, false)
    layout:AddChild(self.guidesVisibilityButton, LM.GUI.ALIGN_LEFT, 0)

    self.opacityInput = LM.GUI.TextControl(30, '100', self.OPACITY, LM.GUI.FIELD_INT, self:Localize('Opacity:'))
    layout:AddChild(self.opacityInput, LM.GUI.ALIGN_LEFT, 0)
    self.opacityInput:SetToolTip(self:Localize('Opacity of new guides'))

    self.widthInput = LM.GUI.TextControl(50, '1', self.WIDTH, LM.GUI.FIELD_UFLOAT, self:Localize('Width:'))
	self.widthInput:SetWheelInc(1.0)
	self.widthInput:SetWheelInteger(true)
    layout:AddChild(self.widthInput, LM.GUI.ALIGN_LEFT, 0)
	
	self.colorText = LM.GUI.DynamicText(self:Localize('Color'), 0)
    layout:AddChild(self.colorText, LM.GUI.ALIGN_LEFT, 0)
	
	self.guideColorSwatch = LM.GUI.ShortColorSwatch(true, self.COLOR)
	layout:AddChild(self.guideColorSwatch, LM.GUI.ALIGN_LEFT)
	self.guideColorSwatch:SetToolTip(MR_Guides:Localize('Guide Color Tooltip'))
end

function MR_Guides:UpdateWidgets(moho)
    self.createGuideHButton:SetValue(self.createVGuidBtn)
    self.createGuideVButton:SetValue(self.createHGuidBtn)
    self.moveGuideButton:SetValue(self.moveGuideBtn)
    self.deleteGuideButton:SetValue(self.deleteGuideBtn)
    self.opacityInput:SetValue(self.opacity)
    self.widthInput:SetValue(self.width)
	local guideColor = LM.rgb_color:new_local()
	guideColor.r = self.guideColorR
	guideColor.g = self.guideColorG
	guideColor.b = self.guideColorB
	guideColor.a = self.guideColorA
	self.guideColorSwatch:SetValue(guideColor)
	self.guidesLayer = self:CheckExistGuidesLayer(moho)
	if self.guidesLayer == nil then
		self.moveGuideButton:Enable(false)
		self.deleteGuideButton:Enable(false)
		self.opacityInput:Enable(false)
		self.deleteLastGuideButton:Enable(false)
		self.deleteGuidesLayerButton:Enable(false)
		self.createVGuidBtn = true
		self.createHGuidBtn = false
		self.moveGuideBtn = false
		self.deleteGuideBtn = false
		self.createGuideHButton:SetValue(self.createVGuidBtn)
		self.createGuideVButton:SetValue(self.createHGuidBtn)
		self.moveGuideButton:SetValue(self.moveGuideBtn)
		self.deleteGuideButton:SetValue(self.deleteGuideBtn)
		self.guidesVisibilityButton:SetValue(false)
		self.guidesVisibilityButton:Enable(false)
	else
		local mesh = self.guidesLayer:Mesh()
		self.guidesVisibilityButton:SetValue(self.guidesLayer:IsVisible())
		if mesh:CountPoints() < 2 then
			self.createVGuidBtn = true
			self.createHGuidBtn = false
			self.moveGuideBtn = false
			self.deleteGuideBtn = false
			self.createGuideHButton:SetValue(self.createVGuidBtn)
			self.createGuideVButton:SetValue(self.createHGuidBtn)
			self.moveGuideButton:SetValue(self.moveGuideBtn)
			self.deleteGuideButton:SetValue(self.deleteGuideBtn)
			self.moveGuideButton:Enable(false)
			self.deleteGuideButton:Enable(false)
			self.deleteLastGuideButton:Enable(false)
			self.guidesVisibilityButton:Enable(false)
			self.guidesVisibilityButton:SetValue(false)
		else
			self.moveGuideButton:Enable(true)
			self.deleteGuideButton:Enable(true)
			self.deleteLastGuideButton:Enable(true)
			self.guidesVisibilityButton:Enable(true)
		end
		self.opacityInput:Enable(true)
		self.deleteGuidesLayerButton:Enable(true)
		self.opacityInput:SetValue(self.guidesLayer.fAlpha:GetValue(0) * 100)
	end
end

function MR_Guides:HandleMessage(moho, view, msg)
    if msg == self.CREATE_GUIDE_H then
        self.createVGuidBtn = true
		self.createHGuidBtn = false
		self.moveGuideBtn = false
		self.deleteGuideBtn = false
		self.createGuideHButton:SetValue(true)
		self.createGuideVButton:SetValue(false)
		self.moveGuideButton:SetValue(false)
		self.deleteGuideButton:SetValue(false)
    elseif msg == self.CREATE_GUIDE_V then
        self.createVGuidBtn = false
		self.createHGuidBtn = true
		self.moveGuideBtn = false
		self.deleteGuideBtn = false
		self.createGuideHButton:SetValue(false)
		self.createGuideVButton:SetValue(true)
		self.moveGuideButton:SetValue(false)
		self.deleteGuideButton:SetValue(false)
    elseif msg == self.MOVE_GUIDE then
        self.createVGuidBtn = false
		self.createHGuidBtn = false
		self.moveGuideBtn = true
		self.deleteGuideBtn = false
		self.createGuideHButton:SetValue(false)
		self.createGuideVButton:SetValue(false)
		self.moveGuideButton:SetValue(true)
		self.deleteGuideButton:SetValue(false)
    elseif msg == self.DELETE_GUIDE then
        self.createVGuidBtn = false
		self.createHGuidBtn = false
		self.moveGuideBtn = false
		self.deleteGuideBtn = true
		self.createGuideHButton:SetValue(false)
		self.createGuideVButton:SetValue(false)
		self.moveGuideButton:SetValue(false)
		self.deleteGuideButton:SetValue(true)
		self:UpdateWidgets(moho)
    elseif msg == self.DELETE_LAST_GUIDE then
        self:DeleteLastGuide(moho)
		self:UpdateWidgets(moho)
	elseif msg == self.DELETE_GUIDES_LAYER then
        self:DeleteGuideLayer(moho)	
	elseif msg == self.VISIBILITY then
        self.guidesLayer = self:CheckExistGuidesLayer(moho)
		self.guidesLayer:SetVisible(self.guidesVisibilityButton:Value())
		moho:UpdateUI()
    elseif msg == self.OPACITY then
        self.opacity = LM.Clamp(self.opacityInput:Value(), 0, 100)
		self.opacityInput:SetValue(LM.Clamp(self.opacity, 0, 100))
		self:SetGuidesLayerOpacity(moho)
    elseif msg == self.WIDTH then
        self.width = LM.Clamp(self.widthInput:Value(), 0.25, 256)
		self.widthInput:SetValue(self.width)
	 elseif msg == self.COLOR then
        local colorSwatchValue = self.guideColorSwatch:Value()
		self.guideColorR = colorSwatchValue.r
		self.guideColorG = colorSwatchValue.g
		self.guideColorB = colorSwatchValue.b
		self.guideColorA = colorSwatchValue.a
    end
end

function MR_Guides:CheckExistGuidesLayer(moho)
	local topLayer = moho.document:Layer(moho.document:CountLayers()-1)
	local guidesLayer = nil
	local scriptData = topLayer:ScriptData()
	if (scriptData:HasKey("MR Guides Layer")) then
		guidesLayer = moho:LayerAsVector(topLayer)
	end	
	return guidesLayer
end

function MR_Guides:CreateGuide(moho, direction)
	local layer = moho:LayerAsVector(self.guidesLayer)
	local mesh = layer:Mesh()
	local n = mesh:CountPoints()
	local startPointPos = LM.Vector2:new_local()
	local endPointPos = LM.Vector2:new_local()
	if direction then
		startPointPos:Set(- 15, self.cursorVec.y)
		endPointPos:Set(15, self.cursorVec.y)
	else
		startPointPos:Set(self.cursorVec.x, - 5)
		endPointPos:Set(self.cursorVec.x, 5)
	end	
	
	mesh:SelectNone()
	
	local color = LM.rgb_color:new_local()
	color.r = self.guideColorR
	color.g = self.guideColorG
	color.b = self.guideColorB
	color.a = self.guideColorA
	
	if mesh:CountPoints() < 2 then
		mesh:AddLonePoint(startPointPos, 0)
		mesh:AppendPoint(endPointPos, 0)
		mesh:Point(n):SetCurvature(MOHO.PEAKED, 0)
		mesh:Point(n + 1):SetCurvature(MOHO.PEAKED, 0)
		mesh:Point(n + 1).fSelected = true
		mesh:SelectConnected()
		local shapeID = moho:CreateShape(false, false, 0)
		if shapeID >= 0 then
			local shape = mesh:Shape(shapeID)
			if mesh:CountShapes() > 0 then
				local style = moho:CurrentEditStyle()
				if (style ~= nil) then
					local lineWidth = self.width
					lineWidth = LM.Clamp(lineWidth, 0.25, 256)
					style.fLineWidth = lineWidth / moho.document:Height()
					style.fLineCol:SetValue(0, color)
				end
			end		
			local lineWidth = self.width
			lineWidth = LM.Clamp(lineWidth, 0.25, 256)
			shape.fMyStyle.fLineWidth = lineWidth / moho.document:Height()
			shape.fMyStyle.fLineCol:SetValue(0, color)
		end
	else
		mesh:Point(n - 1).fSelected = true
		mesh:SelectConnected()
		moho:Copy(mesh)
		moho:Paste()
		mesh:SelectNone()
		local startPoint = mesh:Point(mesh:CountPoints() - 2)
		local endPoint = mesh:Point(mesh:CountPoints() - 1)
		startPoint.fSelected = true
		endPoint.fSelected = true
		startPoint.fAnimPos:SetValue(0, startPointPos)
		endPoint.fAnimPos:SetValue(0, endPointPos)
		startPoint:SetCurvature(MOHO.PEAKED, 0)
		endPoint:SetCurvature(MOHO.PEAKED, 0)
		for i = 0, mesh:CountShapes() - 1 do
			local shape = mesh:Shape(i)
			local pointId = mesh:PointID(endPoint)
			if (shape.fHasOutline and shape:ContainsPoint(pointId)) then
				local lineWidth = self.width
				lineWidth = LM.Clamp(lineWidth, 0.25, 256)
				shape.fMyStyle.fLineWidth = lineWidth / moho.document:Height()
				shape.fMyStyle.fLineCol:SetValue(0, color)
			end
		end
	end	
	mesh:SelectNone()
end

function MR_Guides:CreateUpdateGuidsLayer(moho)
	local topLayer = moho.document:Layer(moho.document:CountLayers()-1)
	local scriptData = topLayer:ScriptData()
	if (scriptData:HasKey("MR Guides Layer")) then
		local topLayerMesh = moho:LayerAsVector(topLayer):Mesh()
		if topLayerMesh ~= nil then
			self.guidesLayer = moho:LayerAsVector(topLayer)
			self.guidesLayer:SetVisible(true)
		end
	else
		self.guidesLayer = moho:CreateNewLayer(MOHO.LT_VECTOR)
		local scriptData = self.guidesLayer:ScriptData()
		scriptData:Set("MR Guides Layer", true)
		local numVers = {}
		local vers = moho:AppVersion()
		for n in string.gmatch (vers, "%d+") do
			table.insert(numVers, tonumber(n))
		end
		if numVers[1] == 13 and numVers[2] == 5 then
			if numVers[3] ~= nil then
				if numVers[3] >= 2 then
					self.guidesLayer:SetIgnoredByLayerPicker(true)
				end
			end
		elseif numVers[1] == 13 and numVers[2] > 5 then
			self.guidesLayer:SetIgnoredByLayerPicker(true)
		elseif numVers[1] > 13 then
			self.guidesLayer:SetIgnoredByLayerPicker(true)	
		end
	end	

	self.guidesLayer:SetName('Guides')
	self.guidesLayer.fAlpha:SetValue(0, self.opacity / 100)
	self.guidesLayer:SetEditOnly(true)
	self.guidesLayer:SetImmuneToCamera(true)
	local newMesh = moho:LayerAsVector(self.guidesLayer):Mesh()
	local newMesh = moho:LayerAsVector(self.guidesLayer):Mesh()
	if self.createVGuidBtn and self.lastCursorVec.y ~= self.cursorVec.y then
		self:CreateGuide(moho, true)
	elseif self.createHGuidBtn and self.lastCursorVec.x ~= self.cursorVec.x then
		self:CreateGuide(moho, false)
	end

	self:ReturnToAction(moho)
	
	moho:SetCurFrame(self.curFrame)
end

function MR_Guides:GetGlobalPointPos(moho, pointPosition, layer)
	local pointPos = LM.Vector2:new_local()
	pointPos:Set(pointPosition)
	local layerMatrix = LM.Matrix:new_local()
	layer:GetFullTransform(moho.frame, layerMatrix, moho.document)
	layerMatrix:Transform(pointPos)
	return pointPos
end

function MR_Guides:ReturnToAction(moho)
	if self.curAction ~= '' then
		local parentGroup = self.curLayer:Parent()
		local skelLayer = nil
		
		if self.curLayer:LayerType() == 4 and self.curLayer:HasAction(self.curAction) then
			skelLayer = self.curLayer
		elseif parentGroup ~= nil then
			local targetGroup = parentGroup
			repeat
				if targetGroup:LayerType() == 4 then -- LT_BONE
					if targetGroup:HasAction(self.curAction) then
						skelLayer = targetGroup
					end	
				end
				targetGroup = targetGroup:Parent()
			until targetGroup == nil
		end
		
		moho:SetSelLayer(skelLayer)
		moho.document:SetCurrentDocAction(self.curAction)
		skelLayer:ActivateAction(self.curAction)
		if skelLayer ~= self.curLayer then
			moho:SetSelLayer(self.curLayer)
			self.curLayer:ActivateAction(self.curAction)
		end	
		moho:SetCurFrame(self.curFrame)
	else	
		moho:SetSelLayer(self.curLayer)
	end
end


function MR_Guides:DeleteGuide(moho, mouseEvent)
	local topLayer = moho.document:Layer(moho.document:CountLayers()-1)
	self.guidesLayer = nil
	local scriptData = topLayer:ScriptData()
	if (scriptData:HasKey("MR Guides Layer")) then
		self.guidesLayer = topLayer
	else
		return
	end
	
	local layer = moho:LayerAsVector(self.guidesLayer)
	local mesh = layer:Mesh()
	
	if mesh:CountPoints() < 1 then
		return
	end
	
	moho:SetSelLayer(self.guidesLayer)
	mesh:SelectNone()
	local shapesWidth = {}
	for i = 0, mesh:CountShapes() -1 do
		local shape = mesh:Shape(i)
		table.insert(shapesWidth, shape.fMyStyle.fLineWidth)
		shape.fMyStyle.fLineWidth = (10 / moho.document:Height())/moho.view:Graphics():CurrentScale()
	end
	local shapeID = mouseEvent.view:PickShape(mouseEvent.pt, -1, 5)
	for i = 0, mesh:CountShapes() -1 do
		local shape = mesh:Shape(i)
		shape.fMyStyle.fLineWidth = shapesWidth[i + 1]
	end	
	if (shapeID >= 0) then
		local shape = mesh:Shape(shapeID)
		for i = 0, shape:CountEdges() - 1 do
			curveID, segID = shape:GetEdge(i, curveID, segID)
			local curve = mesh:Curve(curveID)
			curve:Point(segID).fSelected = true
			mesh:SelectConnected()
			mesh:DeleteSelectedPoints()
		end
	end
	self:ReturnToAction(moho)
end

function MR_Guides:DeleteLastGuide(moho)
	local topLayer = moho.document:Layer(moho.document:CountLayers()-1)
	local guidesLayer = nil
	local scriptData = topLayer:ScriptData()
	if (scriptData:HasKey("MR Guides Layer")) then
		guidesLayer = topLayer
	else
		return
	end
	
	local layer = moho:LayerAsVector(guidesLayer)
	local mesh = layer:Mesh()
	
	if mesh:CountPoints() < 1 then
		return
	end
	
	local point = mesh:Point(mesh:CountPoints()-1)
	mesh:SelectNone()
	point.fSelected = true
	mesh:SelectConnected()
	mesh:DeleteSelectedPoints()
end

function MR_Guides:SetGuidesLayerOpacity(moho)
	local topLayer = moho.document:Layer(moho.document:CountLayers()-1)
	local guidesLayer = nil
	local scriptData = topLayer:ScriptData()
	if (scriptData:HasKey("MR Guides Layer")) then
		guidesLayer = topLayer
	else
		return
	end
	guidesLayer.fAlpha:SetValue(0, self.opacity / 100)
	moho.view:DrawMe()
	moho:UpdateUI()
	moho:UpdateSelectedChannels()
end

function MR_Guides:DeleteGuideLayer(moho)
	local curFrame = moho.frame
	local topLayer = moho.document:Layer(moho.document:CountLayers()-1)
	local guidesLayer = nil
	local scriptData = topLayer:ScriptData()
	if (scriptData:HasKey("MR Guides Layer")) then
		guidesLayer = topLayer
	else
		return
	end
	
	self.curLayer = moho.layer
	if self.curLayer == guidesLayer then
		self.curLayer = moho.document:Layer(moho.document:CountLayers()-2)
	end	
	local curAction = moho.layer:CurrentAction()
	local curFrame = moho.frame
	moho.document:PrepUndo(nil)
	moho.document:SetDirty()
	moho:DeleteLayer(guidesLayer)
	self:ReturnToAction(moho)
	if curFrame > 0 then
		moho:SetCurFrame(0)
		moho:SetCurFrame(curFrame)
	elseif curFrame == 0 then
		moho:SetCurFrame(1)
		moho:SetCurFrame(curFrame)
	end
	moho.layer:UpdateCurFrame()
	moho.view:DrawMe()
	moho:UpdateUI()
	moho:UpdateSelectedChannels()
end

-- **************************************************
-- Localization
-- **************************************************

function MR_Guides:Localize(text)
	local phrase = {}

	phrase['Description'] = 'Create and edit guides without leaving the current layer and action.'
	phrase['UILabel'] = 'Guides'

	phrase['Create Horizontal Guide'] = 'Create Horizontal Guide'
	phrase['Create Vertical Guide'] = 'Create Vertical Guide'
	phrase['Move Existing Guide'] = 'Move Existing Guide'
	phrase['Delete Guide'] = 'Delete Guide'
	phrase['Delete Last Guide'] = 'Delete Last Guide'
	phrase['Opacity:'] = 'Guides Opacity:'
	phrase['Opacity of new guides'] = 'Opacity of all guides.'
	phrase['Width:'] = 'Width:'
	phrase['Color'] = 'Color'
	phrase['Guide Color Tooltip'] = 'Guide Color'
	phrase['Delete Guides Layer'] = 'Delete Guides Layer'
	phrase['Guides Visibility'] = 'Show/Hide Guides'

	local fileWord = MOHO.Localize("/Menus/File/File=File")
	if fileWord == "Файл" then
		phrase['Description'] = 'Инструмент позволяет создавать и редактировать гайды не покидая текущего слоя и экшена.'
		phrase['UILabel'] = 'Гайды'

		phrase['Create Horizontal Guide'] = 'Создать горизонтальный гайд'
		phrase['Create Vertical Guide'] = 'Создать вертикальный гайд'
		phrase['Move Existing Guide'] = 'Переместить существующий гайд'
		phrase['Delete Guide'] = 'Удалить гайд'
		phrase['Delete Last Guide'] = 'Удалить последний гайд'
		phrase['Opacity:'] = 'Прозрачность гайдов:'
		phrase['Opacity of new guides'] = 'Прозрачность всех гайдов'
		phrase['Width:'] = 'Ширина:'
		phrase['Color'] = 'Цвет'
		phrase['Guide Color Tooltip'] = 'Цвет гайда'
		phrase['Delete Guides Layer'] = 'Удалить слой гайдов'
		phrase['Guides Visibility'] = 'Показать/скрыть гайды'
	end

	return phrase[text]
end

Icon
MR Guides
Listed

Script type: Tool

Uploaded: Oct 17 2021, 15:05

Last modified: Nov 12 2021, 03:40

Create and edit guides without leaving the current layer and action.
This script, and all other scripts on this site are distributed as free software under the GNU General Public License 3.0 or later.
Downloads count: 233