PDA

View Full Version : Need help with a while loop in a subselection related tool


Malkalypse
10-15-2010, 04:02 AM
I'm currently working on a script to make it easier to divide an edit-poly object into sub-selections. The basic idea is that you click on an edge and it selects the entire edge loop UNTIL it reaches the point where it intersects with an existing selected edge loop. The tricky part is that I also want to be able to click on a selected edge loop, and UNSELECT the selected edge loop section by doing so.

I have this script almost worked out, but there is one small section I am having trouble with and can't seem to get past. Basically it has to do with the while loop that builds the array of edges to either add or subtract to the selection. I've tried 2 different variants on the condition for the loop, but each one has its own problem.

I have the problematic lines below, followed by the entirety of the script with the problem area labeled. Feel free to play around with the script if you see other things that can be improved!

Problem area isolated:
--while hotEdges.numberSet != oldEdges.numberSet do
while (hotEdges - oldEdges).numberSet != 0 do



/***********************************************/
-- EXPLANATION:
--
-- FIRST CONDITION WORKS FINE UNTIL A
-- SINGLE-EDGED LOOP IS CLICKED, THEN IT STOPS
-- SELECTING MORE THAN ONE EDGE AT A TIME
-- UNTIL THE SCRIPT IS RESTARTED
--
-- THE SECOND CONDITION WORKS FINE UNLESS
-- THE SAME EDGE LOOP IS CLICKED TWICE IN A ROW
-- (I.E. SELECTED THEN UNSELECTED), IN WHICH
-- CASE, ONLY A SINGLE EDGE WILL BE UNSELECTED
/***********************************************/
(
oldEdges = #{}; for s in hotEdges do append oldEdges s
findExtants hotEdges

for v in xVerts do extendLoop v
)

The script in its entirety:
global xVerts, xEdges, hotEdges

global restartTool = false
global initSel = false

allEdges = #{} -- all edges of the selected object
selEdges = #{} -- selected edges
hotEdges = #{} -- specified edges
oldEdges = #{} -- previously specified edges



--------------------------------------------------------------
-- Function to find the extant edges of a specified edge array
-- edges: specified edges
--------------------------------------------------------------
fn findExtants edges =
(
xVerts = #{} -- i.e. "extant vertices"
xEdges = #{} -- i.e. "extend edges"

edgeVerts = polyOp.getVertsUsingEdge $ edges -- vertices of all specified edges

for v in (edgeVerts as array) do -- for all vertices in edgeVerts array
(
nEdges = polyOp.getEdgesUsingVert $ v -- edges adjoining vertex v
nEdges -= (nEdges - edges - selEdges) -- keep only edges that are specified or selected
nEdges = nEdges as array

-- Declare extant vertices and edges
if initSel == false
then (if nEdges.count == 1 do (append xVerts v; append xEdges nEdges[1]))
else (if nEdges.count == 2 do (append xVerts v; append xEdges nEdges[1]))
) -- end v loop
) -- end function (findExtants)
-------------------------------



--------------------------------------------------
-- Function to extend the loop of hot edges by one
-- v: extant vertex to use as starting point
--------------------------------------------------
fn extendLoop v =
(
vertEdges = polyOp.getEdgesUsingVert $ v -- edges adjoining vertex v
xEdge = vertEdges - (allEdges - hotEdges) -- i.e. "extant edge"
xEdgeFaces = (polyOp.getFacesUsingEdge $ xEdge) as array -- faces of extant edge

-- Add vertex edge(s) that share(s) no faces with extant edge to hot edges
for s in vertEdges do
(
ff = (polyOp.getFacesUsingEdge $ s) as array
if (findItem xEdgeFaces ff[1] == 0) and (findItem xEdgeFaces ff[2] == 0) do append hotEdges s
) -- end s loop
) -- end function (extendLoop)
------------------------------



-----------------------------------------------------------------------------------
-- Function to select an edge loop up to its intersection with other selected loops
-----------------------------------------------------------------------------------
fn loopToIntersect =
(
if (hotEdges - selEdges).numberSet == 0 then initSel = true else initSel = false





/***********************************************/
-- PROBLEM CODE:
/***********************************************/

--while hotEdges.numberSet != oldEdges.numberSet do
while (hotEdges - oldEdges).numberSet != 0 do

/***********************************************/
(
oldEdges = #{}; for s in hotEdges do append oldEdges s
findExtants hotEdges

for v in xVerts do extendLoop v
)





if initSel == false
then selEdges += hotEdges -- add hot edges to edge selection
else selEdges -= hotEdges -- remove hot edges from edge selection

polyOp.setEdgeSelection $ selEdges; update $
) -- end function (loopToIntersect)
----------------------------------------------



----------------------------------------------------------------
-- Function to determine the distance between a point and a line
-- Special thanks to prettyPixel
----------------------------------------------------------------
fn pointLineDist pA pB pC =
(
local vAB = pB - pA
local vAC = pC - pA
(length (cross vAB vAC)) / (length vAB)
)
-- end function (pointLineDist)
-------------------------------



------------------------------------------------------
-- Function to determine the edge closest to the mouse
------------------------------------------------------
fn getMouseEdge =
(
vertCount = polyop.getNumVerts $.baseobject
backVerts = (polyop.getVertsByFlag $.baseobject 8)
okVerts = (#{1..vertCount} - backVerts - (polyop.getHiddenVerts $.baseobject)) as array

if vertCount != 0 do
(
mp = mouse.pos


-- Find non-hidden, front facing vertex closest to the mouse
------------------------------------------------------------
vertDistArray = #(#(),#())

for v in okVerts do
(
m = gw.wTranspoint (polyop.getVert $.baseobject v node:$)
append vertDistArray[1] v
append vertDistArray[2] (distance mp [m.x, m.y])
)

minIndex = findItem vertDistArray[2] (aMin vertDistArray[2])
minVert = vertDistArray[1][minIndex]
------------------------------------------------------------


-- Find closest neighboring vertex
-----------------------------------------------------------------------
vertEdges = polyOp.getEdgesUsingVert $ minVert
nVerts = ((polyOp.getVertsUsingEdge $ vertEdges) - #{minVert}) as array

nDistArray = #(#(), #())

for v in nVerts do
(
m = gw.wTranspoint (polyop.getVert $.baseobject v node:$)
append nDistArray[1] v
append nDistArray[2] (distance mp [m.x, m.y])
)

nMinIndex = findItem nDistArray[2] (aMin nDistArray[2])
nMinVert = nDistArray[1][nminIndex]
-----------------------------------------------------------------------


nVertEdges = polyOp.getEdgesUsingVert $ nMinVert
hotEdges = (vertEdges - (vertEdges - nVertEdges))
) -- end if (vertCount != 0)

completeredraw()
gw.setcolor #line (yellow)
gw.polyLine #(polyOp.getVert $ minVert, polyOp.getVert $ nMinVert) false
gw.enlargeUpdateRect #whole
gw.updateScreen()
) -- end function (getMouseEdge)
--------------------------------



tool getLoopToIntersect
(
on freeMove do getMouseEdge()

on mousePoint clickno do
(
allEdges = #{1..(polyOp.getNumEdges $)} -- all edges of the selected object
selEdges = polyOp.getEdgeSelection $ -- selected edges
getMouseEdge() -- find edge closest to the mouse
loopToIntersect()
restartTool = true; #stop
)

-- Restart mouse tool unless aborted
on mouseAbort clickno do (restartTool = false)
on stop do (if restartTool == true do startTool getLoopToIntersect)
)

if $ != undefined do startTool getLoopToIntersect

Malkalypse
10-17-2010, 10:30 PM
I'm sure someone here must be able to figure out what I'm doing wrong...?

Malkalypse
10-18-2010, 02:02 AM
And it looks like the one to figure it out was me.

If anyone is interested, I just needed to clear the "oldEdges" bitarray in the loopToIntersect function BEFORE the while loop (while still leaving one inside the loop as well), and then use the first condition for the loop statement.

CGTalk Moderation
10-18-2010, 02:02 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.