본문 바로가기

Script/Python

Python - 3Dsmax 스크립트관리 및 뷰어.

파이참, Pyqt4, Qt-Designer 사용.

 

  1. 초기 스크립트 위치 폴더 지정하면, c:\temp에 위치 경로파일 생성.
  2. 지정한 폴더내의 맥스 스크립트를 불러와서
  3. 목록 구성후
  4. 해당 파일 더블클릭하면 스크립트 실행됨.
  5. 설명 및 아이콘은 파이썬 코드에서 수정.

 

 

####################################
######## created by 김진규 #########
####################################
from PyQt4.QtGui import * # https://www.lfd.uci.edu/~gohlke/pythonlibs/pyqt4
from PyQt4 import uic
from PyQt4.QtCore import QSize
import MaxPlus
import glob
import sys, os

RootPath = os.path.dirname(__file__).replace('\\','/')
mainuipath = RootPath+'/ui/ScriptViewer.ui'  # --- QT디자이너 파일 위치.
scriptPath = 'c:/temp/ms_config.txt' # --- 스크립트 config파일 생성.
model = QStandardItemModel()
stringmodel =QStringListModel()

item_list = [U"1번을 할 수 있는 스크립트 입니다.",
             U"2번을 만드는 스크립트 입니다.",
             U"3번을 생성하는 스크립트 입니다.",
             U"4번을 할까말까 하는 스크립트 입니다."]
iconlist = [RootPath+"/1.png", RootPath+"/2.png", RootPath+"/3.png"]

app = QApplication.instance()
if not app:# PySide using QtGui.QApplication(), 3ds Max, there is already a PySide application running, so you get a handle for that object like this:
   app = QApplication([])

# https://help.autodesk.com/view/3DSMAX/2017/ENU/?guid=__developer_using_pyside_html
class _GCProtector(object): # ---- To protect widgets from being garbage collected
    widgets = []

class Script_Viewer(QMainWindow):
    def __init__(self):
        super(Script_Viewer, self).__init__() # ---https://pystock.atlassian.net/wiki/spaces/FIN/pages/393342/4+-+PyQt
        #QMainWindow.__init__(self)
        _GCProtector.widgets.append(QMainWindow)
        uic.loadUi(mainuipath,self)  #---uic.loadUi essentially loading the widget name into the classes namespace.

        self.init_setup()
        self.Config()
        self.Button01.clicked.connect(self.button)
        self.DirPath_bt.clicked.connect(self.DirectoryPath)
        self.listView_01.doubleClicked.connect(self.excuteMaxScript)
        self.listView_01.clicked.connect(self.Script_Des)

    def Config(self):
        try: # --- 파일 열어서 첫번째 라인 읽고 표시
            config_file = open(scriptPath, 'r')
            line = config_file.readline().decode('utf-8') # --- 한글 경로 불러올시 UTF8로 디코딩.
            self.textEdit.setText(line)
            return line
        except: # --- 파일 없으면 파일 생성후 닫기(디렉토리 웹에서 붙여넣기하면 에러남)
            config_file = open(scriptPath, 'w')
            config_file.close()
            print U"세팅값이 없음."
            return None

    def init_setup(self):
        self.setWindowTitle("ScriptViewer")
        self.move(10, 10)  # ---윈도우창 위치.
        self.setStyleSheet("background-color: white;")
        # --- 디렉토리 다시 선택 할 필요없게 스크립트안에 디렉토리 위치 있으면 실행
        if self.Config: # --- if len(self.Config()) > 1:
            self.getfilelist()

    def button(self):
        QMessageBox.about(self, "message", U"클릭.") #---U 한글깨져서 유니코드 사용.
        print("clicked")

    def DirectoryPath(self):
        targetDir_Ms =unicode (QFileDialog.getExistingDirectory(self, "Select Directory")) #유니코드로 변환후 인/디코딩.

        # --- 디렉토리 선택창 그냥 닫을때 null 오류방지.
        if targetDir_Ms:
            # ---윈도우 슬래쉬 교체.
            targetDir_Ms = targetDir_Ms.replace('\\','/')
            self.textEdit.setText(targetDir_Ms)

            # ---디렉토리 위치 파일에 저장.
            config_file = open(scriptPath, 'w')
            config_file.write(targetDir_Ms.encode('utf-8')) # --- 한글 경로 저장시 UTF8로 인코딩.
            config_file.close()

            self.getfilelist()
            return targetDir_Ms
        else:
            QMessageBox.about(self, "message",  U"파일을 선택하지 않았습니다.")
            print(U"선택되지 않음.")

    def getDirPath(self):
        # --- 설정값 있으면
        if self.Config :
            targetDir = self.Config()
        else:
            targetDir = self.DirectoryPath()
        return targetDir

    def getfilelist(self):
        # --- 기존 목록삭제(중복방지)
        model.clear()
        targetDir = self.getDirPath()
        fileList = sorted(glob.glob(targetDir + "/*.ms")) # --- 파일명으로 정렬 #, key=os.path.getatime)
        print fileList
        view =  self.listView_01

        for file in fileList:
            # --- 스크립트파일명만 보이게 하기위해.
            file = file.split('\\')
            file_item = QStandardItem(file[-1]) # --- 마지막 문자열 선택
            file_item.setSizeHint(QSize(0,50)) # --- 리스트 사이즈

            # --- 아이콘 세팅. https://doc.qt.io/qt-5/qicon.html
            # icon.pixmap(QSize(80, 80)) #--- 일단 여기선 조정 안되고 QT디자이너에서 크기 결정.
            x = model.rowCount()
            icon = QIcon()
            empty_icon =RootPath+"/empty_icon.png"

            if x > len(iconlist)-1:# --- 아이콘 갯수가 스크립트 수보다 적을때(아이콘이 없을때)
                iconlist.append(empty_icon)
            icon.addPixmap(QPixmap(iconlist[x]), QIcon.Normal, QIcon.On)
            file_item.setIcon(icon)

            model.appendRow(file_item)
        view.setModel(model)
        model_Item_Num = model.rowCount()
        print(U'스크립트 개수는 : ' + str(model_Item_Num))

    def Script_Des(self, index):#index에서 넘버링 왜 나오는지는 아직 모르겠네.
        item_num = index.row()#---row  넘버링.
        item_index = model.itemFromIndex(index) #---인덱스로 아이템 구해오기.
        item_text = QStandardItem.text(item_index)#--- 해당 아이템을 텍스트로 가져오기.

        if item_num > len(item_list) -1 :  #---item_num은 0시작 = len(item_list) - 1
            self.textBrowser.setText(U"스크립트에 대한 설명이 없습니다.")
        else : # --- 리스트에서 해당 인덱스 번호의 스크립트 설명 가져오기.
            item_description = item_list[item_num]
            self.textBrowser.setText(item_description)
        return str(item_text)

    def excuteMaxScript(self, index):
        # --- 스크립트 주소
        targetDir = self.getDirPath()

        # --- 스크립트 경로와 스크립트 이름 합침.
        item_text1 = targetDir +"/" + self.Script_Des(index)
        scriptfile = "fileIn" + '"'+ item_text1 +'"'
        try: # --- 맥스에서 맥스스크립트 실행
            MaxPlus.Core.EvalMAXScript(scriptfile)
        except RuntimeError:
            print(U"스크립트가 정상 동작 하지 않습니다.")

# def main():
#    app = QApplication(sys.argv)
#    app = QApplication.instance()
#    if not app:# PySide using QtGui.QApplication(), 3ds Max, there is already a PySide application running, so you get a handle for that object like this:
#        app = QApplication([])
#
#    main = Script_Viewer()
#    main.show()
#    sys.exit((app.exec_()))

if __name__ == '__main__':
    # main()
   main = Script_Viewer()
   main.show()

 

'Script > Python' 카테고리의 다른 글

UE4 에디터 유형별 에셋 및 기타 기능 WIP  (0) 2020.05.20