Advertisement
Guest User

Untitled

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