[maya2022][python3]プログレスバーとかでよくあるパーセンテージの手計算



100が消したいので両方に100かけて


2分の1は0.5なので1割る2

100 *0.5 =50

100 * 現在の値 (1) / 配列の長さ(2) = X

100 *0.5 =50

percent= 100*i/arr_len 

こうなるので

重たい処理を入れないとうまく見えないが。実際に動くサンプル(動かない)

# -*- coding: utf-8 -*-
import os
from functools import partial
import time
import imp


import maya.cmds as cmds
from maya import OpenMaya
import maya.api.OpenMaya as om
from collections import OrderedDict
import math
from pymel.core import *
import pymel.core as pm
import maya.mel as mel

    
try:
    imp.find_module('PySide2')
    from PySide2.QtWidgets import *
    from PySide2.QtGui import *
    from PySide2.QtCore import *

except ImportError:
    from PySide.QtGui import *
    from PySide.QtCore import *


def get_maya_pointer():

    try:
        import maya.cmds as cmds
        from maya import OpenMayaUI

    except ImportError:
        return None


    try:
        imp.find_module("shiboken2")
        import shiboken2
        return shiboken2.wrapInstance(long(OpenMayaUI.MQtUtil.mainWindow()), QWidget)

    except ImportError:
        import shiboken
        return shiboken.wrapInstance(long(OpenMayaUI.MQtUtil.mainWindow()), QWidget)

class Sample_UI(QMainWindow):

    def __init__(self, parent = None):
        super(Sample_UI, self).__init__(parent)

        self.setObjectName("Sample_Window")
        self.setWindowTitle("Sample Window")
        #self._initUI()
        self.errorDialog = QErrorMessage(self) 
           
    def _initUI(self):
        wrapper = QWidget()
        self.setCentralWidget(wrapper)

        mainLayout = QVBoxLayout()
        self.havyFunc()
    
    def _showProgressDialog(self):
        print("---------------------ProgressBar Starting--------------------------")

        self.max = 100
        self.progressDialog = QProgressDialog("Progress...", "Cancel", 0, self.max, self)
        self.progressDialog.setWindowTitle("Progress Dialog")
    
    def setProgress(self,count):
        print("---------------------setProgress ( "+str(count)+"/100 )--------------------------")
        qApp.processEvents()
        if self.progressDialog.wasCanceled():
            self.progressDialog.setValue(100)
        self.progressDialog.setValue(count)
        self.progressDialog.setLabelText("Progress... %d %%" % count)

    def havyfunc(self):
        
        #--------------------------------------------------
        self._showProgressDialog()
        self.setProgress(1)
        #--------------------------------------------------
        duplicatedMesh_vtx_arr=[1,2,3,4,5]
        arr_len=len(duplicatedMesh_vtx_arr)
        for i in range(0,duplicatedMesh_vtx_arr_len):
            #---------------------------------------------------
            parcent=(100*i/duplicatedMesh_vtx_arr_len) /2
            self.setProgress(parcent)
            print("setProgress("+str(parcent)+")")
            #---------------------------------------------------
            #重たい処理1
        
        for i in range(0,duplicatedMesh_vtx_arr_len):
            
            #---------------------------------------------------
            parcent=(100*i/duplicatedMesh_vtx_arr_len) /2 +50
            
            self.setProgress(parcent)
            
            print("setProgress("+str(parcent)+")")
            
            #---------------------------------------------------
            #重たい処理2
              
        #--------------------------------------
        self.setProgress(100)
        print("setProgress("+str(100)+")")
        #--------------------------------------
           
def start():
    maya_win = get_maya_pointer()
    ui = Sample_UI(parent = maya_win)
    #ui= MyDialog()
    ui.show()
    return ui

def starter():
    app = QApplication.instance()
    if app is None:
        app = QApplication([])
    ui = start()
    app.exec_()

print("__name__= "+__name__)
#if __name__ == '__main__':
if __name__ == 'NppMaya' or __name__ == '__main__':
    starter()

いっこめの重い処理

parcent=(100*i/duplicatedMesh_vtx_arr_len) /2

にこめの重い処理

parcent=(100*i/duplicatedMesh_vtx_arr_len) /2 +50

こんなんなる。

よくこんなスクラップブックで計算したりする。

うごかないので更新しておいた。



# -*- coding: utf-8 -*-
import os
from functools import partial
import time
import imp

"""
PySide2モジュールを探し、ある場合はそちらをインポートします。
"""
try:
    imp.find_module('PySide2')
    from PySide2.QtWidgets import *
    from PySide2.QtGui import *
    from PySide2.QtCore import *

except ImportError:
    from PySide.QtGui import *
    from PySide.QtCore import *


LOGO_IMAGE = r"画像のパスをここに入れてください。"


def get_maya_pointer():
    """
    Mayaのメインウィンドウを取得する関数
    """
    try:
        import maya.cmds as cmds
        from maya import OpenMayaUI

    except ImportError:
        return None

    """
    実は2017ではshibokenも2になっているので、あればshiboken2をインポートします。
    """
    try:
        imp.find_module("shiboken2")
        import shiboken2
        return shiboken2.wrapInstance(int(OpenMayaUI.MQtUtil.mainWindow()), QWidget)

    except ImportError:
        import shiboken
        return shiboken.wrapInstance(int(OpenMayaUI.MQtUtil.mainWindow()), QWidget)






class DF_TalkUI(QMainWindow):


    def __init__(self, parent = None):
        super(DF_TalkUI, self).__init__(parent)
        self.setObjectName("DF_Talk_Window")
        self.setWindowTitle("DF Talk Window")
        #self._initUI()
        self.errorDialog = QErrorMessage(self) # QErrorMessageインスタンスの保持


    def myInit(self,qApp):
        self.qApp=qApp
        wrapper = QWidget()
        self.setCentralWidget(wrapper)

        mainLayout = QVBoxLayout()
        wrapper.setLayout(mainLayout)

        #-----------------------------------------------------------------------
        # sixth row
        #-----------------------------------------------------------------------
        sixthHorizontalArea = QHBoxLayout()
        sixthHorizontalArea.setSpacing(20)
        mainLayout.addLayout(sixthHorizontalArea)



        progressDialogBtn = QPushButton("Progress Dialog")
        sixthHorizontalArea.addWidget(progressDialogBtn)
        progressDialogBtn.clicked.connect(self._showProgressDialog)


        #-----------------------------------------------------------------------
        # seventh row
        #-----------------------------------------------------------------------




    def _makeHorizontalLine(self):
        hline = QFrame()
        hline.setFrameShape(QFrame.HLine)
        hline.setFrameShadow(QFrame.Sunken)
        return hline


    def _showProgressDialog(self):
        """
        QProgressDialog表示スロット
        """
        max = 100
        progressDialog = QProgressDialog("Progress...", "Cancel", 0, max, self)
        progressDialog.setWindowTitle("Progress Dialog")

        for count in range(max+1):
            self.qApp.processEvents()

            if progressDialog.wasCanceled():
                break

            progressDialog.setValue(count)
            progressDialog.setLabelText("Progress... %d %%" % count)
            time.sleep(0.1)






def start(app):
    maya_win = get_maya_pointer()
    ui = DF_TalkUI(parent = maya_win)
    ui.myInit(app)
    ui.show()
    return ui


if __name__ == '__main__':

    app = QApplication.instance()
    if app is None:
        app = QApplication([])
    ui = start(app)
    app.exec_()

動くように直したもの



# -*- coding: utf-8 -*-
import os
from functools import partial
import time
import imp

"""
PySide2モジュールを探し、ある場合はそちらをインポートします。
"""
try:
    imp.find_module('PySide2')
    from PySide2.QtWidgets import *
    from PySide2.QtGui import *
    from PySide2.QtCore import *

except ImportError:
    from PySide.QtGui import *
    from PySide.QtCore import *


LOGO_IMAGE = r"画像のパスをここに入れてください。"


def get_maya_pointer():
    """
    Mayaのメインウィンドウを取得する関数
    """
    try:
        import maya.cmds as cmds
        from maya import OpenMayaUI

    except ImportError:
        return None

    """
    実は2017ではshibokenも2になっているので、あればshiboken2をインポートします。
    """
    try:
        imp.find_module("shiboken2")
        import shiboken2
        return shiboken2.wrapInstance(int(OpenMayaUI.MQtUtil.mainWindow()), QWidget)

    except ImportError:
        import shiboken
        return shiboken.wrapInstance(int(OpenMayaUI.MQtUtil.mainWindow()), QWidget)






class DF_TalkUI(QMainWindow):


    def __init__(self, parent = None):
        super(DF_TalkUI, self).__init__(parent)
        self.setObjectName("DF_Talk_Window")
        self.setWindowTitle("DF Talk Window")
        #self._initUI()
        self.errorDialog = QErrorMessage(self) # QErrorMessageインスタンスの保持
        

    def myInit(self,qApp):
        self.qApp=qApp
        wrapper = QWidget()
        self.setCentralWidget(wrapper)

        mainLayout = QVBoxLayout()
        wrapper.setLayout(mainLayout)

        #-----------------------------------------------------------------------
        # sixth row
        #-----------------------------------------------------------------------
        sixthHorizontalArea = QHBoxLayout()
        sixthHorizontalArea.setSpacing(20)
        mainLayout.addLayout(sixthHorizontalArea)



        progressDialogBtn = QPushButton("Progress Dialog")
        sixthHorizontalArea.addWidget(progressDialogBtn)
        progressDialogBtn.clicked.connect(self.havyfunc)


        #-----------------------------------------------------------------------
        # seventh row
        #-----------------------------------------------------------------------
        #self.havyfunc()

    def _showProgressDialog(self):
        print("---------------------ProgressBar Starting--------------------------")

        self.max = 100
        self.progressDialog = QProgressDialog("Progress...", "Cancel", 0, self.max, self)
        self.progressDialog.setWindowTitle("Progress Dialog")
        self.progressDialog.show()
    
    def setProgress(self,count):
        print("---------------------setProgress ( "+str(count)+"/100 )--------------------------")
        self.qApp.processEvents()
        if self.progressDialog.wasCanceled():
            self.progressDialog.setValue(100)
        self.progressDialog.setValue(count)
        self.progressDialog.setLabelText("Progress... %d %%" % count)


    def havyfunc(self):
        
        #--------------------------------------------------
        self._showProgressDialog()
        self.setProgress(1)
        #--------------------------------------------------
        duplicatedMesh_vtx_arr=[1,2,3,4,5]
        duplicatedMesh_vtx_arr_len=len(duplicatedMesh_vtx_arr)
        for i in range(0,duplicatedMesh_vtx_arr_len):
            #---------------------------------------------------
            parcent=(100*i/duplicatedMesh_vtx_arr_len) /2
            self.setProgress(parcent)
            print("setProgress("+str(parcent)+")")
            time.sleep(0.1)
            #---------------------------------------------------
            #重たい処理1
        
        for i in range(0,duplicatedMesh_vtx_arr_len):
            
            #---------------------------------------------------
            parcent=(100*i/duplicatedMesh_vtx_arr_len) /2 +50
            
            self.setProgress(parcent)
            
            print("setProgress("+str(parcent)+")")
            time.sleep(0.1)
            #---------------------------------------------------
            #重たい処理2
              
        #--------------------------------------
        self.setProgress(100)
        print("setProgress("+str(100)+")")
        #--------------------------------------


    def _makeHorizontalLine(self):
        hline = QFrame()
        hline.setFrameShape(QFrame.HLine)
        hline.setFrameShadow(QFrame.Sunken)
        return hline

    """
    def _showProgressDialog(self):
        
        #QProgressDialog表示スロット
        
        max = 100
        progressDialog = QProgressDialog("Progress...", "Cancel", 0, max, self)
        progressDialog.setWindowTitle("Progress Dialog")

        for count in range(max+1):
            self.qApp.processEvents()

            if progressDialog.wasCanceled():
                break

            progressDialog.setValue(count)
            progressDialog.setLabelText("Progress... %d %%" % count)
            time.sleep(0.1)
    """





def start(app):
    maya_win = get_maya_pointer()
    ui = DF_TalkUI(parent = maya_win)
    ui.myInit(app)
    ui.show()
    return ui


if __name__ == '__main__':

    app = QApplication.instance()
    if app is None:
        app = QApplication([])
    ui = start(app)
    app.exec_()

[maya2022][Pyside2][python3]widget_galleryを動くように変更



# -*- coding: utf-8 -*-
import os
from functools import partial
import time
import imp

"""
PySide2モジュールを探し、ある場合はそちらをインポートします。
"""
try:
    imp.find_module('PySide2')
    from PySide2.QtWidgets import *
    from PySide2.QtGui import *
    from PySide2.QtCore import *

except ImportError:
    from PySide.QtGui import *
    from PySide.QtCore import *


LOGO_IMAGE = r"画像のパスをここに入れてください。"


def get_maya_pointer():
    """
    Mayaのメインウィンドウを取得する関数
    """
    try:
        import maya.cmds as cmds
        from maya import OpenMayaUI

    except ImportError:
        return None

    """
    実は2017ではshibokenも2になっているので、あればshiboken2をインポートします。
    """
    try:
        imp.find_module("shiboken2")
        import shiboken2
        return shiboken2.wrapInstance(int(OpenMayaUI.MQtUtil.mainWindow()), QWidget)

    except ImportError:
        import shiboken
        return shiboken.wrapInstance(int(OpenMayaUI.MQtUtil.mainWindow()), QWidget)



class MyDialog(QDialog):


    def __init__(self, parent = None, f = 0):
        super(MyDialog, self).__init__(parent, f)
        #-----------------------------------------------------------------------
        # Layout
        #-----------------------------------------------------------------------
        mainLayout = QVBoxLayout()
        self.setLayout(mainLayout)
        #-----------------------------------------------------------------------
        # Image
        #-----------------------------------------------------------------------
        imageWidget = QLabel()
        imageWidget.setPixmap(QPixmap(LOGO_IMAGE))
        mainLayout.addWidget(imageWidget)
        #-----------------------------------------------------------------------
        # Description
        #-----------------------------------------------------------------------
        description = QLabel("This is coustom dialog.")
        mainLayout.addWidget(description)
        #-----------------------------------------------------------------------
        # Text input
        #-----------------------------------------------------------------------
        self._inputWidget = QLineEdit()
        mainLayout.addWidget(self._inputWidget)
        #-----------------------------------------------------------------------
        # Buttons
        #-----------------------------------------------------------------------
        buttonArea = QHBoxLayout()
        mainLayout.addLayout(buttonArea)
        buttonArea.addStretch()
        okBtn = QPushButton("OK")
        buttonArea.addWidget(okBtn)
        okBtn.clicked.connect(self.accept)
        cancelBtn = QPushButton("Cancel")
        buttonArea.addWidget(cancelBtn)
        cancelBtn.clicked.connect(self.reject)


    def getInputText(self):
        return self._inputWidget.text()


class DF_TalkUI(QMainWindow):


    def __init__(self, parent = None):
        super(DF_TalkUI, self).__init__(parent)
        self.setObjectName("DF_Talk_Window")
        self.setWindowTitle("DF Talk Window")
        #self._initUI()
        self.errorDialog = QErrorMessage(self) # QErrorMessageインスタンスの保持


    def myInit(self,qApp):
        self.qApp=qApp
        wrapper = QWidget()
        self.setCentralWidget(wrapper)

        mainLayout = QVBoxLayout()
        wrapper.setLayout(mainLayout)

        #-----------------------------------------------------------------------
        # First row
        #-----------------------------------------------------------------------
        firstHolizontalArea = QHBoxLayout()
        firstHolizontalArea.setSpacing(20)
        mainLayout.addLayout(firstHolizontalArea)

        labelArea = QVBoxLayout()
        firstHolizontalArea.addLayout(labelArea)

        labelWidget = QLabel("Text is shown like this.")
        labelArea.addWidget(labelWidget)

        imageWidget = QLabel()
        imageWidget.setPixmap(QPixmap(LOGO_IMAGE))
        labelArea.addWidget(imageWidget)
        labelArea.addStretch()

        textArea = QTextEdit()
        textArea.setPlainText("Text are\ncan be set\nmultiple lines and HTML.")
        firstHolizontalArea.addWidget(textArea)

        mainLayout.addWidget(self._makeHorizontalLine())

        #-----------------------------------------------------------------------
        # Second row
        #-----------------------------------------------------------------------
        secondHolizontalArea = QHBoxLayout()
        secondHolizontalArea.setSpacing(20)
        mainLayout.addLayout(secondHolizontalArea)

        lineEdit = QLineEdit()
        lineEdit.setMaximumWidth(200)
        lineEdit.setText("This widget is useful for inputting text")
        secondHolizontalArea.addWidget(lineEdit)

        comboBox = QComboBox()
        comboBox.addItems(["This", "is", "combobox", "it's", "useful"])
        comboBox.setEditable(True)
        comboBox.setInsertPolicy(QComboBox.NoInsert)
        comboBox.completer().setCompletionMode(QCompleter.PopupCompletion)
        secondHolizontalArea.addWidget(comboBox)

        spinBox = QSpinBox()
        spinBox.setMinimum(0)
        spinBox.setMaximum(10)
        spinBox.setSuffix("min")
        secondHolizontalArea.addWidget(spinBox)

        mainLayout.addWidget(self._makeHorizontalLine())

        #-----------------------------------------------------------------------
        # Third row
        #-----------------------------------------------------------------------
        thirdHorizontalArea = QHBoxLayout()
        thirdHorizontalArea.setSpacing(20)
        mainLayout.addLayout(thirdHorizontalArea)

        checkBox = QCheckBox("Check box")
        thirdHorizontalArea.addWidget(checkBox)
        checkBox.setChecked(True)

        radioArea = QVBoxLayout()
        thirdHorizontalArea.addLayout(radioArea)

        radioGroup = QButtonGroup(self)
        radioBtn1 = QRadioButton("Option 1")
        radioArea.addWidget(radioBtn1)
        radioGroup.addButton(radioBtn1)
        radioBtn2 = QRadioButton("Option 2")
        radioArea.addWidget(radioBtn2)
        radioGroup.addButton(radioBtn2)
        radioBtn3 = QRadioButton("Option 3")
        radioArea.addWidget(radioBtn3)
        radioGroup.addButton(radioBtn3)
        radioBtn1.setChecked(True)

        mainLayout.addWidget(self._makeHorizontalLine())

        #-----------------------------------------------------------------------
        # Fourth row
        #-----------------------------------------------------------------------
        fourthHorizontalArea = QHBoxLayout()
        fourthHorizontalArea.setSpacing(20)
        mainLayout.addLayout(fourthHorizontalArea)

        calender = QCalendarWidget()
        fourthHorizontalArea.addWidget(calender)
        calender.setMaximumWidth(300)

        lcdNumber = QLCDNumber()
        fourthHorizontalArea.addWidget(lcdNumber)
        lcdNumber.display(1234)

        sliderArea = QVBoxLayout()
        fourthHorizontalArea.addLayout(sliderArea)

        sliderDisplay = QLabel("0")
        sliderArea.addWidget(sliderDisplay)
        slider = QSlider(Qt.Horizontal)
        sliderArea.addWidget(slider)
        slider.setRange(0, 100)
        slider.setTickPosition(QSlider.TicksBothSides)
        slider.setSingleStep(5)
        slider.setPageStep(10)
        slider.setTickInterval(10)
        slider.valueChanged.connect(lambda val: sliderDisplay.setText(str(val)))
        slider.setValue(0)

        dialDisplay = QLabel("0")
        sliderArea.addWidget(dialDisplay)
        dial = QDial()
        sliderArea.addWidget(dial)
        dial.setRange(0, 100)
        dial.setSingleStep(5)
        dial.setPageStep(10)
        dial.setNotchesVisible(True)
        dial.setWrapping(True)
        dial.setNotchTarget(5)
        dial.valueChanged.connect(lambda val: dialDisplay.setText(str(val)))
        dial.setValue(0)

        mainLayout.addWidget(self._makeHorizontalLine())

        #-----------------------------------------------------------------------
        # fifth row
        #-----------------------------------------------------------------------
        fifthHorizontalArea = QHBoxLayout()
        fifthHorizontalArea.setSpacing(20)
        mainLayout.addLayout(fifthHorizontalArea)

        fifthHorizontalArea.addWidget(self._makeListWidget())
        fifthHorizontalArea.addWidget(self._makeTableWidget())
        fifthHorizontalArea.addWidget(self._makeTreeWidget())

        mainLayout.addWidget(self._makeHorizontalLine())

        #-----------------------------------------------------------------------
        # sixth row
        #-----------------------------------------------------------------------
        sixthHorizontalArea = QHBoxLayout()
        sixthHorizontalArea.setSpacing(20)
        mainLayout.addLayout(sixthHorizontalArea)

        msgBoxBtn = QPushButton("Message Dialog")
        sixthHorizontalArea.addWidget(msgBoxBtn)
        msgBoxBtn.clicked.connect(partial(QMessageBox().information, self, "Message", "This is normal information message."))

        colorDialogBtn = QPushButton("Color Dialog")
        sixthHorizontalArea.addWidget(colorDialogBtn)
        colorDialogBtn.clicked.connect(self._showColorDialog)

        progressDialogBtn = QPushButton("Progress Dialog")
        sixthHorizontalArea.addWidget(progressDialogBtn)
        progressDialogBtn.clicked.connect(self._showProgressDialog)

        fileDialogBtn = QPushButton("File Dialog")
        sixthHorizontalArea.addWidget(fileDialogBtn)
        fileDialogBtn.clicked.connect(partial(QFileDialog.getOpenFileName, self, "File Select", options = QFileDialog.DontUseNativeDialog))

        #-----------------------------------------------------------------------
        # seventh row
        #-----------------------------------------------------------------------
        seventhHorizontalArea = QHBoxLayout()
        seventhHorizontalArea.setSpacing(20)
        mainLayout.addLayout(seventhHorizontalArea)

        errorMsgBtn = QPushButton("Error Dialog")
        seventhHorizontalArea.addWidget(errorMsgBtn)
        errorMsgBtn.clicked.connect(self._showErrorDialog)

        inputDialogTextBtn = QPushButton("Input (text)")
        seventhHorizontalArea.addWidget(inputDialogTextBtn)
        inputDialogTextBtn.clicked.connect(self._showInputTextDialog)

        inputDialogComboBtn = QPushButton("Input (combo)")
        seventhHorizontalArea.addWidget(inputDialogComboBtn)
        inputDialogComboBtn.clicked.connect(self._showInputComboDialog)

        dialogBtn = QPushButton("Custom Dialog")
        seventhHorizontalArea.addWidget(dialogBtn)
        dialogBtn.clicked.connect(self._showCustomDialog)

        #-----------------------------------------------------------------------
        # dock widget
        #-----------------------------------------------------------------------
        dockWidget = QDockWidget("Dock Window", self)
        dockWrapper = QWidget()
        dockWidget.setWidget(dockWrapper)
        dockWidget.setAllowedAreas(Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea)
        dockLayout = QVBoxLayout()
        dockWrapper.setLayout(dockLayout)
        dockDescription = QLabel("This is dock widget contents.")
        dockLayout.addWidget(dockDescription)
        dockButton = QPushButton("OK")
        dockLayout.addWidget(dockButton)
        self.addDockWidget(Qt.BottomDockWidgetArea, dockWidget)


    def _makeHorizontalLine(self):
        hline = QFrame()
        hline.setFrameShape(QFrame.HLine)
        hline.setFrameShadow(QFrame.Sunken)
        return hline


    def _makeListWidget(self):
        """
        QListWidgetを作成する関数
        """
        listWidget = QListWidget()
        listWidget.setMaximumWidth(100)
        listWidget.addItems(["this", "is", "list", "widget"])
        return listWidget


    def _makeTableWidget(self):
        """
        QTableWidgetを作成する関数
        """
        tableWidget = QTableWidget()
        headerLabels = ["Name", "Age", "Sex"]
        tableWidget.setColumnCount(len(headerLabels))
        tableWidget.setHorizontalHeaderLabels(headerLabels)
        tableWidget.verticalHeader().setVisible(False)

        try:
            tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)

        except:
            tableWidget.horizontalHeader().setResizeMode(QHeaderView.Interactive)

        tableWidget.setAlternatingRowColors(True)
        tableWidget.horizontalHeader().setStretchLastSection(True)
        dataList = [
            ["Taro",    "25", "Male"],
            ["Hanako",  "30", "Female"],
            ["Ichiro",  "50", "Male"],
            ["Jiro",    "40", "Male"]
        ]
        tableWidget.setRowCount(len(dataList))

        for row, colData in enumerate(dataList):

            for col, value in enumerate(colData):
                item = QTableWidgetItem(value)
                tableWidget.setItem(row, col, item)

        return tableWidget


    def _makeTreeWidget(self):
        """
        QTreeWidgetを作成する関数
        """
        treeWidget = QTreeWidget()
        headerLabels = ["Name", "Age"]
        treeWidget.setColumnCount(len(headerLabels))
        treeWidget.setHeaderLabels(headerLabels)
        treeWidget.setAlternatingRowColors(True)
        treeData = {
            "Male":[
                {"name":"Taro",     "age":"25"},
                {"name":"Ichiro",   "age":"50"},
                {"name":"Jiro",     "age":"40"}
            ],
            "Female":[
                {"name":"Hanako",   "age":"30"}
            ]
        }

        for sex, profiles in treeData.items():
            topItem = QTreeWidgetItem([sex])
            treeWidget.addTopLevelItem(topItem)

            for profile in profiles:
                childItem = QTreeWidgetItem(topItem, [profile.get("name"), profile.get("age")])

        treeWidget.expandAll()
        return treeWidget


    def _showColorDialog(self):
        """
        QColorDialog表示スロット
        """
        colorDialog = QColorDialog(self)
        response = colorDialog.exec_()

        if response != QDialog.Accepted:
            return

        chosen = colorDialog.currentColor()
        print("Selected color >> (%d, %d, %d)" % (chosen.red(), chosen.green(), chosen.blue()))


    def _showProgressDialog(self):
        """
        QProgressDialog表示スロット
        """
        max = 100
        progressDialog = QProgressDialog("Progress...", "Cancel", 0, max, self)
        progressDialog.setWindowTitle("Progress Dialog")

        for count in range(max+1):
            self.qApp.processEvents()

            if progressDialog.wasCanceled():
                break

            progressDialog.setValue(count)
            progressDialog.setLabelText("Progress... %d %%" % count)
            time.sleep(0.1)


    def _showErrorDialog(self):
        """
        QErrorMessage表示スロット
        """
        self.errorDialog.showMessage("This is error message.")


    def _showInputTextDialog(self):
        """
        QInputDialog表示スロット(文字列入力型)
        """
        response = QInputDialog.getText(self,
                                    "Input Text",
                                    "Input text here.")
        print(response)


    def _showInputComboDialog(self):
        """
        QInputDialog表示スロット(アイテム選択型)
        """
        response = QInputDialog.getItem(self,
                                    "Select Item",
                                    "Select item from the combo box.",
                                    ["item1", "item2", "item3", "item4"],
                                    editable=False)
        print(response)


    def _showCustomDialog(self):
        """
        MyDialog表示スロット
        """
        dialog = MyDialog()
        response = dialog.exec_()

        if response == QDialog.Accepted:
            print(dialog.getInputText())


def start(app):
    maya_win = get_maya_pointer()
    ui = DF_TalkUI(parent = maya_win)
    ui.myInit(app)
    ui.show()
    return ui


if __name__ == '__main__':

    app = QApplication.instance()
    if app is None:
        app = QApplication([])
    ui = start(app)
    app.exec_()

[UE5.3.2][Niagara][Animation Montage]Animation MontageのNotifyからNiagaraのUserParameterをSetする方法

How to set Niagara User Parameter from Animation Montage

BluePrintを新規作成してAnimNotify_PlayNiagaraEffectを選択名前はてきとうに「AnimNotify_NiagaraSetParam」

FUNCTIONS > Override>Received Notifyを選択

こんな風にしておく

NiagaraSystemを作り一番上のボタンからSingleLoopParticleを選んで作成し

User Parameterの+ボタンから「Linear Color」を選択し作成

Particle SpawnにColorを追加してから作ったColor1をドラッグする。

見やすくするためにサイズを大きくしておく

AnimMontageに作ったNotifyを設定して

Color1に緑を設定してNaiagaraga緑になったらおわり

[UE5.3.2][Retarget]IK RetargeterでのT_PoseのキャラクターをAポーズベースのモーションへのリターゲット方法

UE5.3.2 Retarget IK RetargeterでのT_Poseのキャラクターのリターゲット方法

MannyのモーションをT_Poseのキャラクターにリターゲットする方法

Showing Reterget Poseモードにして>Sourceタブを選択して>Create>Import from Animation Sequence を選択

デフォルトで用意されている.AnimSequenceの
/Game/Characters/Mannequins/Animations/Manny/MM_T_Poseを読み込む

反映されればMannyがTposeになる。

Showing Reterget Poseモードボタンを押してRunning Retargetモードにすると

TposeのキャラがAposeになる。

[maya]スキンウェイトを部分的に頂点を選択してコピーしたい。

スキンウェイトを部分的に頂点を選択してコピーしたい。

1 つの頂点からウェイトをコピーする
1 つの頂点を選択し、そのウェイト値を選択したその他の頂点にコピーすることができます。ウェイト値をペーストする頂点は、同じメッシュ上にあっても別のメッシュ上にあっても構いません。

スキン ポイントのウェイト値をコピーしてペーストするには

スキン ウェイト ペイント ツール(Paint Skin Weights Tool)で、選択(Select)またはペイント選択(Paint Select)モードに切り替えます。

ウェイト値をコピーする頂点を選択し、コピー ツール アイコン をクリックします。ウェイト

値をペーストする頂点を選択し、ペースト ツール アイコン をクリックします。コピーしたウェイト値が選択したすべての頂点にペーストされます。

注:
メッシュから別のメッシュにウェイト値をペーストする場合、ソースの頂点に対応するウェイト値のインフルエンスがターゲット メッシュに見つからない場合はエラーが表示されます。

次のホットキーを使用して、頂点から頂点にウェイト値をコピーしてペーストすることもできます。

(Windows) [Alt]+[Ctrl]+[C]、[Alt]+[Ctrl]+[V]
(Mac OS X) [Option]+[Control]+[C]、[Option]+[Control]+[V]


スキンウェイトを部分的に頂点を選択してコピーしたい。がうまくいかない。

// エラー: file: C:/Program Files/Autodesk/Maya2022/scripts/others/artAttrSkinWeightCopy.mel line 22: 選択した項目が多すぎます。ウェイトをコピーする頂点を 1 つだけ選択してください。 //

C:/Program Files/Autodesk/Maya2022/scripts/others/artAttrSkinWeightPaste.mel

1回コピーさせてペーストするのをループさせればできる?

と思って作ったが、いらなくなったコードサンプル 参考にしかならないけど乗せておく。

global proc artAttrSkinWeightCopy_One()
{
    global string $gSkinWeightCopyInfluences[];
    global float $gSkinWeightCopyWeights[];
    
    string $sel[] = `ls -sl -flatten`;
    if(size($sel) < 1) {
        error("選択した項目がありません。ウェイトをコピーする頂点を 1 つだけ選択してください。");		
		return;
    }
    
    if(size($sel) > 1) {
        error("選択した項目が多すぎます。ウェイトをコピーする頂点を 1 つだけ選択してください。");
		return;
    }
    
    string $skinCluster = findSkinClusterFromSelectedComponent($sel[0]);
    if($skinCluster == "")
        return;
    $gSkinWeightCopyInfluences = `skinCluster -q -influence $skinCluster`;
    $gSkinWeightCopyWeights = `skinPercent -q -v $skinCluster`;
            
    
}
global proc artAttrSkinWeightCopy_multiSelect_test()
{
    global string $gSkinWeightCopyInfluences[];
    global float $gSkinWeightCopyWeights[];
    
    string $sel[] = `ls -sl -flatten`;
    if(size($sel) < 1) {
        error("選択した項目がありません。ウェイトをコピーする頂点を 1 つ以上だけ選択してください。");		
		return;
    }
    
    if(size($sel) > 1) {
        error("選択した項目が多すぎます。ウェイトをコピーする頂点を 1 つだけ選択してください。");
		return;
    }
    
    string $skinCluster = findSkinClusterFromSelectedComponent($sel[0]);
    if($skinCluster == "")
        return;
    $gSkinWeightCopyInfluences = `skinCluster -q -influence $skinCluster`;
    print("$gSkinWeightCopyInfluences--------------\n");
    print($gSkinWeightCopyInfluences);
    print("\n--------------\n");
    $gSkinWeightCopyWeights = `skinPercent -q -v $skinCluster`;
    print("$gSkinWeightCopyWeights--------------\n");
    $gSkinWeightCopyWeights_Str=floatArrayToString($gSkinWeightCopyWeights, ",");
    print("$gSkinWeightCopyWeights_Str= "+$gSkinWeightCopyWeights_Str);
    print("\n--------------\n");
}
global proc artAttrSkinWeightCopy_multiSelect2()
{
    $OldSelectVtx = `ls -sl`;
    print("$OldSelectVtx");
    $OldSelectVtx_Str = stringArrayToString($OldSelectVtx, ",");
    print("$OldSelectVtx_Str= "+$OldSelectVtx_Str+"\n");
    
    //UIで選択しておく
    $BaseMesh = "|Mesh|Arm_Only5";
    $PastMesh = "|Mesh|Jacket_For_ShortSkirtUV";
    select($BaseMesh);
    string $selectBaseVtx[] = `polyInfo -nonManifoldVertices`; 
    //string $selectBaseVtx[] = `ls -sl -flatten`; 
    select($PastMesh);
    string $selectPastVtx[] = `polyInfo -nonManifoldVertices`; 
    //string $selectPastVtx[] = `ls -sl -flatten`; 
    
    //選択した頂点を再選択
    select($OldSelectVtx);
    
    $selectBaseVtx_len = `size($selectBaseVtx)`;
    $selectBaseVtx_Str = stringArrayToString($selectBaseVtx, ",");
    print("$selectBaseVtx_Str= "+$selectBaseVtx_Str+"\n");
    print("$selectBaseVtx_len= "+$selectBaseVtx_len+"\n");
    
    for($i = 0; $i < $selectBaseVtx_len; $i++)
    {
	    select($selectBaseVtx[$i]);
	    print("$selectBaseVtx["+$i+"] \n");
	    //artAttrSkinWeightCopy;
	    select($selectPastVtx[$i]);
	    print("$selectPastVtx["+$i+"] \n");
	    //artAttrSkinWeightPaste;
    }
    
    select($OldSelectVtx);
}
artAttrSkinWeightCopy_multiSelect2();

参考URL
https://help.autodesk.com/view/MAYACRE/JPN/?guid=GUID-7D895BB0-1522-4388-96E0-4245127F90AB

[php] [chat]シンプルなIPアドレスファイル名ルームでのチャットを作った。

お客様のチャット

<!-- chat.php -->

<?php
function trace($txt){
    //print($txt);
    $a="a";
}
class RoomLog
{
    
    public $LOG_FILE_NAME;
    public $name;
    public $SPLIT_Str;
    public $message;
    public function get_ip_file_name(){
        global $_SERVER;
        $ip_Address=$_SERVER['REMOTE_ADDR'];
        print("ip_Address= " . $ip_Address . "<br>");
        if($ip_Address=="::1"){
            $ip_Address="192.168.1.29";
            print("テストのためip変数上書きしました。ip_Address= " . $ip_Address . "<br>");
        }
        $ip_Address_Arr = explode(".", $ip_Address);
        $ip_file_name = join('_', $ip_Address_Arr);
        $ip_file_name = "log/ip_" . $ip_file_name . "_chatlog.txt";
        print("ip_file_name= " . $ip_file_name . "<br>");
        return $ip_file_name;
    }
    public function initLog(){
        trace("■ initLog()<br>");
        global $LOG_FILE_NAME;
        global $name;
        global $SPLIT_Str;
        global $message;
        
        $ip_file_name=$this->get_ip_file_name();
        
        // データを書き込むファイルの名前
        //$LOG_FILE_NAME = "chat_class_txt_log.txt";
        $LOG_FILE_NAME = $ip_file_name;
     
        // 区切りのための文字列
        $SPLIT_Str = "|-|";
     
        // 名前を格納する変数
        $name = "お客様";
        // メッセージを格納する変数
        $message = "";
        
        $this->LOG_FILE_NAME=$LOG_FILE_NAME;
        $this->name=$name;
        $this->SPLIT_Str=$SPLIT_Str;
        $this->message=$message;
        /*
        trace("<br>");
        trace("this->LOG_FILE_NAME= " . $this->LOG_FILE_NAME . "<br>");
        trace("this->name= " . $this->name . "<br>");
        trace("this->SPLIT_Str= " . $this->SPLIT_Str . "<br>");
        trace("this->message= " . $this->message . "<br>");
        */
    }
    
    public function startMain(){
        trace("■ startMain()<br>");
        $this->initLog();
        $this->CheckFormPostData();
        $this->LogShow();
    }
    

    public function CheckFormPostData(){
        trace("■ CheckFormPostData()<br>");
        global $_POST;
        
        $name = $this->name;
        $SPLIT_Str = $this->SPLIT_Str;
        $message = $this->message;
        
        
        // 送信されたデータ
        $_POST_string = join(', ', $_POST);
        trace("_POST_string2= " . $_POST_string . "<br>");
        
        if (empty($_POST)) {
            trace("The form is empty.");
        } else {
            trace("Form data is present.");
        }
        
        // 送信された名前とメッセージを変数に代入
        if (isset($_POST['name'])) {
          $name = $_POST['name'];
     
          if (strpos($name, $SPLIT_Str) !== false) {
            // 名前に区切り文字が含まれている場合の処理
            echo "使用できない文字列「|-|」が含まれています。";
            return;
          }
     
          if ($name == "") {
            $name = "お客様";
          }
        }
        if (isset($_POST['message'])) {
          $message = $_POST['message'];
     
          if (strpos($message, $SPLIT_Str) !== false) {
            // メッセージに区切り文字が含まれている場合の処理
            echo "使用できない文字列「|-|」が含まれています。";
            return;
          }
     
          //$this->LOG_FILE_NAME=$LOG_FILE_NAME;
          $this->name=$name;
          //$this->SPLIT_Str=$SPLIT_Str;
          $this->message=$message;
          $this->LogWrite();
        }
    }
   
    
    public function LogWrite(){
      trace("■ LogWrite()<br>");
      $LOG_FILE_NAME = $this->LOG_FILE_NAME;
      $name = $this->name;
      $SPLIT_Str = $this->SPLIT_Str;
      $message = $this->message;
        
      //書き込みモードでファイルを開く
      $fp = fopen($LOG_FILE_NAME, "a") or exit($LOG_FILE_NAME . "が開けません");
 
      // | を区切り文字として2つのデータを繋げて書き込む
      fwrite($fp, $name . $SPLIT_Str . $message . "\n");
      
      
      // リダイレクトのためのHTTPヘッダーを送信
      //header("Location: " . $_SERVER['PHP_SELF'], true, 303);
      
      fclose($fp);
    }

    function LogShow(){
        trace("■ LogShow()<br>");
        //global $LOG_FILE_NAME;
        global $linesNum;
        global $lines;
        $LOG_FILE_NAME = $this->LOG_FILE_NAME;
        //$name = $this->name;
        //$SPLIT_Str = $this->SPLIT_Str;
        //$message = $this->message;
        
        if (!file_exists($LOG_FILE_NAME)) {
          // ファイルがない場合
          echo "書き込みはありません。";
     
          $linesNum = 0;
        } else {
     
          // ファイルの全行を読み取る
          $lines = file($LOG_FILE_NAME);
     
          // 読み込んだ行数
          $linesNum = count($lines);
        }
    }
    
}

$RoomLog_ins = new RoomLog();
$RoomLog_ins->startMain();

?>
 
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>1行メッセージ</title>
</head>
 
<body>
 
<h1>お問い合わせ内容</h1>
 
  <section>
    <?php
 
      // 一行ずつ表示する処理
      for ($i = 0; $i < $linesNum; $i++) {
 
         // 区切り文字でデータを区切って配列に格納
         $array = explode($SPLIT_Str, $lines[$i]);
 
         // 区切り文字の前の部分は名前
         $name = htmlspecialchars($array[0]);
         
         
         // 区切り文字の後の部分はメッセージ
         
         $array_length = count($array);
         if ($array_length == 2) {
           $message = htmlspecialchars($array[1]);
         }
         // 名前とメッセージを表示
         echo '<p>' . $name . "「" . str_replace(PHP_EOL, "", $message) . '」</p>';
      }
    ?>
  </section>


  
 
  <form method="post" action="chat_class_txt.php">
    <div>
      <!--<b>おなまえ</b>-->
      <!--<input name="name" type="text" size="20" maxlength="10">-->
      <input name="name" type="hidden" size="20" maxlength="10">
    </div>
    <div>
      <!--<b>ご入力</b>-->
      <input name="message" type="text" size="50" maxlength="50" required>
      <button name="submit" type="submit">送信</button>
    </div>
    
  </form>
  
</body>
</html>

担当者のチャット画面

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>1行メッセージ</title>
</head>
 
<body>
<!-- chat.php -->

<style>
.base {
  display: flex;
  flex-direction: row;
  width: 100vw;
  height: 90vh;
}
.class1 {
  width: 10%;
}
 
.class2 {
  display: flex;
  flex-direction: column;
  width: 90%;
}

</style>
<style>
  div {
    text-align: center;
    /* background-color: #aaaaaa; 16進数のカラーコードを使用する例 */
  }
  button{
      font-size: 200%;
      width:100px;
      height:100px;
  }
</style>
  <div class="base">
    <div class="class1">

<?php
//$dir = "log";
//$files = scandir($dir);
$files = glob("log/*");
$counter=0;
foreach ($files as $file) {
    //echo("<h2>" . $file . "</h2><br>");
    $url='log_frame.php';
    //echo('<a href="'.$url.'"><h1><div >' . $counter . '</div></h1></a><br>');
    
    $htmlStr='';
    $htmlStr=$htmlStr.'<form method="post" action="chat_class_txt_admin.php">';
    $htmlStr=$htmlStr.'<input type="hidden" name="LOG_FILE_NAME" value="' . $file . '">';
    $htmlStr=$htmlStr.'<button name="submit" type="submit">' . $counter . '</button>';
    $htmlStr=$htmlStr.'</form>';
    echo($htmlStr);

    $counter=$counter+1;
}

?>
      
</div>
<div class="class2">
<?php
function trace($txt){
    //print($txt);
    $a="a";
}
class RoomLog
{
    
    public $LOG_FILE_NAME;
    public $LOG_FILE_NAME_Opened;
    public $name;
    public $SPLIT_Str;
    public $message;
    public function get_ip_file_name(){
        global $_SERVER;
        $ip_Address=$_SERVER['REMOTE_ADDR'];
        trace("ip_Address= " . $ip_Address . "<br>");
        if($ip_Address=="::1"){
            $ip_Address="192.168.1.29";
            trace("テストのためip変数上書きしました。ip_Address= " . $ip_Address . "<br>");
        }
        $ip_Address_Arr = explode(".", $ip_Address);
        $ip_file_name = join('_', $ip_Address_Arr);
        $ip_file_name = "log/ip_" . $ip_file_name . "_chatlog.txt";
        trace("ip_file_name= " . $ip_file_name . "<br>");
        return $ip_file_name;
    }
    
    public function CheckFormPostData_Admin(){
        trace("■ CheckFormPostData_Admin()<br>");
        global $_POST;
        
        // 送信されたデータ
        $_POST_string = join(', ', $_POST);
        trace("_POST_string1= " . $_POST_string . "<br>");
        
        if (empty($_POST)) {
            trace("The form is empty.<br>");
        } else {
            trace("Form data is OK present.<br>");
        }
        if (isset($_POST['LOG_FILE_NAME'])) {
          $LOG_FILE_NAME = $_POST['LOG_FILE_NAME'];
          $this->LOG_FILE_NAME=$LOG_FILE_NAME;
          print("LOG_FILE_NAME= " . $LOG_FILE_NAME . "<br>");
        }
        /*
        // 送信された名前とメッセージを変数に代入
        if (isset($_POST['name'])) {
          $name = $_POST['name'];
     
          if (strpos($name, $SPLIT_Str) !== false) {
            // 名前に区切り文字が含まれている場合の処理
            echo "使用できない文字列「|-|」が含まれています。";
            return;
          }
     
          if ($name == "") {
            $name = "お客様";
          }
        }
        if (isset($_POST['message'])) {
          $message = $_POST['message'];
     
          if (strpos($message, $SPLIT_Str) !== false) {
            // メッセージに区切り文字が含まれている場合の処理
            echo "使用できない文字列「|-|」が含まれています。";
            return;
          }
     
          //$this->LOG_FILE_NAME=$LOG_FILE_NAME;
          $this->name=$name;
          //$this->SPLIT_Str=$SPLIT_Str;
          $this->message=$message;
          $this->LogWrite();
        }
        */
        return $LOG_FILE_NAME;
    }

    public function initLog(){
        trace("■ initLog()<br>");
        global $LOG_FILE_NAME;
        global $name;
        global $SPLIT_Str;
        global $message;
        
        $ip_file_name=$this->CheckFormPostData_Admin();
        
        // データを書き込むファイルの名前
        //$LOG_FILE_NAME = "chat_class_txt_log.txt";
        $LOG_FILE_NAME = $ip_file_name;
     
        // 区切りのための文字列
        $SPLIT_Str = "|-|";
     
        // 名前を格納する変数
        $name = "担当者";
        // メッセージを格納する変数
        $message = "";
        
        $this->LOG_FILE_NAME=$LOG_FILE_NAME;
        $this->name=$name;
        $this->SPLIT_Str=$SPLIT_Str;
        $this->message=$message;
        /*
        trace("<br>");
        trace("this->LOG_FILE_NAME= " . $this->LOG_FILE_NAME . "<br>");
        trace("this->name= " . $this->name . "<br>");
        trace("this->SPLIT_Str= " . $this->SPLIT_Str . "<br>");
        trace("this->message= " . $this->message . "<br>");
        */
    }
    
    public function startMain(){
        trace("■ startMain()<br>");
        $this->initLog();
        $this->CheckFormPostData();
        $this->LogShow();
    }
    

    public function CheckFormPostData(){
        trace("■ CheckFormPostData()<br>");
        global $_POST;
        
        $name = $this->name;
        $SPLIT_Str = $this->SPLIT_Str;
        $message = $this->message;
        
        
        // 送信されたデータ
        $_POST_string = join(', ', $_POST);
        //trace("_POST_string2= " . $_POST_string . "<br>");
        
        if (empty($_POST)) {
            trace("The form is empty.<br>");
        } else {
            trace("Form data is present.<br>");
        }
        
        // 送信された名前とメッセージを変数に代入
        if (isset($_POST['name'])) {
          $name = $_POST['name'];
     
          if (strpos($name, $SPLIT_Str) !== false) {
            // 名前に区切り文字が含まれている場合の処理
            echo "使用できない文字列「|-|」が含まれています。<br>";
            return;
          }
     
          if ($name == "") {
            $name = "担当者";
          }
        }
        if (isset($_POST['message'])) {
          $message = $_POST['message'];
     
          if (strpos($message, $SPLIT_Str) !== false) {
            // メッセージに区切り文字が含まれている場合の処理
            echo "使用できない文字列「|-|」が含まれています。<br>";
            return;
          }
     
          //$this->LOG_FILE_NAME=$LOG_FILE_NAME;
          $this->name=$name;
          //$this->SPLIT_Str=$SPLIT_Str;
          $this->message=$message;
          $this->LogWrite();
        }
    }
   
    
    public function LogWrite(){
      trace("■ LogWrite()<br>");
      $LOG_FILE_NAME = $this->LOG_FILE_NAME;
      $name = $this->name;
      $SPLIT_Str = $this->SPLIT_Str;
      $message = $this->message;
        
      //書き込みモードでファイルを開く
      $fp = fopen($LOG_FILE_NAME, "a") or exit($LOG_FILE_NAME . "が開けません<br>");
 
      // | を区切り文字として2つのデータを繋げて書き込む
      fwrite($fp, $name . $SPLIT_Str . $message . "\n");
      
      
      // リダイレクトのためのHTTPヘッダーを送信
      //header("Location: " . $_SERVER['PHP_SELF'], true, 303);
      
      fclose($fp);
    }

    function LogShow(){
        trace("■ LogShow()<br>");
        //global $LOG_FILE_NAME;
        global $linesNum;
        global $lines;
        $LOG_FILE_NAME = $this->LOG_FILE_NAME;
        //$name = $this->name;
        //$SPLIT_Str = $this->SPLIT_Str;
        //$message = $this->message;
        
        if (!file_exists($LOG_FILE_NAME)) {
          // ファイルがない場合
          echo "書き込みはありません。<br>";
     
          $linesNum = 0;
        } else {
     
          // ファイルの全行を読み取る
          $lines = file($LOG_FILE_NAME);
     
          // 読み込んだ行数
          $linesNum = count($lines);
        }
    }
    
}

$RoomLog_ins = new RoomLog();
$RoomLog_ins->startMain();

?>
 

 
<h1>お問い合わせ内容</h1>
 
  <section>
    <?php
 
      // 一行ずつ表示する処理
      for ($i = 0; $i < $linesNum; $i++) {
 
         // 区切り文字でデータを区切って配列に格納
         $array = explode($SPLIT_Str, $lines[$i]);
 
         // 区切り文字の前の部分は名前
         $name = htmlspecialchars($array[0]);
         
         
         // 区切り文字の後の部分はメッセージ
         
         $array_length = count($array);
         if ($array_length == 2) {
           $message = htmlspecialchars($array[1]);
         }
         // 名前とメッセージを表示
         echo '<p>' . $name . "「" . str_replace(PHP_EOL, "", $message) . '」</p>';
      }
    ?>
  </section>


  
 
  <form method="post" action="chat_class_txt_admin.php">
    <div>
      <!--<b>おなまえ</b>-->
      <!--<input name="name" type="text" size="20" maxlength="10">-->
      <input name="name" type="hidden" size="20" maxlength="10">
    </div>
    <div>
      <!--<b>ご入力</b>-->
      <?php
      echo('<input type="hidden" name="LOG_FILE_NAME" value="' . $LOG_FILE_NAME . '">');
      ?>
      <input name="message" type="text" size="50" maxlength="50" required>
      <button name="submit" type="submit">送信</button>
    </div>
    
  </form>
  
  
    </div><!--div class="class2"-->
  </div><!--div class="base"-->
</body>
</html>

こちらのサイトを参考にしました。
PHPで作るチャット(7) クロスサイトスクリプティング(XSS)の修正

このPHPをクラスベースで書き直しました。

[xampp] php Rechet chatを作る勉強。

参考サイト

[PHP]Ratchetの初期設定とテキストのリアルタイム通信テスト

Xamppをwindowsをインストール

https://sourceforge.net/projects/xampp/files/XAMPP%20Windows/7.4.33/

お名前.comのPHPが7.4なので

https://sourceforge.net/projects/xampp/files/XAMPP%20Windows/7.4.33/xampp-windows-x64-7.4.33-0-VC15-installer.exe/download

をダウンロードした。

システム環境変数にphpのパスを通す

C:\xampp\php

PHPのバージョン確認

PS C:\xampp\htdocs> php -v
PHP 7.4.33 (cli) (built: Nov  2 2022 16:00:55) ( ZTS Visual C++ 2017 x64 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
PS C:\xampp\htdocs>

Composerをインストール

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'e21205b207c3ff031906575712edab6f13eb0b361f2085f1f1237b7126d785e826a450292b6cfd1d64d92e6563bbde02') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

XAMPP の htdocs ディレクトリに任意の名前のフォルダを作成し、ターミナルでアクセスできる状態にします。この例では MyChat というフォルダ名にしています。

php ../composer.phar require cboden/ratchet

こんなファイルが出てきます。

composer.json を開き autoload の5行を追記します。

{
    "autoload": {
        "psr-4": {
            "MyApp\\": "src"
        }
    },
    "require": {
        "cboden/ratchet": "^0.4.3"
    }
}

ディレクトリ MyChat にフォルダ src/ を作成し、その中に(Chat.php)を作成します。

<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
 
class Chat implements MessageComponentInterface {
    public function onOpen(ConnectionInterface $conn) {
    }
 
    public function onMessage(ConnectionInterface $from, $msg) {
    }
 
    public function onClose(ConnectionInterface $conn) {
    }
 
    public function onError(ConnectionInterface $conn, \Exception $e) {
    }
}

同様にフォルダ bin/ を作成し、その中にスクリプト(chat-server.php)を作成してください。

<?php
use Ratchet\Server\IoServer;
use MyApp\Chat;
 
    require dirname(__DIR__) . '/vendor/autoload.php';
 
    $server = IoServer::factory(
        new Chat(),
        8080
    );
 
    $server->run();

以上のスクリプトを作成後、ターミナルで以下のコマンドを入力してください。

php bin/chat-server.php

正常に動作するとターミナルには何も表示されないはずですが、以下のようなエラーが表示される場合があります。

PS C:\xampp\htdocs\MyChat> php bin/chat-server.php
PHP Fatal error:  Uncaught Error: Class 'MyApp\Chat' not found in C:\xampp\htdocs\MyChat\bin\chat-server.php:8
Stack trace:
#0 {main}
  thrown in C:\xampp\htdocs\MyChat\bin\chat-server.php on line 8

Fatal error: Uncaught Error: Class 'MyApp\Chat' not found in C:\xampp\htdocs\MyChat\bin\chat-server.php:8
Stack trace:
#0 {main}
  thrown in C:\xampp\htdocs\MyChat\bin\chat-server.php on line 8
PS C:\xampp\htdocs\MyChat>

もしこのエラーが表示されたなら composer.phar のアップデートを実行してみてください。アップデートのコマンドは以下のとおりです。

	php ../composer.phar update

再度やってみます。

php bin/chat-server.php

正常に動作した場合は control+C で終了させてください。

以上で通信のための準備が整いました。

メッセージ送信の実行

実際に通信をテストするには、まず Chat.php を以下のように書き換えます。

<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
 
class Chat implements MessageComponentInterface {
    protected $clients;
 
    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }
 
    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);
 
        echo "New connection! ({$conn->resourceId})\n";
    }
 
    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
 
        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
    }
 
    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach($conn);
 
        echo "Connection {$conn->resourceId} has disconnected\n";
    }
 
    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";
 
        $conn->close();
    }
}

そして、ターミナルのウィンドウを3つ開き、それぞれ以下のコマンドを入力します。

php bin/chat-server.php
telnet localhost 8080
telnet localhost 8080

もし telnet がないと言われた場合は python を利用する以下のコマンドを試してみてください。

	python -m telnetlib localhost 8080

実行結果です。一方のtelnetにメッセージを入力すると、他方にメッセージが表示されます。接続状態などは bin/chat-server.php を実行したウィンドウに表示されます。

ブラウザを利用したメッセージの送信

chat-server.php を以下のように書き換えます。

<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;
 
    require dirname(__DIR__) . '/vendor/autoload.php';
 
    $server = IoServer::factory(
        new HttpServer(
            new WsServer(
                new Chat()
            )
        ),
        8080
    );
 
    $server->run();

ターミナルで再度 bin/chat-server.php を実行し、

MyChat/index.htmlに以下のHTMLフォームボタンで動くとjavascriptを入力します。

<br><br><br><br><br><br><br><br>
<a href="javascript:myFunction();">リンクでJSのmyFunction()実行</a>
<script>
function myFunction() {
// フォームボタンがクリックされたときの処理をここに記述

//------------------------------------------------------
var conn = new WebSocket('ws://localhost:8080');
conn.onopen = function(e) {
    console.log("Connection established!");
};
 
conn.onmessage = function(e) {
    console.log(e.data);
};
//------------------------------------------------------
alert('入室しました!');
}
</script>

実行結果は以下のとおりです。

ターミナルにブラウザから send によって送信したメッセージが表示されました。

以上、Ratchetの初期設定と、それを利用した通信の例でした。

[maya] maya_usd で get Selected Prim Path

maya_usd 選択したprimからprimのpathを得る方法
ls で取れた、

ufeObjects(ufe)

-sl/selectionフラグ と組み合わせて使用​​すると、ネイティブ Maya オブジェクトだけでなく、UFE インターフェイスを通じて定義されたオブジェクトも返されます。

import maya.cmds as cmds
 
proxy_prim_path = cmds.ls(sl=True, ufe = True)
#or
proxy_prim_path = cmds.ls(sl=True, ufeObjects = True)
print("proxy_prim_path= "+str(proxy_prim_path))

Output

proxy_prim_path= ['|stage1|stageShape1,/Ball1/Ball_Mesh']

参考URL

https://help.autodesk.com/cloudhelp/2022/ENU/Maya-Tech-Docs/CommandsPython/ls.html

https://stackoverflow.com/questions/76558940/select-and-hide-multiple-usd-prims-in-maya

[maya][python]scriptEditorInfoでスクリプトエディタの内容のログの最後の行を取る

Take the last line of the log in the contents of the script editor

#!/usr/bin/env python
# -*- coding: utf-8 -*-
workSpaceDir=cmds.workspace( q=True, rootDirectory=True )
print("workSpaceDir= "+workSpaceDir)
historyFilename=workSpaceDir+'scriptEditorInfo_tempHistoryLog7.txt'
print("historyFilename= "+historyFilename)
cmds.scriptEditorInfo(input="")
cmds.scriptEditorInfo( historyFilename=historyFilename, writeHistory=True )

print("----startLog00700---")
#-----この間にUSD prim を選択させてみたい。 ----------
#------難しいかな??
#-----この間にUSD prim を選択させてみたい。 ----------
import codecs
fin  = codecs.open(historyFilename, 'r', 'shift_jis')
lineCount=0
lineArr=[]
for line in fin:
    #print("lineNum:"+str(lineCount)+" lineStr:"+line)
    lineCount=lineCount+1
    lineArr.append(line)
#fout = codecs.open('sjis.txt', 'w', 'shift_jis')
#fin_str=str(fin)
lineArr_len=len(lineArr)
print("lineArr_len= "+str(lineArr_len))
LastLine_Str=lineArr[lineArr_len-1]
print("LastLine_Str= "+LastLine_Str)

cmds.scriptEditorInfo(input="")
cmds.scriptEditorInfo( historyFilename=historyFilename, writeHistory=False )

print("----NotLoged----")