szubkin
11/21/2018 - 8:57 PM

Массовый Autofollow (с глобальной точностью)

Массовый Autofollow (с глобальной точностью)

Dim info As String = "Скрипт определяет максимально высокую точку у выбранных контейнеров
и располагает self-контейнер в эту точку (в глобальном измерении)
Разработчик: Дудин Дмитрий. Vizart co.    Версия 1.0 (13 августа 2012)
"

Dim arr_mode As Array[String]
arr_mode.Push("[ X ]")
arr_mode.Push("[ Y ]")
Dim arr_direction As Array[String]
arr_direction.Push("[ > ]")
arr_direction.Push("[ * ]")
arr_direction.Push("[ < ]")
Dim mode, direction As Integer
Dim arr_c As Array[Container]
Dim c As Container
Dim i As Integer
Dim max, max2, mid As Vertex
Dim v1,v2, v_world As Vertex
Dim defY,defX As Double
Dim threshold As Double = 0.01
Dim thresholdMove As Double = 1.0
Dim quantity_of_container As Integer = 1

sub OnInitParameters()
	RegisterInfoText(info)
	RegisterRadioButton("mode", "Следить по оси:", 0, arr_mode)
	RegisterRadioButton("direction", "Направление:", 0, arr_direction)
	RegisterParameterDouble("defX", "Позиция по X без смещений:", 0, -1000.0, 1000.0)
	RegisterParameterDouble("shiftX", "Смещение по X со смещением:", 0, -1000.0, 1000.0)
	RegisterParameterDouble("defY", "Позиция по Y без смещений:", 0, -1000.0, 1000.0)
	RegisterParameterDouble("shiftY", "Смещение по Y со смещением:", 0, -1000.0, 1000.0)
	For i = 1 to quantity_of_container
		RegisterParameterContainer("c" & i,"Контейнер " & i & ":")
	Next
end sub

sub OnInit()
	arr_c.Clear()

	For i = 1 to quantity_of_container
		c = GetParameterContainer("c" & i)
		If c <> null Then arr_c.Push(c)
	Next
end sub

sub OnExecPerField()

	mode = GetParameterInt("mode")
	direction = GetParameterInt("direction")
	If mode == 0 Then
		'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
		
		If direction == 0 Then
			max = CVertex(10000000.0,0,0)
			For i = 0 to quantity_of_container-1
				arr_c[i].RecomputeMatrix()
				arr_c[i].GetTransformedBoundingBox(v1,v2)
				If v2.y > (v1.y + threshold) Then
					If v1.x < max.x AND (v2.x > v1.x + threshold OR v2.x < v1.x - threshold) Then max = v1
				End If
			Next

			If max.x >= 1000000 Then
				'если не на что ориентировать и надо встать в свое стандартное место
				defX = GetParameterDouble("defX")
				If this.position.x > defX - threshold AND this.position.x < defX + threshold Then
					max.x = defX
				Else
					v_world = LocalPosToWorldPos(this.position.xyz)
					max.x = v_world.x - ((v_world.x - defX)/5.0)
				End If
			Else
				max.x += GetParameterDouble("shiftX")
			End If	
			
		ElseIf direction == 1 Then
			max2 = CVertex(-10000000.0,0,0)
			max = CVertex(10000000.0,0,0)
			For i = 0 to quantity_of_container-1
				arr_c[i].RecomputeMatrix()
				arr_c[i].GetTransformedBoundingBox(v1,v2)

				If v2.x > (v1.x + threshold) Then
					If v2.x > max2.x AND (v2.x > v1.x + threshold OR v2.x < v1.x - threshold) Then max2 = v2
					If v1.x < max.x AND (v2.x > v1.x + threshold OR v2.x < v1.x - threshold) Then max = v1
				End If
			Next
			
			mid.x = (max.x + max2.x)/2
			mid.x += GetParameterDouble("shiftX")
			max = mid
			
		ElseIf direction == 2 Then
			max = CVertex(-10000000.0,0,0)
			For i = 0 to quantity_of_container-1
				arr_c[i].RecomputeMatrix()
				arr_c[i].GetTransformedBoundingBox(v1,v2)
				If v2.y > (v1.y + threshold) Then
					If v2.x > max.x AND (v2.x > v1.x + threshold OR v2.x < v1.x - threshold) Then max = v2
				End If
			Next

			If max.x <= -1000000 Then
				'если не на что ориентировать и надо встать в свое стандартное место
				defX = GetParameterDouble("defX")
				If this.position.x > defX - threshold AND this.position.x < defX + threshold Then
					max.x = defX
				Else
					v_world = LocalPosToWorldPos(this.position.xyz)
					max.x = v_world.x - ((v_world.x - defX)/5.0)
				End If
			Else
				max.x += GetParameterDouble("shiftX")
			End If
		End If
		
		

		'ANIMATE REAL MOVE TO NEW POINT
		max = this.WorldPosToLocalPos(max)
		If Abs(max.x - this.position.x) > thresholdMove Then
			this.position.x += (max.x - this.position.x)/5.0
		End If


	ElseIf mode == 1 Then
		'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY

		If direction == 0 Then
			max = CVertex(0,10000000.0,0)
			For i = 0 to quantity_of_container-1
				arr_c[i].RecomputeMatrix()
				arr_c[i].GetTransformedBoundingBox(v1,v2)
				If v2.x > (v1.x + threshold) Then
					If v1.y < max.y AND (v2.y > v1.y + threshold OR v2.y < v1.y - threshold) Then max = v1
				End If
			Next

			If max.y >= 1000000 Then
				'если не на что ориентировать и надо встать в свое стандартное место
				defY = GetParameterDouble("defY")
				If this.position.y > defY - threshold AND this.position.y < defY + threshold Then
					max.y = defY
				Else
					v_world = LocalPosToWorldPos(this.position.xyz)
					max.y = v_world.y - ((v_world.y - defY)/2.0)
				End If
			Else
				max.y += GetParameterDouble("shiftY")
			End If
		ElseIf direction == 1 Then
			max2 = CVertex(0,-10000000.0,0)
			max = CVertex(0,10000000.0,0)
			For i = 0 to quantity_of_container-1
				arr_c[i].RecomputeMatrix()
				arr_c[i].GetTransformedBoundingBox(v1,v2)

				If v2.y > (v1.y + threshold) Then
					If v2.y > max2.y AND (v2.y > v1.y + threshold OR v2.y < v1.y - threshold) Then max2 = v2
					If v1.y < max.y AND (v2.y > v1.y + threshold OR v2.y < v1.y - threshold) Then max = v1
				End If
			Next
			
			mid.y = (max.y + max2.y)/2
			mid.y += GetParameterDouble("shiftY")
			max = mid


		ElseIf direction == 2 Then
			max = CVertex(0,-10000000.0,0)
			For i = 0 to quantity_of_container-1
				arr_c[i].RecomputeMatrix()
				arr_c[i].GetTransformedBoundingBox(v1,v2)
				If v2.x > (v1.x + threshold) Then
					If v2.y > max.y AND (v2.y > v1.y + threshold OR v2.y < v1.y - threshold) Then max = v2
				End If
			Next

			If max.y <= -1000000 Then
				'если не на что ориентировать и надо встать в свое стандартное место
				defY = GetParameterDouble("defY")
				If this.position.y > defY - threshold AND this.position.y < defY + threshold Then
					max.y = defY
				Else
					v_world = LocalPosToWorldPos(this.position.xyz)
					max.y = v_world.y - ((v_world.y - defY)/2.0)
				End If
			Else
				max.y += GetParameterDouble("shiftY")
			End If
			
		End If
		
		'ANIMATE REAL MOVE TO NEW POINT
		max = this.WorldPosToLocalPos(max)
		If Abs(max.y - this.position.y) > thresholdMove Then
			this.position.y += (max.y - this.position.y)/5.0
		End If
	End If
end sub

sub OnParameterChanged(parameterName As String)
	OnInit()

	mode = GetParameterInt("mode")
	If mode == 0 Then
		SendGuiParameterShow("defX",SHOW)
		SendGuiParameterShow("defY",HIDE)
		SendGuiParameterShow("shiftX",SHOW)
		SendGuiParameterShow("shiftY",HIDE)
	ElseIf mode == 1 Then
		SendGuiParameterShow("defX",HIDE)
		SendGuiParameterShow("defY",SHOW)
		SendGuiParameterShow("shiftX",HIDE)
		SendGuiParameterShow("shiftY",SHOW)
	End If
end sub