Advertisement
Guest User

Untitled

a guest
Jul 13th, 2024
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.72 KB | None | 0 0
  1. import maya.cmds as cmds
  2. import maya.OpenMayaUI as omui
  3. import maya.OpenMaya as om
  4. from PySide2 import QtWidgets, QtCore
  5. from shiboken2 import wrapInstance
  6.  
  7. class VertexDistributor(QtWidgets.QWidget):
  8.     def __init__(self):
  9.         super(VertexDistributor, self).__init__()
  10.         self.setWindowTitle("Vertex Distributor")
  11.         self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
  12.         self.setGeometry(100, 100, 500, 200)
  13.         self.create_ui()
  14.  
  15.     def create_ui(self):
  16.         layout = QtWidgets.QVBoxLayout()
  17.  
  18.         # Create a form layout for aligned fields
  19.         form_layout = QtWidgets.QFormLayout()
  20.  
  21.         # Start Point
  22.         start_layout = QtWidgets.QHBoxLayout()
  23.         self.start_field = QtWidgets.QLineEdit()
  24.         start_layout.addWidget(self.start_field)
  25.         start_layout.addWidget(self.create_button("Assign", self.assign_start))
  26.         start_layout.addWidget(self.create_button("Select", self.select_start))
  27.         start_layout.addWidget(self.create_button("Clear", self.clear_start))
  28.         form_layout.addRow("Start Point:", start_layout)
  29.  
  30.         # End Point
  31.         end_layout = QtWidgets.QHBoxLayout()
  32.         self.end_field = QtWidgets.QLineEdit()
  33.         end_layout.addWidget(self.end_field)
  34.         end_layout.addWidget(self.create_button("Assign", self.assign_end))
  35.         end_layout.addWidget(self.create_button("Select", self.select_end))
  36.         end_layout.addWidget(self.create_button("Clear", self.clear_end))
  37.         form_layout.addRow("End Point:", end_layout)
  38.  
  39.         # Vertices
  40.         vert_layout = QtWidgets.QHBoxLayout()
  41.         self.vert_field = QtWidgets.QLineEdit()
  42.         vert_layout.addWidget(self.vert_field)
  43.         vert_layout.addWidget(self.create_button("Assign", self.assign_verts))
  44.         vert_layout.addWidget(self.create_button("Select", self.select_verts))
  45.         vert_layout.addWidget(self.create_button("Clear", self.clear_verts))
  46.         form_layout.addRow("Vertices:", vert_layout)
  47.  
  48.         layout.addLayout(form_layout)
  49.  
  50.         # Order Radio Buttons
  51.         order_layout = QtWidgets.QHBoxLayout()
  52.         self.order_group = QtWidgets.QButtonGroup()
  53.         self.passed_order = QtWidgets.QRadioButton("Use Passed Order")
  54.         self.spatial_order = QtWidgets.QRadioButton("Use Spatial Order")
  55.         self.order_group.addButton(self.passed_order)
  56.         self.order_group.addButton(self.spatial_order)
  57.         self.passed_order.setChecked(True)
  58.         order_layout.addWidget(self.passed_order)
  59.         order_layout.addWidget(self.spatial_order)
  60.         layout.addLayout(order_layout)
  61.  
  62.         # Include Start/End Checkboxes
  63.         include_layout = QtWidgets.QHBoxLayout()
  64.         self.include_start_checkbox = QtWidgets.QCheckBox("Include Start")
  65.         self.include_end_checkbox = QtWidgets.QCheckBox("Include End")
  66.         self.include_start_checkbox.setChecked(True)
  67.         self.include_end_checkbox.setChecked(True)
  68.         include_layout.addWidget(self.include_start_checkbox)
  69.         include_layout.addWidget(self.include_end_checkbox)
  70.         layout.addLayout(include_layout)
  71.  
  72.         '''
  73.        # Slope Editor
  74.        self.slope_editor = self.create_slope_editor()
  75.        layout.addWidget(QtWidgets.QLabel("Distribution Curve:"))
  76.        layout.addWidget(self.slope_editor)
  77.  
  78.        # Curve Type Dropdown
  79.        self.curve_type_combo = QtWidgets.QComboBox()
  80.        self.curve_type_combo.addItems(["Linear", "Smooth", "Spline", "Exponential Up", "Exponential Down"])
  81.        self.curve_type_combo.currentIndexChanged.connect(self.update_curve_type)
  82.        layout.addWidget(self.curve_type_combo)
  83.        '''
  84.  
  85.         # Align and Distribute Button
  86.         self.align_button = QtWidgets.QPushButton("Align and Distribute")
  87.         self.align_button.clicked.connect(self.align_and_distribute)
  88.         self.align_button.setEnabled(False)
  89.         layout.addWidget(self.align_button)
  90.  
  91.         self.setLayout(layout)
  92.  
  93.     def create_button(self, text, callback):
  94.         button = QtWidgets.QPushButton(text)
  95.         button.clicked.connect(callback)
  96.         return button
  97.     '''
  98.    def create_slope_editor(self):
  99.        # Create the gradientControlNoAttr
  100.        gradient_control = cmds.gradientControlNoAttr(
  101.            h=100,  # Height of the control
  102.            w=400   # Width of the control
  103.        )
  104.        
  105.        # Set initial keyframes for start and end
  106.        cmds.gradientControlNoAttr(gradient_control, e=True, vap=0.0)
  107.        cmds.gradientControlNoAttr(gradient_control, e=True, vap=1.0)
  108.  
  109.        # Convert the Maya UI element to a QWidget
  110.        ptr = omui.MQtUtil.findControl(gradient_control)
  111.        if ptr is not None:
  112.            return wrapInstance(int(ptr), QtWidgets.QWidget)
  113.        return None
  114.  
  115.    def update_curve_type(self, index):
  116.        curve_type = self.curve_type_combo.currentText()
  117.        if curve_type == "Linear":
  118.            self.set_curve_interp(0)  # 0 for linear
  119.        elif curve_type == "Smooth":
  120.            self.set_curve_interp(1)  # 1 for smooth
  121.        elif curve_type == "Spline":
  122.            self.set_curve_interp(2)  # 2 for spline
  123.        elif curve_type == "Exponential Up":
  124.            self.set_curve_interp(3)  # 3 for exponential up
  125.        elif curve_type == "Exponential Down":
  126.            self.set_curve_interp(4)  # 4 for exponential down
  127.  
  128.    def set_curve_interp(self, interp_value):
  129.        # Set the interpolation for all keys
  130.        keys = cmds.gradientControlNoAttr(self.slope_editor, q=True, asString=True).split(",")
  131.        num_keys = len(keys) // 4  # Each key is represented by 4 values
  132.        for i in range(num_keys):
  133.            cmds.gradientControlNoAttr(self.slope_editor, e=True, ckv=i, civ=interp_value)
  134.    '''
  135.     def clear_start(self):
  136.         self.start_field.clear()
  137.         self.update_align_button()
  138.  
  139.     def assign_start(self):
  140.         sel = cmds.ls(sl=True, fl=True)
  141.         if sel:
  142.             self.start_field.setText(sel[0])
  143.         self.update_align_button()
  144.  
  145.     def select_start(self):
  146.         obj = self.start_field.text()
  147.         if obj:
  148.             cmds.select(obj, r=True)
  149.  
  150.     def clear_end(self):
  151.         self.end_field.clear()
  152.         self.update_align_button()
  153.  
  154.     def assign_end(self):
  155.         sel = cmds.ls(sl=True, fl=True)
  156.         if sel:
  157.             self.end_field.setText(sel[0])
  158.         self.update_align_button()
  159.  
  160.     def select_end(self):
  161.         obj = self.end_field.text()
  162.         if obj:
  163.             cmds.select(obj, r=True)
  164.  
  165.     def clear_verts(self):
  166.         self.vert_field.clear()
  167.         self.update_align_button()
  168.  
  169.     def assign_verts(self):
  170.         sel = cmds.ls(sl=True, fl=True)
  171.         verts = cmds.filterExpand(sel, sm=31)
  172.         if verts:
  173.             self.vert_field.setText(','.join(verts))
  174.         self.update_align_button()
  175.  
  176.     def select_verts(self):
  177.         verts = self.vert_field.text().split(',')
  178.         if verts:
  179.             cmds.select(verts, r=True)
  180.  
  181.     def update_align_button(self):
  182.         self.align_button.setEnabled(
  183.             bool(self.start_field.text()) and
  184.             bool(self.end_field.text()) and
  185.             bool(self.vert_field.text())
  186.         )
  187.  
  188.     def align_and_distribute(self):
  189.         start = self.start_field.text()
  190.         end = self.end_field.text()
  191.         verts = self.vert_field.text().split(',')
  192.         use_spatial = self.spatial_order.isChecked()
  193.         include_start = self.include_start_checkbox.isChecked()
  194.         include_end = self.include_end_checkbox.isChecked()
  195.  
  196.         # Check if start and end are the same object
  197.         if start == end:
  198.             cmds.warning("Start and end points are the same object. Please choose different objects.")
  199.             return
  200.  
  201.         self.distribute_vertices(verts, start, end, use_spatial, include_start, include_end)
  202.  
  203.     def get_position(self, obj):
  204.         if '.vtx[' in obj:
  205.             vertex_index = int(obj.split('[')[-1].split(']')[0])
  206.             mesh_name = obj.split('.')[0]
  207.            
  208.             sel_list = om.MSelectionList()
  209.             sel_list.add(mesh_name)
  210.             dag_path = om.MDagPath()
  211.             sel_list.getDagPath(0, dag_path)
  212.            
  213.             fn_mesh = om.MFnMesh(dag_path)
  214.             point = om.MPoint()
  215.             fn_mesh.getPoint(vertex_index, point, om.MSpace.kWorld)
  216.            
  217.             return [point.x, point.y, point.z]
  218.         else:
  219.             return cmds.xform(obj, q=True, ws=True, t=True)
  220.  
  221.     def distribute_vertices(self, vertices, start, end, spatial=False, include_start=True, include_end=True):
  222.         start_pos = self.get_position(start)
  223.         end_pos = self.get_position(end)
  224.  
  225.         # Check if start and end positions are too close
  226.         tolerance = 1e-5
  227.         if self.distance(start_pos, end_pos) < tolerance:
  228.             cmds.warning("Start and end points are too close. Please choose points further apart.")
  229.             return
  230.  
  231.         if spatial:
  232.             vertices = sorted(vertices, key=lambda v: self.distance(self.get_position(v), start_pos))
  233.  
  234.         total_distance = self.distance(start_pos, end_pos)
  235.        
  236.         # Calculate the number of segments based on include_start and include_end
  237.         num_segments = len(vertices) - 1
  238.         if not include_start:
  239.             num_segments += 1
  240.         if not include_end:
  241.             num_segments += 1
  242.  
  243.         step = total_distance / num_segments
  244.  
  245.         # Start an undo chunk
  246.         cmds.undoInfo(openChunk=True)
  247.         try:
  248.             for i, vertex in enumerate(vertices):
  249.                 # Calculate the t value based on include_start and include_end
  250.                 if include_start and include_end:
  251.                     t = i * step / total_distance
  252.                 elif include_start and not include_end:
  253.                     t = i * step / total_distance
  254.                 elif not include_start and include_end:
  255.                     t = (i + 1) * step / total_distance
  256.                 else:  # not include_start and not include_end
  257.                     t = (i + 1) * step / total_distance
  258.  
  259.                 new_pos = [
  260.                     start_pos[j] + t * (end_pos[j] - start_pos[j])
  261.                     for j in range(3)
  262.                 ]
  263.                 cmds.xform(vertex, ws=True, t=new_pos)
  264.         finally:
  265.             # Close the undo chunk
  266.             cmds.undoInfo(closeChunk=True)
  267.  
  268.     def distance(self, p1, p2):
  269.         return sum((a - b) ** 2 for a, b in zip(p1, p2)) ** 0.5
  270.    
  271.  
  272. def show_vertex_distributor():
  273.     global vertex_distributor_window
  274.     try:
  275.         vertex_distributor_window.close()
  276.         vertex_distributor_window.deleteLater()
  277.     except:
  278.         pass
  279.     vertex_distributor_window = VertexDistributor()
  280.     vertex_distributor_window.show()
  281.  
  282. show_vertex_distributor()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement