Esempio n. 1
0
    def __init__(self, frame: wx.Frame, parent: wx.Notebook, tab_idx: int):
        super().__init__(frame, parent, tab_idx)
        self.convert_csv_worker = None

        self.description_txt = wx.StaticText(
            self, wx.ID_ANY,
            "指定されたVMDファイルの解析結果を、ボーン/モーフ/カメラに分けてCSVファイルとして出力します。",
            wx.DefaultPosition, wx.DefaultSize, 0)
        self.sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                         wx.DefaultSize, wx.LI_HORIZONTAL)
        self.sizer.Add(self.static_line, 0, wx.EXPAND | wx.ALL, 5)

        # CSVファイルコントロール
        self.vmd_file_ctrl = BaseFilePickerCtrl(frame, self, u"VMDファイル", u"VMDファイルを開く", ("vmd"), wx.FLP_DEFAULT_STYLE, \
                                                u"CSVに変換したいVMDのファイルパスを指定してください。", \
                                                is_aster=False, is_save=False, set_no=0)
        self.sizer.Add(self.vmd_file_ctrl.sizer, 0, wx.EXPAND | wx.ALL, 0)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # CSV変換実行ボタン
        self.csv_btn_ctrl = wx.Button(self, wx.ID_ANY, u"CSV変換実行",
                                      wx.DefaultPosition, wx.Size(200, 50), 0)
        self.csv_btn_ctrl.SetToolTip(u"VMDをCSVに変換します。")
        self.csv_btn_ctrl.Bind(wx.EVT_BUTTON, self.on_convert_csv)
        btn_sizer.Add(self.csv_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, self.frame.logging_level, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.fit()

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_CSV_THREAD, self.on_convert_csv_result)
Esempio n. 2
0
    def __init__(self, frame: wx.Frame, parent: wx.Notebook, tab_idx: int):
        super().__init__(frame, parent, tab_idx)

        self.header_panel = CameraHeaderPanel(self.frame, self, wx.ID_ANY,
                                              wx.DefaultPosition,
                                              wx.DefaultSize, wx.TAB_TRAVERSAL)
        self.header_sizer = wx.BoxSizer(wx.VERTICAL)

        self.description_txt = wx.StaticText(self.header_panel, wx.ID_ANY, u"指定されたカメラモーションのサイジングを、ボーンモーションのサイジングと同時に行えます。\n" \
                                             + "全長オフセットYは、カメラに映す変換先モデルの全長を調整するオフセット値を指定できます。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.header_sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line01 = wx.StaticLine(self.header_panel, wx.ID_ANY,
                                           wx.DefaultPosition, wx.DefaultSize,
                                           wx.LI_HORIZONTAL)
        self.header_sizer.Add(self.static_line01, 0, wx.EXPAND | wx.ALL, 5)

        # カメラVMDファイルコントロール
        self.camera_vmd_file_ctrl = HistoryFilePickerCtrl(self.frame, self.header_panel, u"カメラモーションVMD", u"カメラモーションVMDファイルを開く", ("vmd"), wx.FLP_DEFAULT_STYLE, \
                                                          u"調整したいカメラモーションのVMDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                          file_model_spacer=0, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="camera_vmd", is_change_output=True, \
                                                          is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.camera_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 出力先VMDファイルコントロール
        self.output_camera_vmd_file_ctrl = BaseFilePickerCtrl(frame, self.header_panel, u"出力カメラVMD", u"出力カメラVMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                              u"調整結果のカメラVMD出力パスを指定してください。\nカメラVMDファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                              is_aster=False, is_save=True, set_no=1)
        self.header_sizer.Add(self.output_camera_vmd_file_ctrl.sizer, 1,
                              wx.EXPAND, 0)

        self.header_panel.SetSizer(self.header_sizer)
        self.header_panel.Layout()
        self.sizer.Add(self.header_panel, 0, wx.EXPAND | wx.ALL, 5)

        # カメラセット(key: ファイルセット番号, value: カメラセット)
        self.camera_set_dict = {}
        # カメラセット用基本Sizer
        self.set_list_sizer = wx.BoxSizer(wx.VERTICAL)

        self.scrolled_window = CameraScrolledWindow(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, \
                                                    wx.FULL_REPAINT_ON_RESIZE | wx.VSCROLL | wx.ALWAYS_SHOW_SB)
        self.scrolled_window.SetScrollRate(5, 5)

        # スクロールバーの表示のためにサイズ調整
        self.scrolled_window.SetSizer(self.set_list_sizer)
        self.scrolled_window.Layout()
        self.sizer.Add(self.scrolled_window, 1,
                       wx.ALL | wx.EXPAND | wx.FIXED_MINSIZE, 5)
        self.sizer.Layout()
        self.fit()
Esempio n. 3
0
    def __init__(self, frame: wx.Frame, multi_join: wx.Notebook, tab_idx: int):
        super().__init__(frame, multi_join, tab_idx)
        self.timer = wx.Timer(self, TIMER_ID)
        self.convert_multi_join_worker = None

        self.header_sizer = wx.BoxSizer(wx.VERTICAL)

        self.description_txt = wx.StaticText(self, wx.ID_ANY, u"モーションの指定ボーンの移動量XYZと回転量XYZを統合します。\n" \
                                             + "統合するボーンは「ボーン指定」ボタンから定義できます。多段分割の設定エクスポートファイル流用可能です。" \
                                             + "\n不要キー削除を行うと、キーが間引きされます。キー間がオリジナルから多少ずれ、やや時間がかかります。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.header_sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line01 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                           wx.DefaultSize, wx.LI_HORIZONTAL)
        self.header_sizer.Add(self.static_line01, 0, wx.EXPAND | wx.ALL, 5)

        # 対象VMDファイルコントロール
        self.vmd_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"対象モーションVMD/VPD", u"対象モーションVMDファイルを開く", ("vmd", "vpd"), wx.FLP_DEFAULT_STYLE, \
                                                   u"調整したい対象モーションのVMDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                   file_model_spacer=46, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="multi_join_vmd", is_change_output=True, \
                                                   is_aster=False, is_save=False, set_no=1)
        self.vmd_file_ctrl.file_ctrl.Bind(wx.EVT_FILEPICKER_CHANGED,
                                          self.on_change_file)
        self.header_sizer.Add(self.vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 対象PMXファイルコントロール
        self.model_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"多段化済みモデルPMX", u"多段化済みモデルPMXファイルを開く", ("pmx"), wx.FLP_DEFAULT_STYLE, \
                                                     u"モーションを適用したい多段化済みモデルのPMXパスを指定してください。\n人体モデル以外にも適用可能です。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                     file_model_spacer=49, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="multi_join_pmx", \
                                                     is_change_output=True, is_aster=False, is_save=False, set_no=1)
        self.model_file_ctrl.file_ctrl.Bind(wx.EVT_FILEPICKER_CHANGED,
                                            self.on_change_file)
        self.header_sizer.Add(self.model_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 出力先VMDファイルコントロール
        self.output_vmd_file_ctrl = BaseFilePickerCtrl(frame, self, u"出力対象VMD", u"出力対象VMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                       u"調整結果の対象VMD出力パスを指定してください。\n対象VMDファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                       is_aster=False, is_save=True, set_no=1)
        self.header_sizer.Add(self.output_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        self.sizer.Add(self.header_sizer, 0, wx.EXPAND | wx.ALL, 5)

        self.setting_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # ボーン名指定
        self.bone_target_txt_ctrl = wx.TextCtrl(
            self, wx.ID_ANY, "", wx.DefaultPosition, (450, 50),
            wx.HSCROLL | wx.VSCROLL | wx.TE_MULTILINE | wx.TE_READONLY)
        self.bone_target_txt_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.setting_sizer.Add(self.bone_target_txt_ctrl, 1,
                               wx.EXPAND | wx.ALL, 5)

        self.bone_target_btn_ctrl = wx.Button(self, wx.ID_ANY, u"ボーン指定",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        self.bone_target_btn_ctrl.SetToolTip(
            u"モーションに登録されているボーンから、統合したいボーンを指定できます")
        self.bone_target_btn_ctrl.Bind(wx.EVT_BUTTON,
                                       self.on_click_bone_target)
        self.setting_sizer.Add(self.bone_target_btn_ctrl, 0,
                               wx.ALIGN_BOTTOM | wx.ALL, 5)

        self.sizer.Add(self.setting_sizer, 0, wx.EXPAND | wx.ALL, 5)

        # 不要キー削除処理
        self.flg_sizer = wx.BoxSizer(wx.VERTICAL)
        self.remove_unnecessary_flg_ctrl = wx.CheckBox(self, wx.ID_ANY,
                                                       u"不要キー削除処理を追加実行する",
                                                       wx.DefaultPosition,
                                                       wx.DefaultSize, 0)
        self.remove_unnecessary_flg_ctrl.SetToolTip(
            u"チェックを入れると、不要キー削除処理を追加で実行します。キーが減る分、キー間が少しズレる事があります。")
        self.remove_unnecessary_flg_ctrl.Bind(wx.EVT_CHECKBOX,
                                              self.on_change_file)
        self.flg_sizer.Add(self.remove_unnecessary_flg_ctrl, 0, wx.ALL, 5)
        self.sizer.Add(self.flg_sizer, 0, wx.EXPAND | wx.ALL, 5)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # 実行ボタン
        self.multi_join_btn_ctrl = wx.Button(self, wx.ID_ANY, u"多段統合",
                                             wx.DefaultPosition,
                                             wx.Size(200, 50), 0)
        self.multi_join_btn_ctrl.SetToolTip(u"キーフレを多段用に統合したモーションを生成します")
        self.multi_join_btn_ctrl.Bind(wx.EVT_LEFT_DOWN,
                                      self.on_convert_multi_join)
        self.multi_join_btn_ctrl.Bind(wx.EVT_LEFT_DCLICK, self.on_doubleclick)
        btn_sizer.Add(self.multi_join_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, self.frame.logging_level, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.Layout()
        self.fit()

        # ボーン選択用ダイアログ
        self.bone_dialog = TargetBoneDialog(self.frame, self, "←", "分割")

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_SMOOTH_THREAD, self.on_convert_multi_join_result)
Esempio n. 4
0
class MultiJoinPanel(BasePanel):
    def __init__(self, frame: wx.Frame, multi_join: wx.Notebook, tab_idx: int):
        super().__init__(frame, multi_join, tab_idx)
        self.timer = wx.Timer(self, TIMER_ID)
        self.convert_multi_join_worker = None

        self.header_sizer = wx.BoxSizer(wx.VERTICAL)

        self.description_txt = wx.StaticText(self, wx.ID_ANY, u"モーションの指定ボーンの移動量XYZと回転量XYZを統合します。\n" \
                                             + "統合するボーンは「ボーン指定」ボタンから定義できます。多段分割の設定エクスポートファイル流用可能です。" \
                                             + "\n不要キー削除を行うと、キーが間引きされます。キー間がオリジナルから多少ずれ、やや時間がかかります。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.header_sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line01 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                           wx.DefaultSize, wx.LI_HORIZONTAL)
        self.header_sizer.Add(self.static_line01, 0, wx.EXPAND | wx.ALL, 5)

        # 対象VMDファイルコントロール
        self.vmd_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"対象モーションVMD/VPD", u"対象モーションVMDファイルを開く", ("vmd", "vpd"), wx.FLP_DEFAULT_STYLE, \
                                                   u"調整したい対象モーションのVMDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                   file_model_spacer=46, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="multi_join_vmd", is_change_output=True, \
                                                   is_aster=False, is_save=False, set_no=1)
        self.vmd_file_ctrl.file_ctrl.Bind(wx.EVT_FILEPICKER_CHANGED,
                                          self.on_change_file)
        self.header_sizer.Add(self.vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 対象PMXファイルコントロール
        self.model_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"多段化済みモデルPMX", u"多段化済みモデルPMXファイルを開く", ("pmx"), wx.FLP_DEFAULT_STYLE, \
                                                     u"モーションを適用したい多段化済みモデルのPMXパスを指定してください。\n人体モデル以外にも適用可能です。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                     file_model_spacer=49, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="multi_join_pmx", \
                                                     is_change_output=True, is_aster=False, is_save=False, set_no=1)
        self.model_file_ctrl.file_ctrl.Bind(wx.EVT_FILEPICKER_CHANGED,
                                            self.on_change_file)
        self.header_sizer.Add(self.model_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 出力先VMDファイルコントロール
        self.output_vmd_file_ctrl = BaseFilePickerCtrl(frame, self, u"出力対象VMD", u"出力対象VMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                       u"調整結果の対象VMD出力パスを指定してください。\n対象VMDファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                       is_aster=False, is_save=True, set_no=1)
        self.header_sizer.Add(self.output_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        self.sizer.Add(self.header_sizer, 0, wx.EXPAND | wx.ALL, 5)

        self.setting_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # ボーン名指定
        self.bone_target_txt_ctrl = wx.TextCtrl(
            self, wx.ID_ANY, "", wx.DefaultPosition, (450, 50),
            wx.HSCROLL | wx.VSCROLL | wx.TE_MULTILINE | wx.TE_READONLY)
        self.bone_target_txt_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.setting_sizer.Add(self.bone_target_txt_ctrl, 1,
                               wx.EXPAND | wx.ALL, 5)

        self.bone_target_btn_ctrl = wx.Button(self, wx.ID_ANY, u"ボーン指定",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        self.bone_target_btn_ctrl.SetToolTip(
            u"モーションに登録されているボーンから、統合したいボーンを指定できます")
        self.bone_target_btn_ctrl.Bind(wx.EVT_BUTTON,
                                       self.on_click_bone_target)
        self.setting_sizer.Add(self.bone_target_btn_ctrl, 0,
                               wx.ALIGN_BOTTOM | wx.ALL, 5)

        self.sizer.Add(self.setting_sizer, 0, wx.EXPAND | wx.ALL, 5)

        # 不要キー削除処理
        self.flg_sizer = wx.BoxSizer(wx.VERTICAL)
        self.remove_unnecessary_flg_ctrl = wx.CheckBox(self, wx.ID_ANY,
                                                       u"不要キー削除処理を追加実行する",
                                                       wx.DefaultPosition,
                                                       wx.DefaultSize, 0)
        self.remove_unnecessary_flg_ctrl.SetToolTip(
            u"チェックを入れると、不要キー削除処理を追加で実行します。キーが減る分、キー間が少しズレる事があります。")
        self.remove_unnecessary_flg_ctrl.Bind(wx.EVT_CHECKBOX,
                                              self.on_change_file)
        self.flg_sizer.Add(self.remove_unnecessary_flg_ctrl, 0, wx.ALL, 5)
        self.sizer.Add(self.flg_sizer, 0, wx.EXPAND | wx.ALL, 5)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # 実行ボタン
        self.multi_join_btn_ctrl = wx.Button(self, wx.ID_ANY, u"多段統合",
                                             wx.DefaultPosition,
                                             wx.Size(200, 50), 0)
        self.multi_join_btn_ctrl.SetToolTip(u"キーフレを多段用に統合したモーションを生成します")
        self.multi_join_btn_ctrl.Bind(wx.EVT_LEFT_DOWN,
                                      self.on_convert_multi_join)
        self.multi_join_btn_ctrl.Bind(wx.EVT_LEFT_DCLICK, self.on_doubleclick)
        btn_sizer.Add(self.multi_join_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, self.frame.logging_level, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.Layout()
        self.fit()

        # ボーン選択用ダイアログ
        self.bone_dialog = TargetBoneDialog(self.frame, self, "←", "分割")

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_SMOOTH_THREAD, self.on_convert_multi_join_result)

    def on_click_bone_target(self, event: wx.Event):
        self.disable()

        # VMD読み込み
        sys.stdout = self.console_ctrl
        self.vmd_file_ctrl.load()
        # PMX読み込み
        self.model_file_ctrl.load()

        if (self.vmd_file_ctrl.data and self.model_file_ctrl.data and \
                (self.vmd_file_ctrl.data.digest != self.bone_dialog.vmd_digest or self.model_file_ctrl.data.digest != self.bone_dialog.pmx_digest)):

            # データが揃ってたら押下可能
            self.bone_target_btn_ctrl.Enable()
            # リストクリア
            self.bone_target_txt_ctrl.SetValue("")
            # ボーン選択用ダイアログ
            self.bone_dialog.Destroy()
            self.bone_dialog = TargetBoneDialog(self.frame, self, "←", "統合")
            self.bone_dialog.initialize()
        else:
            if not self.vmd_file_ctrl.data or not self.model_file_ctrl.data:
                logger.error("対象モーションVMD/VPDもしくは多段化済みモデルPMXが未指定です。",
                             decoration=MLogger.DECORATION_BOX)
                self.enable()
                return

        self.enable()

        if self.bone_dialog.ShowModal() == wx.ID_CANCEL:
            return  # the user changed their mind

        # 選択されたボーンリストを入力欄に設定
        bone_list = self.bone_dialog.get_bone_list()

        selections = ["{0} {7} 【回転X: {1}】【回転Y: {2}】【回転Z: {3}】【移動X: {4}】【移動Y: {5}】【移動Z: {6}】" \
                      .format(bset[0], bset[1], bset[2], bset[3], bset[4], bset[5], bset[6], "←") for bset in bone_list]
        self.bone_target_txt_ctrl.SetValue('\n'.join(selections))

        self.bone_dialog.Hide()

    # ファイル変更時の処理
    def on_change_file(self, event: wx.Event):
        self.set_output_vmd_path(event, is_force=True)

    def set_output_vmd_path(self, event: wx.Event, is_force=False):
        output_multi_join_vmd_path = MFileUtils.get_output_multi_join_vmd_path(
            self.vmd_file_ctrl.file_ctrl.GetPath(),
            self.model_file_ctrl.file_ctrl.GetPath(),
            self.output_vmd_file_ctrl.file_ctrl.GetPath(), is_force)

        self.output_vmd_file_ctrl.file_ctrl.SetPath(output_multi_join_vmd_path)

        if len(output_multi_join_vmd_path) >= 255 and os.name == "nt":
            logger.error("生成予定のファイルパスがWindowsの制限を超えています。\n生成予定パス: {0}".format(
                output_multi_join_vmd_path),
                         decoration=MLogger.DECORATION_BOX)

    # フォーム無効化
    def disable(self):
        self.vmd_file_ctrl.disable()
        self.model_file_ctrl.disable()
        self.output_vmd_file_ctrl.disable()
        self.bone_target_btn_ctrl.Disable()
        self.multi_join_btn_ctrl.Disable()
        self.remove_unnecessary_flg_ctrl.Disable()

    # フォーム無効化
    def enable(self):
        self.vmd_file_ctrl.enable()
        self.model_file_ctrl.enable()
        self.output_vmd_file_ctrl.enable()
        self.bone_target_btn_ctrl.Enable()
        self.multi_join_btn_ctrl.Enable()
        self.remove_unnecessary_flg_ctrl.Enable()

    def on_doubleclick(self, event: wx.Event):
        self.timer.Stop()
        logger.warning("ダブルクリックされました。", decoration=MLogger.DECORATION_BOX)
        event.Skip(False)
        return False

    def on_convert_multi_join(self, event: wx.Event):
        self.timer.Start(200)
        self.Bind(wx.EVT_TIMER, self.on_convert, id=TIMER_ID)

    # 多段統合変換
    def on_convert(self, event: wx.Event):
        self.timer.Stop()
        self.Unbind(wx.EVT_TIMER, id=TIMER_ID)
        # フォーム無効化
        self.disable()
        # タブ固定
        self.fix_tab()
        # コンソールクリア
        self.console_ctrl.Clear()
        # 出力先を多段統合パネルのコンソールに変更
        sys.stdout = self.console_ctrl

        self.vmd_file_ctrl.save()
        self.model_file_ctrl.save()

        # JSON出力
        MFileUtils.save_history(self.frame.mydir_path,
                                self.frame.file_hitories)

        self.elapsed_time = 0
        result = True
        result = self.vmd_file_ctrl.is_valid() and result
        result = self.model_file_ctrl.is_valid() and result

        if len(self.bone_target_txt_ctrl.GetValue()) == 0:
            logger.error("統合対象ボーンが指定されていません。",
                         decoration=MLogger.DECORATION_BOX)
            result = False

        if not result:
            # 終了音
            self.frame.sound_finish()
            # タブ移動可
            self.release_tab()
            # フォーム有効化
            self.enable()

            return result

        # 多段統合変換開始
        if self.multi_join_btn_ctrl.GetLabel(
        ) == "多段統合停止" and self.convert_multi_join_worker:
            # フォーム無効化
            self.disable()
            # 停止状態でボタン押下時、停止
            self.convert_multi_join_worker.stop()

            # タブ移動可
            self.frame.release_tab()
            # フォーム有効化
            self.frame.enable()
            # ワーカー終了
            self.convert_multi_join_worker = None
            # プログレス非表示
            self.gauge_ctrl.SetValue(0)

            logger.warning("多段統合を中断します。", decoration=MLogger.DECORATION_BOX)
            self.multi_join_btn_ctrl.SetLabel("多段統合")

            event.Skip(False)
        elif not self.convert_multi_join_worker:
            # フォーム無効化
            self.disable()
            # タブ固定
            self.fix_tab()
            # コンソールクリア
            self.console_ctrl.Clear()
            # ラベル変更
            self.multi_join_btn_ctrl.SetLabel("多段統合停止")
            self.multi_join_btn_ctrl.Enable()

            self.convert_multi_join_worker = MultiJoinWorkerThread(
                self.frame, MultiJoinThreadEvent, self.frame.is_saving,
                self.frame.is_out_log)
            self.convert_multi_join_worker.start()

            event.Skip()
        else:
            logger.error("まだ処理が実行中です。終了してから再度実行してください。",
                         decoration=MLogger.DECORATION_BOX)
            event.Skip(False)

        return result

    # 多段統合変換完了処理
    def on_convert_multi_join_result(self, event: wx.Event):
        self.elapsed_time = event.elapsed_time
        logger.info("\n処理時間: %s", self.show_worked_time())
        self.multi_join_btn_ctrl.SetLabel("多段統合")

        # 終了音
        self.frame.sound_finish()

        # タブ移動可
        self.release_tab()
        # フォーム有効化
        self.enable()
        # ワーカー終了
        self.convert_multi_join_worker = None
        # プログレス非表示
        self.gauge_ctrl.SetValue(0)
        # ラベル変更
        self.multi_join_btn_ctrl.SetLabel("多段統合")
        self.multi_join_btn_ctrl.Enable()

    def show_worked_time(self):
        # 経過秒数を時分秒に変換
        td_m, td_s = divmod(self.elapsed_time, 60)

        if td_m == 0:
            worked_time = "{0:02d}秒".format(int(td_s))
        else:
            worked_time = "{0:02d}分{1:02d}秒".format(int(td_m), int(td_s))

        return worked_time
Esempio n. 5
0
    def __init__(self, frame: wx.Frame, panel: wx.Panel, file_hitories: dict,
                 set_no):
        self.file_hitories = file_hitories
        self.frame = frame
        self.panel = panel
        self.set_no = set_no
        self.STANCE_DETAIL_CHOICES = [
            "センターXZ補正", "上半身補正", "下半身補正", "足IK補正", "つま先補正", "つま先IK補正", "肩補正",
            "センターY補正"
        ]
        self.selected_stance_details = [0, 1, 2, 4, 5, 6, 7]

        if self.set_no == 1:
            # ファイルパネルのはそのまま追加
            self.set_sizer = wx.BoxSizer(wx.VERTICAL)
        else:
            self.set_sizer = wx.StaticBoxSizer(wx.StaticBox(
                self.panel, wx.ID_ANY, "【No.{0}】".format(set_no)),
                                               orient=wx.VERTICAL)

        able_aster_toottip = "ファイル名にアスタリスク(*)を使用すると複数件のデータを一度にサイジングできます。" if self.set_no == 1 else "一括指定はできません。"
        # VMD/VPDファイルコントロール
        self.motion_vmd_file_ctrl = HistoryFilePickerCtrl(frame, panel, u"調整対象モーションVMD/VPD", u"調整対象モーションVMD/VPDファイルを開く", ("vmd", "vpd"), wx.FLP_DEFAULT_STYLE, \
                                                          u"調整したいモーションのVMD/VPDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。\n{0}".format(able_aster_toottip), \
                                                          file_model_spacer=46, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="vmd", is_change_output=True, \
                                                          is_aster=True, is_save=False, set_no=set_no)
        self.set_sizer.Add(self.motion_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 作成元のスタンス詳細再現FLG
        detail_stance_flg_ctrl = wx.CheckBox(panel, wx.ID_ANY, u"スタンス追加補正",
                                             wx.DefaultPosition,
                                             wx.DefaultSize, 0)
        detail_stance_flg_ctrl.SetToolTip(
            u"チェックを入れると、細かいスタンス補正を追加で行う事ができます。\n補正内容の詳細は隣の「*」ボタンを押してみてください。")
        detail_stance_flg_ctrl.Bind(wx.EVT_CHECKBOX, self.set_output_vmd_path)

        # スタンス補正
        detail_btn_ctrl = wx.Button(panel, wx.ID_ANY, u"*", wx.DefaultPosition,
                                    (20, 20), 0)
        detail_btn_ctrl.SetToolTip("スタンス追加補正の内訳確認、および取捨選択を行う事が出来ます。")
        detail_btn_ctrl.Bind(wx.EVT_BUTTON, self.select_detail)

        # 作成元PMXファイルコントロール
        self.org_model_file_ctrl = HistoryFilePickerCtrl(frame, panel, u"モーション作成元モデルPMX", u"モーション作成元モデルPMXファイルを開く", ("pmx"), wx.FLP_DEFAULT_STYLE, \
                                                         u"モーション作成に使用されたモデルのPMXパスを指定してください。\n精度は落ちますが、類似したサイズ・ボーン構造のモデルでも代用できます。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                         file_model_spacer=1, title_parts_ctrl=detail_stance_flg_ctrl, title_parts2_ctrl=detail_btn_ctrl, \
                                                         file_histories_key="org_pmx", is_change_output=False, is_aster=False, is_save=False, set_no=set_no)
        self.set_sizer.Add(self.org_model_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 捩り分散追加FLG
        twist_flg_ctrl = wx.CheckBox(panel, wx.ID_ANY, u"捩り分散あり",
                                     wx.DefaultPosition, wx.DefaultSize, 0)
        twist_flg_ctrl.SetToolTip(u"チェックを入れると、腕捻り等への分散処理を追加できます。\n時間がかかります。")
        twist_flg_ctrl.Bind(wx.EVT_CHECKBOX, self.set_output_vmd_path)

        # 変換先PMXファイルコントロール
        self.rep_model_file_ctrl = HistoryFilePickerCtrl(frame, panel, u"モーション変換先モデルPMX", u"モーション変換先モデルPMXファイルを開く", ("pmx"), wx.FLP_DEFAULT_STYLE, \
                                                         u"実際にモーションを読み込ませたいモデルのPMXパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                         file_model_spacer=18, title_parts_ctrl=twist_flg_ctrl, title_parts2_ctrl=None, file_histories_key="rep_pmx", \
                                                         is_change_output=True, is_aster=False, is_save=False, set_no=set_no)
        self.set_sizer.Add(self.rep_model_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 出力先VMDファイルコントロール
        self.output_vmd_file_ctrl = BaseFilePickerCtrl(frame, panel, u"出力VMD", u"出力VMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                       u"調整結果のVMD出力パスを指定してください。\nVMDファイルと変換先PMXのファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                       is_aster=False, is_save=True, set_no=set_no)
        self.set_sizer.Add(self.output_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)
Esempio n. 6
0
class SizingFileSet():
    def __init__(self, frame: wx.Frame, panel: wx.Panel, file_hitories: dict,
                 set_no):
        self.file_hitories = file_hitories
        self.frame = frame
        self.panel = panel
        self.set_no = set_no
        self.STANCE_DETAIL_CHOICES = [
            "センターXZ補正", "上半身補正", "下半身補正", "足IK補正", "つま先補正", "つま先IK補正", "肩補正",
            "センターY補正"
        ]
        self.selected_stance_details = [0, 1, 2, 4, 5, 6, 7]

        if self.set_no == 1:
            # ファイルパネルのはそのまま追加
            self.set_sizer = wx.BoxSizer(wx.VERTICAL)
        else:
            self.set_sizer = wx.StaticBoxSizer(wx.StaticBox(
                self.panel, wx.ID_ANY, "【No.{0}】".format(set_no)),
                                               orient=wx.VERTICAL)

        able_aster_toottip = "ファイル名にアスタリスク(*)を使用すると複数件のデータを一度にサイジングできます。" if self.set_no == 1 else "一括指定はできません。"
        # VMD/VPDファイルコントロール
        self.motion_vmd_file_ctrl = HistoryFilePickerCtrl(frame, panel, u"調整対象モーションVMD/VPD", u"調整対象モーションVMD/VPDファイルを開く", ("vmd", "vpd"), wx.FLP_DEFAULT_STYLE, \
                                                          u"調整したいモーションのVMD/VPDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。\n{0}".format(able_aster_toottip), \
                                                          file_model_spacer=46, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="vmd", is_change_output=True, \
                                                          is_aster=True, is_save=False, set_no=set_no)
        self.set_sizer.Add(self.motion_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 作成元のスタンス詳細再現FLG
        detail_stance_flg_ctrl = wx.CheckBox(panel, wx.ID_ANY, u"スタンス追加補正",
                                             wx.DefaultPosition,
                                             wx.DefaultSize, 0)
        detail_stance_flg_ctrl.SetToolTip(
            u"チェックを入れると、細かいスタンス補正を追加で行う事ができます。\n補正内容の詳細は隣の「*」ボタンを押してみてください。")
        detail_stance_flg_ctrl.Bind(wx.EVT_CHECKBOX, self.set_output_vmd_path)

        # スタンス補正
        detail_btn_ctrl = wx.Button(panel, wx.ID_ANY, u"*", wx.DefaultPosition,
                                    (20, 20), 0)
        detail_btn_ctrl.SetToolTip("スタンス追加補正の内訳確認、および取捨選択を行う事が出来ます。")
        detail_btn_ctrl.Bind(wx.EVT_BUTTON, self.select_detail)

        # 作成元PMXファイルコントロール
        self.org_model_file_ctrl = HistoryFilePickerCtrl(frame, panel, u"モーション作成元モデルPMX", u"モーション作成元モデルPMXファイルを開く", ("pmx"), wx.FLP_DEFAULT_STYLE, \
                                                         u"モーション作成に使用されたモデルのPMXパスを指定してください。\n精度は落ちますが、類似したサイズ・ボーン構造のモデルでも代用できます。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                         file_model_spacer=1, title_parts_ctrl=detail_stance_flg_ctrl, title_parts2_ctrl=detail_btn_ctrl, \
                                                         file_histories_key="org_pmx", is_change_output=False, is_aster=False, is_save=False, set_no=set_no)
        self.set_sizer.Add(self.org_model_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 捩り分散追加FLG
        twist_flg_ctrl = wx.CheckBox(panel, wx.ID_ANY, u"捩り分散あり",
                                     wx.DefaultPosition, wx.DefaultSize, 0)
        twist_flg_ctrl.SetToolTip(u"チェックを入れると、腕捻り等への分散処理を追加できます。\n時間がかかります。")
        twist_flg_ctrl.Bind(wx.EVT_CHECKBOX, self.set_output_vmd_path)

        # 変換先PMXファイルコントロール
        self.rep_model_file_ctrl = HistoryFilePickerCtrl(frame, panel, u"モーション変換先モデルPMX", u"モーション変換先モデルPMXファイルを開く", ("pmx"), wx.FLP_DEFAULT_STYLE, \
                                                         u"実際にモーションを読み込ませたいモデルのPMXパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                         file_model_spacer=18, title_parts_ctrl=twist_flg_ctrl, title_parts2_ctrl=None, file_histories_key="rep_pmx", \
                                                         is_change_output=True, is_aster=False, is_save=False, set_no=set_no)
        self.set_sizer.Add(self.rep_model_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 出力先VMDファイルコントロール
        self.output_vmd_file_ctrl = BaseFilePickerCtrl(frame, panel, u"出力VMD", u"出力VMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                       u"調整結果のVMD出力パスを指定してください。\nVMDファイルと変換先PMXのファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                       is_aster=False, is_save=True, set_no=set_no)
        self.set_sizer.Add(self.output_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

    def get_selected_stance_details(self):
        # 選択されたINDEXの名称を返す
        return [
            self.STANCE_DETAIL_CHOICES[n] for n in self.selected_stance_details
        ]

    def select_detail(self, event: wx.Event):

        with wx.MultiChoiceDialog(self.panel, "スタンス追加補正のうち、チェックが入っている補正のみ実施します", caption="スタンス追加補正選択", \
                                  choices=self.STANCE_DETAIL_CHOICES, style=wx.CHOICEDLG_STYLE) as choiceDialog:

            choiceDialog.SetSelections(self.selected_stance_details)

            if choiceDialog.ShowModal() == wx.ID_CANCEL:
                return  # the user changed their mind

            self.selected_stance_details = choiceDialog.GetSelections()

            if len(self.selected_stance_details) == 0:
                self.org_model_file_ctrl.title_parts_ctrl.SetValue(0)
            else:
                self.org_model_file_ctrl.title_parts_ctrl.SetValue(1)

    def save(self):
        self.motion_vmd_file_ctrl.save()
        self.org_model_file_ctrl.save()
        self.rep_model_file_ctrl.save()

    # フォーム無効化
    def disable(self):
        self.motion_vmd_file_ctrl.disable()
        self.org_model_file_ctrl.disable()
        self.rep_model_file_ctrl.disable()
        self.output_vmd_file_ctrl.disable()

    # フォーム無効化
    def enable(self):
        self.motion_vmd_file_ctrl.enable()
        self.org_model_file_ctrl.enable()
        self.rep_model_file_ctrl.enable()
        self.output_vmd_file_ctrl.enable()

    # ファイル読み込み前のチェック
    def is_valid(self):
        result = True
        if self.set_no == 1:
            # 1番目は必ず調べる
            result = self.motion_vmd_file_ctrl.is_valid() and result
            result = self.org_model_file_ctrl.is_valid() and result
            result = self.rep_model_file_ctrl.is_valid() and result
            result = self.output_vmd_file_ctrl.is_valid() and result
        else:
            # 2番目以降は、ファイルが揃ってたら調べる
            if self.motion_vmd_file_ctrl.is_set_path() or self.org_model_file_ctrl.is_set_path() or \
               self.rep_model_file_ctrl.is_set_path() or self.output_vmd_file_ctrl.is_set_path():
                result = self.motion_vmd_file_ctrl.is_valid() and result
                result = self.org_model_file_ctrl.is_valid() and result
                result = self.rep_model_file_ctrl.is_valid() and result
                result = self.output_vmd_file_ctrl.is_valid() and result

        return result

    # 入力後の入力可否チェック
    def is_loaded_valid(self):
        if self.set_no == 0:
            # CSVとかのファイルは番号出力なし
            display_set_no = ""
        else:
            display_set_no = "{0}番目の".format(self.set_no)

        # 両方のPMXが読めて、モーションも読み込めた場合、キーチェック
        not_org_bones = []
        not_org_morphs = []
        not_rep_bones = []
        not_rep_morphs = []
        mismatch_bones = []

        motion = self.motion_vmd_file_ctrl.data
        org_pmx = self.org_model_file_ctrl.data
        rep_pmx = self.rep_model_file_ctrl.data

        if not motion or not org_pmx or not rep_pmx:
            # どれか読めてなければそのまま終了
            return True

        if motion.motion_cnt == 0:
            logger.warning("%sボーンモーションデータにキーフレームが登録されていません。",
                           display_set_no,
                           decoration=MLogger.DECORATION_BOX)
            return True

        result = True
        is_warning = False

        # ボーン
        for k in motion.bones.keys():
            bone_fnos = motion.get_bone_fnos(k)
            for fno in bone_fnos:
                if motion.bones[k][fno].position != MVector3D(
                ) or motion.bones[k][fno].rotation != MQuaternion():
                    # キーが存在しており、かつ初期値ではない値が入っている場合、警告対象

                    if k not in org_pmx.bones:
                        not_org_bones.append(k)

                    if k not in rep_pmx.bones:
                        not_rep_bones.append(k)

                    if k in org_pmx.bones and k in rep_pmx.bones:
                        mismatch_types = []
                        # 両方にボーンがある場合、フラグが同じであるかチェック
                        if org_pmx.bones[k].getRotatable(
                        ) != rep_pmx.bones[k].getRotatable():
                            mismatch_types.append("性能:回転")
                        if org_pmx.bones[k].getTranslatable(
                        ) != rep_pmx.bones[k].getTranslatable():
                            mismatch_types.append("性能:移動")
                        if org_pmx.bones[k].getIkFlag(
                        ) != rep_pmx.bones[k].getIkFlag():
                            mismatch_types.append("性能:IK")
                        if org_pmx.bones[k].getVisibleFlag(
                        ) != rep_pmx.bones[k].getVisibleFlag():
                            mismatch_types.append("性能:表示")
                        if org_pmx.bones[k].getManipulatable(
                        ) != rep_pmx.bones[k].getManipulatable():
                            mismatch_types.append("性能:操作")
                        if org_pmx.bones[k].display != rep_pmx.bones[k].display:
                            mismatch_types.append("表示枠")

                        if len(mismatch_types) > 0:
                            mismatch_bones.append(
                                f"{k}  【差異】{', '.join(mismatch_types)})")

                    # 1件あればOK
                    break

        for k in motion.morphs.keys():
            morph_fnos = motion.get_morph_fnos(k)
            for fno in morph_fnos:
                if motion.morphs[k][fno].ratio != 0:
                    # キーが存在しており、かつ初期値ではない値が入っている場合、警告対象

                    if k not in org_pmx.morphs:
                        not_org_morphs.append(k)

                    if k not in rep_pmx.morphs:
                        not_rep_morphs.append(k)

                    # 1件あればOK
                    break

        if len(not_org_bones) > 0 or len(not_org_morphs) > 0:
            logger.warning("%s%sに、モーションで使用されているボーン・モーフが不足しています。\nモデル: %s\n不足ボーン: %s\n不足モーフ: %s", \
                           display_set_no, self.org_model_file_ctrl.title, org_pmx.name, ",".join(not_org_bones), ",".join(not_org_morphs), decoration=MLogger.DECORATION_BOX)
            is_warning = True

        if len(not_rep_bones) > 0 or len(not_rep_morphs) > 0:
            logger.warning("%s%sに、モーションで使用されているボーン・モーフが不足しています。\nモデル: %s\n不足ボーン: %s\n不足モーフ: %s", \
                           display_set_no, self.rep_model_file_ctrl.title, rep_pmx.name, ",".join(not_rep_bones), ",".join(not_rep_morphs), decoration=MLogger.DECORATION_BOX)
            is_warning = True

        if len(mismatch_bones) > 0:
            logger.warning("%s%sで、モーションで使用されているボーンの性能等が異なっています。\nモデル: %s\n差異ボーン:\n %s", \
                           display_set_no, self.rep_model_file_ctrl.title, rep_pmx.name, "\n ".join(mismatch_bones), decoration=MLogger.DECORATION_BOX)
            is_warning = True

        if not is_warning:
            logger.info("モーションで使用されているボーン・モーフが揃っています。",
                        decoration=MLogger.DECORATION_BOX,
                        title="OK")

        return result

    def is_loaded(self):
        result = True
        if self.is_valid():
            result = self.motion_vmd_file_ctrl.data and result
            result = self.org_model_file_ctrl.data and result
            result = self.rep_model_file_ctrl.data and result
        else:
            result = False

        return result

    def load(self):
        result = True
        try:
            result = self.motion_vmd_file_ctrl.load() and result
            result = self.org_model_file_ctrl.load() and result
            result = self.rep_model_file_ctrl.load() and result
        except Exception:
            result = False

        return result

    # VMD出力ファイルパス生成
    def set_output_vmd_path(self, event, is_force=False):
        output_vmd_path = MFileUtils.get_output_vmd_path(
            self.motion_vmd_file_ctrl.file_ctrl.GetPath(),
            self.rep_model_file_ctrl.file_ctrl.GetPath(),
            self.org_model_file_ctrl.title_parts_ctrl.GetValue(),
            self.rep_model_file_ctrl.title_parts_ctrl.GetValue(),
            self.frame.arm_panel_ctrl.arm_process_flg_avoidance.GetValue(),
            self.frame.arm_panel_ctrl.arm_process_flg_alignment.GetValue(),
            (self.set_no in self.frame.morph_panel_ctrl.morph_set_dict and self.frame.morph_panel_ctrl.morph_set_dict[self.set_no].is_set_morph()) \
            or (self.set_no in self.frame.morph_panel_ctrl.bulk_morph_set_dict and len(self.frame.morph_panel_ctrl.bulk_morph_set_dict[self.set_no]) > 0),
            self.output_vmd_file_ctrl.file_ctrl.GetPath(), is_force)

        self.output_vmd_file_ctrl.file_ctrl.SetPath(output_vmd_path)

        if len(output_vmd_path) >= 255 and os.name == "nt":
            logger.error("生成予定のファイルパスがWindowsの制限を超えています。\n生成予定パス: {0}".format(
                output_vmd_path),
                         decoration=MLogger.DECORATION_BOX)
Esempio n. 7
0
    def __init__(self, frame: wx.Frame, arm_ik2fk: wx.Notebook, tab_idx: int):
        super().__init__(frame, arm_ik2fk, tab_idx)
        self.convert_arm_ik2fk_worker = None

        self.header_sizer = wx.BoxSizer(wx.VERTICAL)

        self.description_txt = wx.StaticText(self, wx.ID_ANY, u"腕IKを腕FK(腕・ひじ・手首)に変換します" \
                                             + "\n不要キー削除を行うと、キーが間引きされます。キー間がオリジナルから多少ずれ、またそれなりに時間がかかります。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.header_sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line01 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                           wx.DefaultSize, wx.LI_HORIZONTAL)
        self.header_sizer.Add(self.static_line01, 0, wx.EXPAND | wx.ALL, 5)

        # 対象VMDファイルコントロール
        self.arm_ik2fk_vmd_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"対象モーションVMD/VPD", u"対象モーションVMDファイルを開く", ("vmd", "vpd"), wx.FLP_DEFAULT_STYLE, \
                                                             u"調整したい対象モーションのVMDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                             file_model_spacer=46, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="arm_ik2fk_vmd", is_change_output=True, \
                                                             is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.arm_ik2fk_vmd_file_ctrl.sizer, 1, wx.EXPAND,
                              0)

        # 対象PMXファイルコントロール
        self.arm_ik2fk_model_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"適用モデルPMX", u"適用モデルPMXファイルを開く", ("pmx"), wx.FLP_DEFAULT_STYLE, \
                                                               u"モーションを適用したいモデルのPMXパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                               file_model_spacer=60, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="arm_ik2fk_pmx", \
                                                               is_change_output=True, is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.arm_ik2fk_model_file_ctrl.sizer, 1,
                              wx.EXPAND, 0)

        # 出力先VMDファイルコントロール
        self.output_arm_ik2fk_vmd_file_ctrl = BaseFilePickerCtrl(frame, self, u"出力対象VMD", u"出力対象VMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                                 u"調整結果の対象VMD出力パスを指定してください。\n対象VMDファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                                 is_aster=False, is_save=True, set_no=1)
        self.header_sizer.Add(self.output_arm_ik2fk_vmd_file_ctrl.sizer, 1,
                              wx.EXPAND, 0)

        # 不要キー削除処理
        self.remove_unnecessary_flg_ctrl = wx.CheckBox(self, wx.ID_ANY,
                                                       u"不要キー削除処理を追加実行する",
                                                       wx.DefaultPosition,
                                                       wx.DefaultSize, 0)
        self.remove_unnecessary_flg_ctrl.SetToolTip(
            u"チェックを入れると、不要キー削除処理を追加で実行します。キーが減る分、キー間が少しズレる事があります。")
        self.header_sizer.Add(self.remove_unnecessary_flg_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(self.header_sizer, 0, wx.EXPAND | wx.ALL, 5)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # 多段分割変換実行ボタン
        self.arm_ik2fk_btn_ctrl = wx.Button(self, wx.ID_ANY,
                                            u"腕IK変換", wx.DefaultPosition,
                                            wx.Size(200, 50), 0)
        self.arm_ik2fk_btn_ctrl.SetToolTip(u"足FKを足IKに変換したモーションを再生成します。")
        self.arm_ik2fk_btn_ctrl.Bind(wx.EVT_LEFT_DOWN,
                                     self.on_convert_arm_ik2fk)
        self.arm_ik2fk_btn_ctrl.Bind(wx.EVT_LEFT_DCLICK, self.on_doubleclick)
        btn_sizer.Add(self.arm_ik2fk_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, self.frame.logging_level, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.Layout()
        self.fit()

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_SMOOTH_THREAD, self.on_convert_arm_ik2fk_result)
Esempio n. 8
0
class ArmIKtoFKPanel(BasePanel):
    def __init__(self, frame: wx.Frame, arm_ik2fk: wx.Notebook, tab_idx: int):
        super().__init__(frame, arm_ik2fk, tab_idx)
        self.convert_arm_ik2fk_worker = None

        self.header_sizer = wx.BoxSizer(wx.VERTICAL)

        self.description_txt = wx.StaticText(self, wx.ID_ANY, u"腕IKを腕FK(腕・ひじ・手首)に変換します" \
                                             + "\n不要キー削除を行うと、キーが間引きされます。キー間がオリジナルから多少ずれ、またそれなりに時間がかかります。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.header_sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line01 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                           wx.DefaultSize, wx.LI_HORIZONTAL)
        self.header_sizer.Add(self.static_line01, 0, wx.EXPAND | wx.ALL, 5)

        # 対象VMDファイルコントロール
        self.arm_ik2fk_vmd_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"対象モーションVMD/VPD", u"対象モーションVMDファイルを開く", ("vmd", "vpd"), wx.FLP_DEFAULT_STYLE, \
                                                             u"調整したい対象モーションのVMDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                             file_model_spacer=46, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="arm_ik2fk_vmd", is_change_output=True, \
                                                             is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.arm_ik2fk_vmd_file_ctrl.sizer, 1, wx.EXPAND,
                              0)

        # 対象PMXファイルコントロール
        self.arm_ik2fk_model_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"適用モデルPMX", u"適用モデルPMXファイルを開く", ("pmx"), wx.FLP_DEFAULT_STYLE, \
                                                               u"モーションを適用したいモデルのPMXパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                               file_model_spacer=60, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="arm_ik2fk_pmx", \
                                                               is_change_output=True, is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.arm_ik2fk_model_file_ctrl.sizer, 1,
                              wx.EXPAND, 0)

        # 出力先VMDファイルコントロール
        self.output_arm_ik2fk_vmd_file_ctrl = BaseFilePickerCtrl(frame, self, u"出力対象VMD", u"出力対象VMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                                 u"調整結果の対象VMD出力パスを指定してください。\n対象VMDファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                                 is_aster=False, is_save=True, set_no=1)
        self.header_sizer.Add(self.output_arm_ik2fk_vmd_file_ctrl.sizer, 1,
                              wx.EXPAND, 0)

        # 不要キー削除処理
        self.remove_unnecessary_flg_ctrl = wx.CheckBox(self, wx.ID_ANY,
                                                       u"不要キー削除処理を追加実行する",
                                                       wx.DefaultPosition,
                                                       wx.DefaultSize, 0)
        self.remove_unnecessary_flg_ctrl.SetToolTip(
            u"チェックを入れると、不要キー削除処理を追加で実行します。キーが減る分、キー間が少しズレる事があります。")
        self.header_sizer.Add(self.remove_unnecessary_flg_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(self.header_sizer, 0, wx.EXPAND | wx.ALL, 5)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # 多段分割変換実行ボタン
        self.arm_ik2fk_btn_ctrl = wx.Button(self, wx.ID_ANY,
                                            u"腕IK変換", wx.DefaultPosition,
                                            wx.Size(200, 50), 0)
        self.arm_ik2fk_btn_ctrl.SetToolTip(u"足FKを足IKに変換したモーションを再生成します。")
        self.arm_ik2fk_btn_ctrl.Bind(wx.EVT_LEFT_DOWN,
                                     self.on_convert_arm_ik2fk)
        self.arm_ik2fk_btn_ctrl.Bind(wx.EVT_LEFT_DCLICK, self.on_doubleclick)
        btn_sizer.Add(self.arm_ik2fk_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, self.frame.logging_level, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.Layout()
        self.fit()

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_SMOOTH_THREAD, self.on_convert_arm_ik2fk_result)

    def on_wheel_spin_ctrl(self, event: wx.Event, inc=1):
        self.frame.on_wheel_spin_ctrl(event, inc)
        self.set_output_vmd_path(event)

    # ファイル変更時の処理
    def on_change_file(self, event: wx.Event):
        self.set_output_vmd_path(event, is_force=True)

    def set_output_vmd_path(self, event, is_force=False):
        output_arm_ik2fk_vmd_path = MFileUtils.get_output_arm_ik2fk_vmd_path(
            self.arm_ik2fk_vmd_file_ctrl.file_ctrl.GetPath(),
            self.arm_ik2fk_model_file_ctrl.file_ctrl.GetPath(),
            self.output_arm_ik2fk_vmd_file_ctrl.file_ctrl.GetPath(), is_force)

        self.output_arm_ik2fk_vmd_file_ctrl.file_ctrl.SetPath(
            output_arm_ik2fk_vmd_path)

        if len(output_arm_ik2fk_vmd_path) >= 255 and os.name == "nt":
            logger.error("生成予定のファイルパスがWindowsの制限を超えています。\n生成予定パス: {0}".format(
                output_arm_ik2fk_vmd_path),
                         decoration=MLogger.DECORATION_BOX)

    # フォーム無効化
    def disable(self):
        self.arm_ik2fk_vmd_file_ctrl.disable()
        self.arm_ik2fk_model_file_ctrl.disable()
        self.output_arm_ik2fk_vmd_file_ctrl.disable()
        self.arm_ik2fk_btn_ctrl.Disable()

    # フォーム無効化
    def enable(self):
        self.arm_ik2fk_vmd_file_ctrl.enable()
        self.arm_ik2fk_model_file_ctrl.enable()
        self.output_arm_ik2fk_vmd_file_ctrl.enable()
        self.arm_ik2fk_btn_ctrl.Enable()

    def on_doubleclick(self, event: wx.Event):
        self.timer.Stop()
        logger.warning("ダブルクリックされました。", decoration=MLogger.DECORATION_BOX)
        event.Skip(False)
        return False

    # 多段分割変換
    def on_convert_arm_ik2fk(self, event: wx.Event):
        self.timer = wx.Timer(self, TIMER_ID)
        self.timer.Start(200)
        self.Bind(wx.EVT_TIMER, self.on_convert, id=TIMER_ID)

    # 多段分割変換
    def on_convert(self, event: wx.Event):
        self.timer.Stop()
        self.Unbind(wx.EVT_TIMER, id=TIMER_ID)
        # フォーム無効化
        self.disable()
        # タブ固定
        self.fix_tab()
        # コンソールクリア
        self.console_ctrl.Clear()
        # 出力先を多段分割パネルのコンソールに変更
        sys.stdout = self.console_ctrl

        self.arm_ik2fk_vmd_file_ctrl.save()
        self.arm_ik2fk_model_file_ctrl.save()

        # JSON出力
        MFileUtils.save_history(self.frame.mydir_path,
                                self.frame.file_hitories)

        self.elapsed_time = 0
        result = True
        result = self.arm_ik2fk_vmd_file_ctrl.is_valid(
        ) and self.arm_ik2fk_model_file_ctrl.is_valid() and result

        if not result:
            # 終了音
            self.frame.sound_finish()
            # タブ移動可
            self.release_tab()
            # フォーム有効化
            self.enable()

            return result

        # 腕IK変換変換開始
        if self.arm_ik2fk_btn_ctrl.GetLabel(
        ) == "腕IK変換停止" and self.convert_arm_ik2fk_worker:
            # フォーム無効化
            self.disable()
            # 停止状態でボタン押下時、停止
            self.convert_arm_ik2fk_worker.stop()

            # タブ移動可
            self.frame.release_tab()
            # フォーム有効化
            self.frame.enable()
            # ワーカー終了
            self.convert_arm_ik2fk_worker = None
            # プログレス非表示
            self.gauge_ctrl.SetValue(0)

            logger.warning("腕IK変換を中断します。", decoration=MLogger.DECORATION_BOX)
            self.arm_ik2fk_btn_ctrl.SetLabel("腕IK変換")

            event.Skip(False)
        elif not self.convert_arm_ik2fk_worker:
            # フォーム無効化
            self.disable()
            # タブ固定
            self.fix_tab()
            # コンソールクリア
            self.console_ctrl.Clear()
            # ラベル変更
            self.arm_ik2fk_btn_ctrl.SetLabel("腕IK変換停止")
            self.arm_ik2fk_btn_ctrl.Enable()

            self.convert_arm_ik2fk_worker = ArmIKtoFKWorkerThread(
                self.frame, ArmIKtoFKThreadEvent, self.frame.is_saving,
                self.frame.is_out_log)
            self.convert_arm_ik2fk_worker.start()

            event.Skip()
        else:
            logger.error("まだ処理が実行中です。終了してから再度実行してください。",
                         decoration=MLogger.DECORATION_BOX)
            event.Skip(False)

        return result

    # 多段分割変換完了処理
    def on_convert_arm_ik2fk_result(self, event: wx.Event):
        self.elapsed_time = event.elapsed_time
        logger.info("\n処理時間: %s", self.show_worked_time())
        self.arm_ik2fk_btn_ctrl.SetLabel("腕IK変換")

        # 終了音
        self.frame.sound_finish()

        # タブ移動可
        self.release_tab()
        # フォーム有効化
        self.enable()
        # ワーカー終了
        self.convert_arm_ik2fk_worker = None
        # プログレス非表示
        self.gauge_ctrl.SetValue(0)

    def show_worked_time(self):
        # 経過秒数を時分秒に変換
        td_m, td_s = divmod(self.elapsed_time, 60)

        if td_m == 0:
            worked_time = "{0:02d}秒".format(int(td_s))
        else:
            worked_time = "{0:02d}分{1:02d}秒".format(int(td_m), int(td_s))

        return worked_time
Esempio n. 9
0
    def __init__(self, frame: wx.Frame, parent: wx.Notebook, tab_idx: int):
        super().__init__(frame, parent, tab_idx)
        self.convert_smooth_worker = None

        self.header_sizer = wx.BoxSizer(wx.VERTICAL)

        self.description_txt = wx.StaticText(self, wx.ID_ANY, u"指定されたVMDファイルに対して、キーを分割し、滑らかな補間曲線で繋いで、再出力します。\n" \
                                             + "スムージング回数1回で、全打ちとなり、2回目以降はフィルタリングした後に補間曲線で繋ぎます。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.header_sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line01 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                           wx.DefaultSize, wx.LI_HORIZONTAL)
        self.header_sizer.Add(self.static_line01, 0, wx.EXPAND | wx.ALL, 5)

        # 対象VMDファイルコントロール
        self.smooth_vmd_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"対象モーションVMD", u"対象モーションVMDファイルを開く", ("vmd"), wx.FLP_DEFAULT_STYLE, \
                                                          u"調整したい対象モーションのVMDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                          file_model_spacer=0, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="smooth_vmd", is_change_output=True, \
                                                          is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.smooth_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 対象PMXファイルコントロール
        self.smooth_model_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"適用モデルPMX", u"適用モデルPMXファイルを開く", ("pmx"), wx.FLP_DEFAULT_STYLE, \
                                                            u"モーションを適用したいモデルのPMXパスを指定してください。\n人体モデル以外にも適用可能です。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                            file_model_spacer=0, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="smooth_pmx", \
                                                            is_change_output=True, is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.smooth_model_file_ctrl.sizer, 1, wx.EXPAND,
                              0)

        # 出力先VMDファイルコントロール
        self.output_smooth_vmd_file_ctrl = BaseFilePickerCtrl(frame, self, u"出力対象VMD", u"出力対象VMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                              u"調整結果の対象VMD出力パスを指定してください。\n対象VMDファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                              is_aster=False, is_save=True, set_no=1)
        self.header_sizer.Add(self.output_smooth_vmd_file_ctrl.sizer, 1,
                              wx.EXPAND, 0)

        self.sizer.Add(self.header_sizer, 0, wx.EXPAND | wx.ALL, 5)

        self.setting_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # 処理回数
        self.loop_cnt_txt = wx.StaticText(self, wx.ID_ANY, u"処理回数",
                                          wx.DefaultPosition, wx.DefaultSize,
                                          0)
        self.setting_sizer.Add(self.loop_cnt_txt, 0, wx.ALL, 5)

        self.loop_cnt_ctrl = wx.SpinCtrl(self,
                                         id=wx.ID_ANY,
                                         size=wx.Size(60, -1),
                                         value="2",
                                         min=1,
                                         max=99999999,
                                         initial=2)
        self.loop_cnt_ctrl.SetToolTip(
            u"スムージングを行う回数を指定してください。\n1回だと全打ちになります。\n2回目以降はフィルタをかけた上で間引きします。\n回数が増えると、変化が遅く、弱くなります。"
        )
        self.loop_cnt_ctrl.Bind(wx.EVT_SPINCTRL, self.on_change_file)
        self.setting_sizer.Add(self.loop_cnt_ctrl, 0, wx.ALL, 5)

        # 補間
        self.interpolation_txt = wx.StaticText(self, wx.ID_ANY, u"補間方法",
                                               wx.DefaultPosition,
                                               wx.DefaultSize, 0)
        self.setting_sizer.Add(self.interpolation_txt, 0, wx.ALL, 5)

        self.interpolation_ctrl = wx.Choice(
            self,
            id=wx.ID_ANY,
            choices=["補間曲線に従う", "補間曲線無視(円形)", "補間曲線無視(曲線)"])
        self.interpolation_ctrl.SetSelection(0)
        self.interpolation_ctrl.SetToolTip(u"キーとキーの補間方法を指定してください。\n「補間曲線に従う」は、補間曲線に従って繋ぎます。" \
                                           + "\n「補間曲線無視(円形)」は、補間曲線を無視して、\n3つのキーを円周上に置いた円になるように補間します。" \
                                           + "\n「補間曲線無視(曲線)」は、補間曲線を無視して、\nキーを滑らかな曲線(カトマル曲線)で繋いで補間します。")
        self.interpolation_ctrl.Bind(wx.EVT_CHOICE, self.on_change_file)
        self.setting_sizer.Add(self.interpolation_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(self.setting_sizer, 0, wx.EXPAND | wx.ALL, 5)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # スムージング変換実行ボタン
        self.smooth_btn_ctrl = wx.Button(self, wx.ID_ANY,
                                         u"スムージング実行", wx.DefaultPosition,
                                         wx.Size(200, 50), 0)
        self.smooth_btn_ctrl.SetToolTip(u"VMDを滑らかに繋いだモーションを再生成します。")
        self.smooth_btn_ctrl.Bind(wx.EVT_BUTTON, self.on_convert_smooth)
        btn_sizer.Add(self.smooth_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.Layout()
        self.fit()

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_SMOOTH_THREAD, self.on_convert_smooth_result)
Esempio n. 10
0
class SmoothPanel(BasePanel):
    def __init__(self, frame: wx.Frame, parent: wx.Notebook, tab_idx: int):
        super().__init__(frame, parent, tab_idx)
        self.convert_smooth_worker = None

        self.header_sizer = wx.BoxSizer(wx.VERTICAL)

        self.description_txt = wx.StaticText(self, wx.ID_ANY, u"指定されたVMDファイルに対して、キーを分割し、滑らかな補間曲線で繋いで、再出力します。\n" \
                                             + "スムージング回数1回で、全打ちとなり、2回目以降はフィルタリングした後に補間曲線で繋ぎます。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.header_sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line01 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                           wx.DefaultSize, wx.LI_HORIZONTAL)
        self.header_sizer.Add(self.static_line01, 0, wx.EXPAND | wx.ALL, 5)

        # 対象VMDファイルコントロール
        self.smooth_vmd_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"対象モーションVMD", u"対象モーションVMDファイルを開く", ("vmd"), wx.FLP_DEFAULT_STYLE, \
                                                          u"調整したい対象モーションのVMDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                          file_model_spacer=0, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="smooth_vmd", is_change_output=True, \
                                                          is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.smooth_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 対象PMXファイルコントロール
        self.smooth_model_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"適用モデルPMX", u"適用モデルPMXファイルを開く", ("pmx"), wx.FLP_DEFAULT_STYLE, \
                                                            u"モーションを適用したいモデルのPMXパスを指定してください。\n人体モデル以外にも適用可能です。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                            file_model_spacer=0, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="smooth_pmx", \
                                                            is_change_output=True, is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.smooth_model_file_ctrl.sizer, 1, wx.EXPAND,
                              0)

        # 出力先VMDファイルコントロール
        self.output_smooth_vmd_file_ctrl = BaseFilePickerCtrl(frame, self, u"出力対象VMD", u"出力対象VMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                              u"調整結果の対象VMD出力パスを指定してください。\n対象VMDファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                              is_aster=False, is_save=True, set_no=1)
        self.header_sizer.Add(self.output_smooth_vmd_file_ctrl.sizer, 1,
                              wx.EXPAND, 0)

        self.sizer.Add(self.header_sizer, 0, wx.EXPAND | wx.ALL, 5)

        self.setting_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # 処理回数
        self.loop_cnt_txt = wx.StaticText(self, wx.ID_ANY, u"処理回数",
                                          wx.DefaultPosition, wx.DefaultSize,
                                          0)
        self.setting_sizer.Add(self.loop_cnt_txt, 0, wx.ALL, 5)

        self.loop_cnt_ctrl = wx.SpinCtrl(self,
                                         id=wx.ID_ANY,
                                         size=wx.Size(60, -1),
                                         value="2",
                                         min=1,
                                         max=99999999,
                                         initial=2)
        self.loop_cnt_ctrl.SetToolTip(
            u"スムージングを行う回数を指定してください。\n1回だと全打ちになります。\n2回目以降はフィルタをかけた上で間引きします。\n回数が増えると、変化が遅く、弱くなります。"
        )
        self.loop_cnt_ctrl.Bind(wx.EVT_SPINCTRL, self.on_change_file)
        self.setting_sizer.Add(self.loop_cnt_ctrl, 0, wx.ALL, 5)

        # 補間
        self.interpolation_txt = wx.StaticText(self, wx.ID_ANY, u"補間方法",
                                               wx.DefaultPosition,
                                               wx.DefaultSize, 0)
        self.setting_sizer.Add(self.interpolation_txt, 0, wx.ALL, 5)

        self.interpolation_ctrl = wx.Choice(
            self,
            id=wx.ID_ANY,
            choices=["補間曲線に従う", "補間曲線無視(円形)", "補間曲線無視(曲線)"])
        self.interpolation_ctrl.SetSelection(0)
        self.interpolation_ctrl.SetToolTip(u"キーとキーの補間方法を指定してください。\n「補間曲線に従う」は、補間曲線に従って繋ぎます。" \
                                           + "\n「補間曲線無視(円形)」は、補間曲線を無視して、\n3つのキーを円周上に置いた円になるように補間します。" \
                                           + "\n「補間曲線無視(曲線)」は、補間曲線を無視して、\nキーを滑らかな曲線(カトマル曲線)で繋いで補間します。")
        self.interpolation_ctrl.Bind(wx.EVT_CHOICE, self.on_change_file)
        self.setting_sizer.Add(self.interpolation_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(self.setting_sizer, 0, wx.EXPAND | wx.ALL, 5)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # スムージング変換実行ボタン
        self.smooth_btn_ctrl = wx.Button(self, wx.ID_ANY,
                                         u"スムージング実行", wx.DefaultPosition,
                                         wx.Size(200, 50), 0)
        self.smooth_btn_ctrl.SetToolTip(u"VMDを滑らかに繋いだモーションを再生成します。")
        self.smooth_btn_ctrl.Bind(wx.EVT_BUTTON, self.on_convert_smooth)
        btn_sizer.Add(self.smooth_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.Layout()
        self.fit()

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_SMOOTH_THREAD, self.on_convert_smooth_result)

    # ファイル変更時の処理
    def on_change_file(self, event: wx.Event):
        self.set_output_vmd_path(event)

    def set_output_vmd_path(self, event, is_force=False):
        output_smooth_vmd_path = MFileUtils.get_output_smooth_vmd_path(
            self.smooth_vmd_file_ctrl.file_ctrl.GetPath(),
            self.smooth_model_file_ctrl.file_ctrl.GetPath(),
            self.output_smooth_vmd_file_ctrl.file_ctrl.GetPath(),
            self.interpolation_ctrl.GetSelection(),
            self.loop_cnt_ctrl.GetValue(), is_force)

        self.output_smooth_vmd_file_ctrl.file_ctrl.SetPath(
            output_smooth_vmd_path)

        if len(output_smooth_vmd_path) >= 255 and os.name == "nt":
            logger.error("生成予定のファイルパスがWindowsの制限を超えています。\n生成予定パス: {0}".format(
                output_smooth_vmd_path),
                         decoration=MLogger.DECORATION_BOX)

    # フォーム無効化
    def disable(self):
        self.smooth_vmd_file_ctrl.disable()
        self.smooth_model_file_ctrl.disable()
        self.output_smooth_vmd_file_ctrl.disable()
        self.loop_cnt_ctrl.Disable()
        self.interpolation_ctrl.Disable()
        self.smooth_btn_ctrl.Disable()

    # フォーム無効化
    def enable(self):
        self.smooth_vmd_file_ctrl.enable()
        self.smooth_model_file_ctrl.enable()
        self.output_smooth_vmd_file_ctrl.enable()
        self.loop_cnt_ctrl.Enable()
        self.interpolation_ctrl.Enable()
        self.smooth_btn_ctrl.Enable()

    # スムージング変換
    def on_convert_smooth(self, event: wx.Event):
        # フォーム無効化
        self.disable()
        # タブ固定
        self.fix_tab()
        # コンソールクリア
        self.console_ctrl.Clear()
        # 出力先をスムージングパネルのコンソールに変更
        sys.stdout = self.console_ctrl

        wx.GetApp().Yield()

        self.smooth_vmd_file_ctrl.save()
        self.smooth_model_file_ctrl.save()

        # JSON出力
        MFileUtils.save_history(self.frame.mydir_path,
                                self.frame.file_hitories)

        self.elapsed_time = 0
        result = True
        result = self.smooth_vmd_file_ctrl.is_valid(
        ) and self.smooth_model_file_ctrl.is_valid() and result

        if not result:
            # 終了音
            self.frame.sound_finish()
            # タブ移動可
            self.release_tab()
            # フォーム有効化
            self.enable()
            # 出力先をデフォルトに戻す
            sys.stdout = self.frame.file_panel_ctrl.console_ctrl

            return result

        # スムージング変換開始
        if self.convert_smooth_worker:
            logger.error("まだ処理が実行中です。終了してから再度実行してください。",
                         decoration=MLogger.DECORATION_BOX)
        else:
            # 別スレッドで実行
            self.convert_smooth_worker = SmoothWorkerThread(
                self.frame, SmoothThreadEvent, self.frame.is_saving)
            self.convert_smooth_worker.start()

        return result

        event.Skip()

    # スムージング変換完了処理
    def on_convert_smooth_result(self, event: wx.Event):
        self.elapsed_time = event.elapsed_time
        logger.info("\n処理時間: %s", self.show_worked_time())

        # 終了音
        self.frame.sound_finish()

        # タブ移動可
        self.release_tab()
        # フォーム有効化
        self.enable()
        # ワーカー終了
        self.convert_smooth_worker = None
        # プログレス非表示
        self.gauge_ctrl.SetValue(0)

        # 出力先をデフォルトに戻す
        sys.stdout = self.frame.file_panel_ctrl.console_ctrl

    def show_worked_time(self):
        # 経過秒数を時分秒に変換
        td_m, td_s = divmod(self.elapsed_time, 60)

        if td_m == 0:
            worked_time = "{0:02d}秒".format(int(td_s))
        else:
            worked_time = "{0:02d}分{1:02d}秒".format(int(td_m), int(td_s))

        return worked_time
Esempio n. 11
0
    def __init__(self, frame: wx.Frame, parent: wx.Notebook, tab_idx: int):
        super().__init__(frame, parent, tab_idx)
        self.convert_vmd_worker = None

        self.description_txt = wx.StaticText(self, wx.ID_ANY, "指定されたCSVファイル(ボーン+モーフ or カメラ)を、VMDファイルとして出力します。\n" \
                                             + "モデルモーション(ボーン・モーフ)とカメラモーション(カメラ)は別々に出力できます。\n" \
                                             + "CSVのフォーマットは、CSVタブで出力したデータと同じものを定義してください。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                         wx.DefaultSize, wx.LI_HORIZONTAL)
        self.sizer.Add(self.static_line, 0, wx.EXPAND | wx.ALL, 5)

        # CSVファイルコントロール(ボーン)
        self.bone_csv_file_ctrl = BaseFilePickerCtrl(frame, self, u"CSVファイル(ボーン)", u"CSVファイルを選択してください", ("csv"), wx.FLP_DEFAULT_STYLE, \
                                                     u"VMDに変換したいボーンモーションのファイルパスを指定してください。", \
                                                     is_aster=False, is_save=False, set_no=0, required=False)
        self.sizer.Add(self.bone_csv_file_ctrl.sizer, 0, wx.EXPAND | wx.ALL, 0)

        # CSVファイルコントロール(モーフ)
        self.morph_csv_file_ctrl = BaseFilePickerCtrl(frame, self, u"CSVファイル(モーフ)", u"CSVファイルを選択してください", ("csv"), wx.FLP_DEFAULT_STYLE, \
                                                      u"VMDに変換したいモーフモーションのファイルパスを指定してください。", \
                                                      is_aster=False, is_save=False, set_no=0, required=False)
        self.sizer.Add(self.morph_csv_file_ctrl.sizer, 0, wx.EXPAND | wx.ALL,
                       0)

        self.static_line2 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                          wx.DefaultSize, wx.LI_HORIZONTAL)
        self.sizer.Add(self.static_line2, 0, wx.EXPAND | wx.ALL, 5)

        # CSVファイルコントロール(カメラ)
        self.camera_csv_file_ctrl = BaseFilePickerCtrl(frame, self, u"CSVファイル(カメラ)", u"CSVファイルを選択してください", ("csv"), wx.FLP_DEFAULT_STYLE, \
                                                       u"VMDに変換したいカメラモーションのファイルパスを指定してください。", \
                                                       is_aster=False, is_save=False, set_no=0, required=False)
        self.sizer.Add(self.camera_csv_file_ctrl.sizer, 0, wx.EXPAND | wx.ALL,
                       0)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # VMD変換実行ボタン
        self.vmd_btn_ctrl = wx.Button(self, wx.ID_ANY, u"VMD変換実行",
                                      wx.DefaultPosition, wx.Size(200, 50), 0)
        self.vmd_btn_ctrl.SetToolTip(u"CSVをVMDに変換します。")
        self.vmd_btn_ctrl.Bind(wx.EVT_BUTTON, self.on_convert_vmd)
        btn_sizer.Add(self.vmd_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, self.frame.logging_level, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.fit()

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_VMD_THREAD, self.on_convert_vmd_result)
Esempio n. 12
0
class VmdPanel(BasePanel):
    def __init__(self, frame: wx.Frame, parent: wx.Notebook, tab_idx: int):
        super().__init__(frame, parent, tab_idx)
        self.convert_vmd_worker = None

        self.description_txt = wx.StaticText(self, wx.ID_ANY, "指定されたCSVファイル(ボーン+モーフ or カメラ)を、VMDファイルとして出力します。\n" \
                                             + "モデルモーション(ボーン・モーフ)とカメラモーション(カメラ)は別々に出力できます。\n" \
                                             + "CSVのフォーマットは、CSVタブで出力したデータと同じものを定義してください。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                         wx.DefaultSize, wx.LI_HORIZONTAL)
        self.sizer.Add(self.static_line, 0, wx.EXPAND | wx.ALL, 5)

        # CSVファイルコントロール(ボーン)
        self.bone_csv_file_ctrl = BaseFilePickerCtrl(frame, self, u"CSVファイル(ボーン)", u"CSVファイルを選択してください", ("csv"), wx.FLP_DEFAULT_STYLE, \
                                                     u"VMDに変換したいボーンモーションのファイルパスを指定してください。", \
                                                     is_aster=False, is_save=False, set_no=0, required=False)
        self.sizer.Add(self.bone_csv_file_ctrl.sizer, 0, wx.EXPAND | wx.ALL, 0)

        # CSVファイルコントロール(モーフ)
        self.morph_csv_file_ctrl = BaseFilePickerCtrl(frame, self, u"CSVファイル(モーフ)", u"CSVファイルを選択してください", ("csv"), wx.FLP_DEFAULT_STYLE, \
                                                      u"VMDに変換したいモーフモーションのファイルパスを指定してください。", \
                                                      is_aster=False, is_save=False, set_no=0, required=False)
        self.sizer.Add(self.morph_csv_file_ctrl.sizer, 0, wx.EXPAND | wx.ALL,
                       0)

        self.static_line2 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                          wx.DefaultSize, wx.LI_HORIZONTAL)
        self.sizer.Add(self.static_line2, 0, wx.EXPAND | wx.ALL, 5)

        # CSVファイルコントロール(カメラ)
        self.camera_csv_file_ctrl = BaseFilePickerCtrl(frame, self, u"CSVファイル(カメラ)", u"CSVファイルを選択してください", ("csv"), wx.FLP_DEFAULT_STYLE, \
                                                       u"VMDに変換したいカメラモーションのファイルパスを指定してください。", \
                                                       is_aster=False, is_save=False, set_no=0, required=False)
        self.sizer.Add(self.camera_csv_file_ctrl.sizer, 0, wx.EXPAND | wx.ALL,
                       0)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # VMD変換実行ボタン
        self.vmd_btn_ctrl = wx.Button(self, wx.ID_ANY, u"VMD変換実行",
                                      wx.DefaultPosition, wx.Size(200, 50), 0)
        self.vmd_btn_ctrl.SetToolTip(u"CSVをVMDに変換します。")
        self.vmd_btn_ctrl.Bind(wx.EVT_BUTTON, self.on_convert_vmd)
        btn_sizer.Add(self.vmd_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, self.frame.logging_level, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.fit()

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_VMD_THREAD, self.on_convert_vmd_result)

    # フォーム無効化
    def disable(self):
        self.bone_csv_file_ctrl.disable()
        self.morph_csv_file_ctrl.disable()
        self.camera_csv_file_ctrl.disable()
        self.vmd_btn_ctrl.Disable()

    # フォーム無効化
    def enable(self):
        self.bone_csv_file_ctrl.enable()
        self.morph_csv_file_ctrl.enable()
        self.camera_csv_file_ctrl.enable()
        self.vmd_btn_ctrl.Enable()

    # VMD変換
    def on_convert_vmd(self, event: wx.Event):
        # フォーム無効化
        self.disable()
        # タブ固定
        self.fix_tab()
        # コンソールクリア
        self.console_ctrl.Clear()
        # 出力先をVMDパネルのコンソールに変更
        sys.stdout = self.console_ctrl

        wx.GetApp().Yield()

        self.elapsed_time = 0
        result = True
        result = self.bone_csv_file_ctrl.is_valid() and result

        if not result:
            # 終了音
            self.frame.sound_finish()
            # タブ移動可
            self.release_tab()
            # フォーム有効化
            self.enable()
            # 出力先をデフォルトに戻す
            if sys.stdout != self.frame.file_panel_ctrl.console_ctrl:
                sys.stdout = self.frame.file_panel_ctrl.console_ctrl

            return result

        # VMD変換開始
        if self.convert_vmd_worker:
            logger.error("まだ処理が実行中です。終了してから再度実行してください。",
                         decoration=MLogger.DECORATION_BOX)
        else:
            # 別スレッドで実行
            self.convert_vmd_worker = VmdWorkerThread(self.frame,
                                                      VmdThreadEvent)
            self.convert_vmd_worker.start()

        return result

        event.Skip()

    # VMD変換完了処理
    def on_convert_vmd_result(self, event: wx.Event):
        self.elapsed_time = event.elapsed_time

        # 終了音
        self.frame.sound_finish()

        # タブ移動可
        self.release_tab()
        # フォーム有効化
        self.enable()
        # ワーカー終了
        self.convert_vmd_worker = None
        # プログレス非表示
        self.gauge_ctrl.SetValue(0)

        if not event.result:
            logger.error("VMD変換処理に失敗しました。", decoration=MLogger.DECORATION_BOX)

            event.Skip()
            return False

        logger.info("VMD変換が完了しました",
                    decoration=MLogger.DECORATION_BOX,
                    title="OK")

        # 出力先をデフォルトに戻す
        if sys.stdout != self.frame.file_panel_ctrl.console_ctrl:
            sys.stdout = self.frame.file_panel_ctrl.console_ctrl
Esempio n. 13
0
    def __init__(self, frame: wx.Frame, parent: wx.Notebook, tab_idx: int):
        super().__init__(frame, parent, tab_idx)

        self.header_panel = CameraHeaderPanel(self.frame, self, wx.ID_ANY,
                                              wx.DefaultPosition,
                                              wx.DefaultSize, wx.TAB_TRAVERSAL)
        self.header_sizer = wx.BoxSizer(wx.VERTICAL)

        self.description_txt = wx.StaticText(self.header_panel, wx.ID_ANY, u"指定されたカメラモーションのサイジングを、ボーンモーションのサイジングと同時に行えます。\n" \
                                             + "全長オフセットYは、カメラに映す変換先モデルの全長を調整するオフセット値を指定できます。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.header_sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line01 = wx.StaticLine(self.header_panel, wx.ID_ANY,
                                           wx.DefaultPosition, wx.DefaultSize,
                                           wx.LI_HORIZONTAL)
        self.header_sizer.Add(self.static_line01, 0, wx.EXPAND | wx.ALL, 5)

        camera_only_flg_spacer_ctrl = wx.StaticText(self.header_panel,
                                                    wx.ID_ANY,
                                                    u"                     ",
                                                    wx.DefaultPosition,
                                                    wx.DefaultSize, 0)

        # カメラサイジングのみ実行
        self.camera_only_flg_ctrl = wx.CheckBox(self.header_panel, wx.ID_ANY,
                                                u"カメラサイジングのみ実行",
                                                wx.DefaultPosition,
                                                wx.DefaultSize, 0)
        self.camera_only_flg_ctrl.SetToolTip(
            u"ボーンサイジング済みファイルを出力ファイルに指定した上でチェックを入れると、\nそのサイジング済みVMDを元にカメラサイジングを実行します。"
        )
        self.camera_only_flg_ctrl.Bind(wx.EVT_CHECKBOX,
                                       self.set_output_vmd_path)

        # カメラVMDファイルコントロール
        self.camera_vmd_file_ctrl = HistoryFilePickerCtrl(self.frame, self.header_panel, u"カメラモーションVMD", u"カメラモーションVMDファイルを開く", ("vmd"), wx.FLP_DEFAULT_STYLE, \
                                                          u"調整したいカメラモーションのVMDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                          file_model_spacer=0, title_parts_ctrl=camera_only_flg_spacer_ctrl, title_parts2_ctrl=self.camera_only_flg_ctrl, file_histories_key="camera_vmd", \
                                                          is_change_output=True, is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.camera_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 出力先VMDファイルコントロール
        self.output_camera_vmd_file_ctrl = BaseFilePickerCtrl(frame, self.header_panel, u"出力カメラVMD", u"出力カメラVMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                              u"調整結果のカメラVMD出力パスを指定してください。\nカメラVMDファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                              is_aster=False, is_save=True, set_no=1)
        self.header_sizer.Add(self.output_camera_vmd_file_ctrl.sizer, 1,
                              wx.EXPAND, 0)

        # カメラ距離調整スライダー
        self.camera_length_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.camera_length_txt = wx.StaticText(self.header_panel, wx.ID_ANY,
                                               u"距離可動範囲", wx.DefaultPosition,
                                               wx.DefaultSize, 0)
        self.camera_length_txt.SetToolTip(u"ステージの大きさなどにより、カメラの距離の調整範囲を限定したい場合に\n" \
                                          + "カメラの距離可動範囲を限定することができます。\n" \
                                          + "可動範囲は手動で調整する事も可能です。")
        self.camera_length_txt.Wrap(-1)
        self.camera_length_sizer.Add(self.camera_length_txt, 0, wx.ALL, 5)

        self.camera_length_type_ctrl = wx.Choice(
            self.header_panel,
            id=wx.ID_ANY,
            choices=["距離制限強", "距離制限弱", "距離制限なし"])
        self.camera_length_type_ctrl.SetSelection(2)
        self.camera_length_type_ctrl.Bind(wx.EVT_CHOICE,
                                          self.on_camera_length_type)
        self.camera_length_type_ctrl.SetToolTip(u"「距離制限強」 … 小さめのステージ用。距離可動範囲を厳しめに制限します。\n" \
                                                + "「距離制限弱」 … 中くらいのステージ用。距離可動範囲を多少制限します。\n" \
                                                + "「距離制限なし」 … 距離可動範囲を無制限とし、元モデルと同じ映り具合になるよう、最大限調整します。")
        self.camera_length_sizer.Add(self.camera_length_type_ctrl, 0, wx.ALL,
                                     5)

        self.camera_length_label = wx.StaticText(self.header_panel, wx.ID_ANY,
                                                 u"(5)", wx.DefaultPosition,
                                                 wx.DefaultSize, 0)
        self.camera_length_label.SetToolTip(u"現在指定されているカメラ距離の可動範囲です。")
        self.camera_length_label.Wrap(-1)
        self.camera_length_sizer.Add(self.camera_length_label, 0, wx.ALL, 5)

        self.camera_length_slider = FloatSliderCtrl(self.header_panel,
                                                    wx.ID_ANY, 5, 1, 5, 0.01,
                                                    self.camera_length_label,
                                                    wx.DefaultPosition,
                                                    wx.DefaultSize,
                                                    wx.SL_HORIZONTAL)
        self.camera_length_slider.Bind(wx.EVT_SCROLL_CHANGED,
                                       self.set_output_vmd_path)
        self.camera_length_sizer.Add(self.camera_length_slider, 1,
                                     wx.ALL | wx.EXPAND, 5)

        self.header_sizer.Add(self.camera_length_sizer, 0, wx.ALL | wx.EXPAND,
                              5)

        self.header_panel.SetSizer(self.header_sizer)
        self.header_panel.Layout()
        self.sizer.Add(self.header_panel, 0, wx.EXPAND | wx.ALL, 5)

        # カメラセット(key: ファイルセット番号, value: カメラセット)
        self.camera_set_dict = {}
        # Bulk用カメラセット
        self.bulk_camera_set_dict = {}
        # カメラセット用基本Sizer
        self.set_list_sizer = wx.BoxSizer(wx.VERTICAL)

        self.scrolled_window = CameraScrolledWindow(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, \
                                                    wx.FULL_REPAINT_ON_RESIZE | wx.VSCROLL | wx.ALWAYS_SHOW_SB)
        self.scrolled_window.SetScrollRate(5, 5)

        # スクロールバーの表示のためにサイズ調整
        self.scrolled_window.SetSizer(self.set_list_sizer)
        self.scrolled_window.Layout()
        self.sizer.Add(self.scrolled_window, 1,
                       wx.ALL | wx.EXPAND | wx.FIXED_MINSIZE, 5)
        self.sizer.Layout()
        self.fit()
Esempio n. 14
0
class SmoothPanel(BasePanel):
    def __init__(self, frame: wx.Frame, parent: wx.Notebook, tab_idx: int):
        super().__init__(frame, parent, tab_idx)
        self.convert_smooth_worker = None

        self.header_sizer = wx.BoxSizer(wx.VERTICAL)

        self.description_txt = wx.StaticText(self, wx.ID_ANY, u"指定されたVMDファイルに対して、キーを分割し、滑らかな補間曲線で繋いで、再出力します。\n" \
                                             + "スムージング回数1回で、全打ちとなり、2回目以降はフィルタリングした後に補間曲線で繋ぎます。\n" \
                                             + "不要キー削除を行うと、キーが間引きされます。キー間がオリジナルから多少ずれ、やや時間がかかります。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.header_sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line01 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                           wx.DefaultSize, wx.LI_HORIZONTAL)
        self.header_sizer.Add(self.static_line01, 0, wx.EXPAND | wx.ALL, 5)

        # 対象VMDファイルコントロール
        self.smooth_vmd_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"対象モーションVMD", u"対象モーションVMDファイルを開く", ("vmd"), wx.FLP_DEFAULT_STYLE, \
                                                          u"調整したい対象モーションのVMDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                          file_model_spacer=46, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="smooth_vmd", is_change_output=True, \
                                                          is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.smooth_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 対象PMXファイルコントロール
        self.smooth_model_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"適用モデルPMX", u"適用モデルPMXファイルを開く", ("pmx"), wx.FLP_DEFAULT_STYLE, \
                                                            u"モーションを適用したいモデルのPMXパスを指定してください。\n人体モデル以外にも適用可能です。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                            file_model_spacer=52, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="smooth_pmx", \
                                                            is_change_output=True, is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.smooth_model_file_ctrl.sizer, 1, wx.EXPAND,
                              0)

        # 出力先VMDファイルコントロール
        self.output_smooth_vmd_file_ctrl = BaseFilePickerCtrl(frame, self, u"出力対象VMD", u"出力対象VMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                              u"調整結果の対象VMD出力パスを指定してください。\n対象VMDファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                              is_aster=False, is_save=True, set_no=1)
        self.header_sizer.Add(self.output_smooth_vmd_file_ctrl.sizer, 1,
                              wx.EXPAND, 0)

        self.sizer.Add(self.header_sizer, 0, wx.EXPAND | wx.ALL, 5)

        self.target_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # ボーン名指定
        self.bone_target_txt_ctrl = wx.TextCtrl(
            self, wx.ID_ANY, "", wx.DefaultPosition, (450, 50),
            wx.HSCROLL | wx.VSCROLL | wx.TE_MULTILINE | wx.TE_READONLY)
        self.bone_target_txt_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.target_sizer.Add(self.bone_target_txt_ctrl, 1, wx.EXPAND | wx.ALL,
                              5)

        self.bone_target_btn_ctrl = wx.Button(self, wx.ID_ANY, u"対象指定",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        self.bone_target_btn_ctrl.SetToolTip(
            u"モーションに登録されているボーン・モーフから、スムージングにかけたいボーン・モーフを指定できます")
        self.bone_target_btn_ctrl.Bind(wx.EVT_BUTTON,
                                       self.on_click_bone_target)
        self.target_sizer.Add(self.bone_target_btn_ctrl, 0,
                              wx.ALIGN_BOTTOM | wx.ALL, 5)

        self.sizer.Add(self.target_sizer, 0, wx.EXPAND | wx.ALL, 5)

        self.setting_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # 処理回数
        self.loop_cnt_txt = wx.StaticText(self, wx.ID_ANY, u"処理回数",
                                          wx.DefaultPosition, wx.DefaultSize,
                                          0)
        self.setting_sizer.Add(self.loop_cnt_txt, 0, wx.ALL, 5)

        self.loop_cnt_ctrl = wx.SpinCtrl(self,
                                         id=wx.ID_ANY,
                                         size=wx.Size(60, -1),
                                         value="2",
                                         min=1,
                                         max=99999999,
                                         initial=2)
        self.loop_cnt_ctrl.SetToolTip(
            u"スムージングを行う回数を指定してください。\n1回だと全打ちになります。\n2回目以降はフィルタをかけた上で間引きします。\n回数が増えると、変化が遅く、弱くなります。"
        )
        self.loop_cnt_ctrl.Bind(wx.EVT_SPINCTRL, self.on_change_file)
        self.setting_sizer.Add(self.loop_cnt_ctrl, 0, wx.ALL, 5)

        # 補間
        self.interpolation_txt = wx.StaticText(self, wx.ID_ANY, u"補間方法",
                                               wx.DefaultPosition,
                                               wx.DefaultSize, 0)
        self.setting_sizer.Add(self.interpolation_txt, 0, wx.ALL, 5)

        self.interpolation_ctrl = wx.Choice(
            self,
            id=wx.ID_ANY,
            choices=["補間曲線に従う", "補間曲線無視(円形)", "補間曲線無視(曲線)"])
        self.interpolation_ctrl.SetSelection(0)
        self.interpolation_ctrl.SetToolTip(u"キーとキーの補間方法を指定してください。\n「補間曲線に従う」は、補間曲線に従って繋ぎます。" \
                                           + "\n「補間曲線無視(円形)」は、補間曲線を無視して、\n3つのキーを円周上に置いた円になるように補間します。" \
                                           + "\n「補間曲線無視(曲線)」は、補間曲線を無視して、\nキーを滑らかな曲線(カトマル曲線)で繋いで補間します。")
        self.interpolation_ctrl.Bind(wx.EVT_CHOICE, self.on_change_file)
        self.setting_sizer.Add(self.interpolation_ctrl, 0, wx.ALL, 5)

        # 不要キー削除処理
        self.remove_unnecessary_flg_ctrl = wx.CheckBox(self, wx.ID_ANY,
                                                       u"不要キー削除処理を追加実行する",
                                                       wx.DefaultPosition,
                                                       wx.DefaultSize, 0)
        self.remove_unnecessary_flg_ctrl.SetToolTip(
            u"チェックを入れると、不要キー削除処理を追加で実行します。キーが減る分、キー間が少しズレる事があります。")
        self.remove_unnecessary_flg_ctrl.Bind(wx.EVT_CHECKBOX,
                                              self.on_change_file)
        self.setting_sizer.Add(self.remove_unnecessary_flg_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(self.setting_sizer, 0, wx.EXPAND | wx.ALL, 5)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # スムージング変換実行ボタン
        self.smooth_btn_ctrl = wx.Button(self, wx.ID_ANY,
                                         u"スムージング実行", wx.DefaultPosition,
                                         wx.Size(200, 50), 0)
        self.smooth_btn_ctrl.SetToolTip(u"VMDを滑らかに繋いだモーションを再生成します。")
        self.smooth_btn_ctrl.Bind(wx.EVT_BUTTON, self.on_convert_smooth)
        self.smooth_btn_ctrl.Bind(wx.EVT_LEFT_DCLICK, self.on_doubleclick)
        btn_sizer.Add(self.smooth_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, self.frame.logging_level, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.Layout()
        self.fit()

        # ボーン選択用ダイアログ
        self.bone_dialog = TargetBoneDialog(self.frame, self)
        self.bone_list = []

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_SMOOTH_THREAD, self.on_convert_smooth_result)

    # ファイル変更時の処理
    def on_change_file(self, event: wx.Event):
        self.set_output_vmd_path(event)

    def set_output_vmd_path(self, event, is_force=False):
        output_smooth_vmd_path = MFileUtils.get_output_smooth_vmd_path(
            self.smooth_vmd_file_ctrl.file_ctrl.GetPath(),
            self.smooth_model_file_ctrl.file_ctrl.GetPath(),
            self.output_smooth_vmd_file_ctrl.file_ctrl.GetPath(),
            self.interpolation_ctrl.GetSelection(),
            self.loop_cnt_ctrl.GetValue(), is_force)

        self.output_smooth_vmd_file_ctrl.file_ctrl.SetPath(
            output_smooth_vmd_path)

        if len(output_smooth_vmd_path) >= 255 and os.name == "nt":
            logger.error("生成予定のファイルパスがWindowsの制限を超えています。\n生成予定パス: {0}".format(
                output_smooth_vmd_path),
                         decoration=MLogger.DECORATION_BOX)

    # フォーム無効化
    def disable(self):
        self.smooth_vmd_file_ctrl.disable()
        self.smooth_model_file_ctrl.disable()
        self.output_smooth_vmd_file_ctrl.disable()
        self.loop_cnt_ctrl.Disable()
        self.interpolation_ctrl.Disable()
        self.smooth_btn_ctrl.Disable()
        self.remove_unnecessary_flg_ctrl.Disable()

    # フォーム無効化
    def enable(self):
        self.smooth_vmd_file_ctrl.enable()
        self.smooth_model_file_ctrl.enable()
        self.output_smooth_vmd_file_ctrl.enable()
        self.loop_cnt_ctrl.Enable()
        self.interpolation_ctrl.Enable()
        self.smooth_btn_ctrl.Enable()
        self.remove_unnecessary_flg_ctrl.Enable()

    def on_doubleclick(self, event: wx.Event):
        self.timer.Stop()
        logger.warning("ダブルクリックされました。", decoration=MLogger.DECORATION_BOX)
        event.Skip(False)
        return False

    # 多段分割変換
    def on_convert_smooth(self, event: wx.Event):
        self.timer = wx.Timer(self, TIMER_ID)
        self.timer.Start(200)
        self.Bind(wx.EVT_TIMER, self.on_convert, id=TIMER_ID)

    # スムージング変換
    def on_convert(self, event: wx.Event):
        self.timer.Stop()
        self.Unbind(wx.EVT_TIMER, id=TIMER_ID)
        # フォーム無効化
        self.disable()
        # タブ固定
        self.fix_tab()
        # コンソールクリア
        self.console_ctrl.Clear()
        # 出力先をスムージングパネルのコンソールに変更
        sys.stdout = self.console_ctrl

        wx.GetApp().Yield()

        self.smooth_vmd_file_ctrl.save()
        self.smooth_model_file_ctrl.save()

        # JSON出力
        MFileUtils.save_history(self.frame.mydir_path,
                                self.frame.file_hitories)

        self.elapsed_time = 0
        result = True
        result = self.smooth_vmd_file_ctrl.is_valid(
        ) and self.smooth_model_file_ctrl.is_valid() and result

        # スムージング変換開始
        if self.smooth_btn_ctrl.GetLabel(
        ) == "スムージング停止" and self.convert_smooth_worker:
            # フォーム無効化
            self.disable()
            # 停止状態でボタン押下時、停止
            self.convert_smooth_worker.stop()

            # タブ移動可
            self.frame.release_tab()
            # フォーム有効化
            self.frame.enable()
            # ワーカー終了
            self.convert_smooth_worker = None
            # プログレス非表示
            self.gauge_ctrl.SetValue(0)

            logger.warning("スムージングを中断します。", decoration=MLogger.DECORATION_BOX)
            self.smooth_btn_ctrl.SetLabel("スムージング実行")

            event.Skip(False)
        elif not self.convert_smooth_worker:
            # フォーム無効化
            self.disable()
            # タブ固定
            self.fix_tab()
            # コンソールクリア
            self.console_ctrl.Clear()
            # ラベル変更
            self.smooth_btn_ctrl.SetLabel("スムージング停止")
            self.smooth_btn_ctrl.Enable()

            self.convert_smooth_worker = SmoothWorkerThread(
                self.frame, SmoothThreadEvent, self.frame.is_saving,
                self.frame.is_out_log)
            self.convert_smooth_worker.start()

            event.Skip()
        else:
            logger.error("まだ処理が実行中です。終了してから再度実行してください。",
                         decoration=MLogger.DECORATION_BOX)
            event.Skip(False)

        return result

    # スムージング変換完了処理
    def on_convert_smooth_result(self, event: wx.Event):
        self.elapsed_time = event.elapsed_time
        logger.info("\n処理時間: %s", self.show_worked_time())
        self.smooth_btn_ctrl.SetLabel("スムージング実行")

        # 終了音
        self.frame.sound_finish()

        # タブ移動可
        self.release_tab()
        # フォーム有効化
        self.enable()
        # ワーカー終了
        self.convert_smooth_worker = None
        # プログレス非表示
        self.gauge_ctrl.SetValue(0)

    def show_worked_time(self):
        # 経過秒数を時分秒に変換
        td_m, td_s = divmod(self.elapsed_time, 60)

        if td_m == 0:
            worked_time = "{0:02d}秒".format(int(td_s))
        else:
            worked_time = "{0:02d}分{1:02d}秒".format(int(td_m), int(td_s))

        return worked_time

    def on_click_bone_target(self, event: wx.Event):
        self.disable()

        sys.stdout = self.console_ctrl
        # VMD読み込み
        self.smooth_vmd_file_ctrl.load()
        # PMX読み込み
        self.smooth_model_file_ctrl.load()

        if (self.smooth_vmd_file_ctrl.data and self.smooth_model_file_ctrl.data and \
                (self.smooth_vmd_file_ctrl.data.digest != self.bone_dialog.vmd_digest or self.smooth_model_file_ctrl.data.digest != self.bone_dialog.pmx_digest)):

            # データが揃ってたら押下可能
            self.bone_target_btn_ctrl.Enable()
            # リストクリア
            self.bone_target_txt_ctrl.SetValue("")
            # ボーン選択用ダイアログ
            self.bone_dialog.Destroy()
            self.bone_dialog = TargetBoneDialog(self.frame, self)
        else:
            if not self.smooth_vmd_file_ctrl.data or not self.smooth_model_file_ctrl.data:
                logger.error("対象モーションVMDもしくは適用モデルPMXが未指定です。",
                             decoration=MLogger.DECORATION_BOX)
                self.enable()
                return

        self.enable()

        if self.bone_dialog.ShowModal() == wx.ID_CANCEL:
            return  # the user changed their mind

        # 選択されたボーンリストを入力欄に設定
        self.bone_list = self.bone_dialog.get_bone_list()
        self.bone_target_txt_ctrl.SetValue(', '.join(self.bone_list))

        self.bone_dialog.Hide()

    def get_bone_list(self):
        return self.bone_list
Esempio n. 15
0
    def __init__(self, frame: wx.Frame, noise: wx.Notebook, tab_idx: int):
        super().__init__(frame, noise, tab_idx)
        self.timer = wx.Timer(self, TIMER_ID)
        self.convert_noise_worker = None

        self.header_sizer = wx.BoxSizer(wx.VERTICAL)

        self.description_txt = wx.StaticText(self, wx.ID_ANY, u"モーションをゆらぎ(ノイズ)を付与して複製します。\n" \
                                             + "出力ファイル名のNxxは指定ゆらぎの大きさ、nxxxは複製連番、axxはやる気係数(身体の振りの大きさ)です。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.header_sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line01 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                           wx.DefaultSize, wx.LI_HORIZONTAL)
        self.header_sizer.Add(self.static_line01, 0, wx.EXPAND | wx.ALL, 5)

        # 対象VMDファイルコントロール
        self.noise_vmd_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"対象モーションVMD/VPD", u"対象モーションVMD/VPDファイルを開く", ("vmd", "vpd"), wx.FLP_DEFAULT_STYLE, \
                                                         u"調整したい対象モーションのVMDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                         file_model_spacer=46, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="noise_vmd", is_change_output=True, \
                                                         is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.noise_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 出力先VMDファイルコントロール
        self.output_noise_vmd_file_ctrl = BaseFilePickerCtrl(frame, self, u"出力対象VMD", u"出力対象VMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                             u"調整結果の対象VMD出力パスを指定してください。\n対象VMDファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                             is_aster=False, is_save=True, set_no=1)
        self.header_sizer.Add(self.output_noise_vmd_file_ctrl.sizer, 1,
                              wx.EXPAND, 0)

        self.sizer.Add(self.header_sizer, 0, wx.EXPAND | wx.ALL, 5)

        self.setting_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # ゆらぎの大きさ
        self.noise_size_txt = wx.StaticText(self, wx.ID_ANY, u"ゆらぎの大きさ",
                                            wx.DefaultPosition, wx.DefaultSize,
                                            0)
        self.setting_sizer.Add(self.noise_size_txt, 0, wx.ALL, 5)

        self.noise_size_ctrl = wx.SpinCtrl(self,
                                           id=wx.ID_ANY,
                                           size=wx.Size(60, -1),
                                           value="8",
                                           min=0,
                                           max=99999999,
                                           initial=8)
        self.noise_size_ctrl.SetToolTip(
            u"ゆらぎの大きさを指定して下さい。値が大きいほど、ゆらぎが大きくなります。")
        self.noise_size_ctrl.Bind(wx.EVT_SPINCTRL, self.on_change_file)
        self.setting_sizer.Add(self.noise_size_ctrl, 0, wx.ALL, 5)

        # 複製数
        self.copy_cnt_txt = wx.StaticText(self, wx.ID_ANY, u"複製数",
                                          wx.DefaultPosition, wx.DefaultSize,
                                          0)
        self.setting_sizer.Add(self.copy_cnt_txt, 0, wx.ALL, 5)

        self.copy_cnt_ctrl = wx.SpinCtrl(self,
                                         id=wx.ID_ANY,
                                         size=wx.Size(60, -1),
                                         value="2",
                                         min=1,
                                         max=99999999,
                                         initial=2)
        self.copy_cnt_ctrl.SetToolTip(u"複製する数を指定して下さい。")
        self.copy_cnt_ctrl.Bind(wx.EVT_SPINCTRL, self.on_change_file)
        self.setting_sizer.Add(self.copy_cnt_ctrl, 0, wx.ALL, 5)

        # やる気係数
        self.motivation_flg_ctrl = wx.CheckBox(self, wx.ID_ANY, u"やる気係数を適用する",
                                               wx.DefaultPosition,
                                               wx.DefaultSize, 0)
        self.motivation_flg_ctrl.SetToolTip(
            u"チェックを入れると、やる気係数もランダムに発生します。\nやる気係数は値が大きいほどモーションの振り幅が大きくなります。\n値が小さいほどモーションの振り幅が小さくなります。"
        )
        self.setting_sizer.Add(self.motivation_flg_ctrl, 0, wx.ALL, 5)

        # 指ゆらぎ
        self.finger_noise_flg_ctrl = wx.CheckBox(self, wx.ID_ANY,
                                                 u"指にもゆらぎを適用する",
                                                 wx.DefaultPosition,
                                                 wx.DefaultSize, 0)
        self.finger_noise_flg_ctrl.SetToolTip(
            u"チェックを入れると、「指」をボーン名に含むボーンも揺らがせます。")
        self.setting_sizer.Add(self.finger_noise_flg_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(self.setting_sizer, 0, wx.EXPAND | wx.ALL, 5)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # 実行ボタン
        self.noise_btn_ctrl = wx.Button(self, wx.ID_ANY,
                                        u"ゆらぎ複製", wx.DefaultPosition,
                                        wx.Size(200, 50), 0)
        self.noise_btn_ctrl.SetToolTip(u"ゆらぎを付与したモーションを複製します")
        self.noise_btn_ctrl.Bind(wx.EVT_LEFT_DOWN, self.on_convert_noise)
        self.noise_btn_ctrl.Bind(wx.EVT_LEFT_DCLICK, self.on_doubleclick)
        btn_sizer.Add(self.noise_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, self.frame.logging_level, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.Layout()
        self.fit()

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_SMOOTH_THREAD, self.on_convert_noise_result)
Esempio n. 16
0
class NoisePanel(BasePanel):
    def __init__(self, frame: wx.Frame, noise: wx.Notebook, tab_idx: int):
        super().__init__(frame, noise, tab_idx)
        self.timer = wx.Timer(self, TIMER_ID)
        self.convert_noise_worker = None

        self.header_sizer = wx.BoxSizer(wx.VERTICAL)

        self.description_txt = wx.StaticText(self, wx.ID_ANY, u"モーションをゆらぎ(ノイズ)を付与して複製します。\n" \
                                             + "出力ファイル名のNxxは指定ゆらぎの大きさ、nxxxは複製連番、axxはやる気係数(身体の振りの大きさ)です。", wx.DefaultPosition, wx.DefaultSize, 0)
        self.header_sizer.Add(self.description_txt, 0, wx.ALL, 5)

        self.static_line01 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                           wx.DefaultSize, wx.LI_HORIZONTAL)
        self.header_sizer.Add(self.static_line01, 0, wx.EXPAND | wx.ALL, 5)

        # 対象VMDファイルコントロール
        self.noise_vmd_file_ctrl = HistoryFilePickerCtrl(self.frame, self, u"対象モーションVMD/VPD", u"対象モーションVMD/VPDファイルを開く", ("vmd", "vpd"), wx.FLP_DEFAULT_STYLE, \
                                                         u"調整したい対象モーションのVMDパスを指定してください。\nD&Dでの指定、開くボタンからの指定、履歴からの選択ができます。", \
                                                         file_model_spacer=46, title_parts_ctrl=None, title_parts2_ctrl=None, file_histories_key="noise_vmd", is_change_output=True, \
                                                         is_aster=False, is_save=False, set_no=1)
        self.header_sizer.Add(self.noise_vmd_file_ctrl.sizer, 1, wx.EXPAND, 0)

        # 出力先VMDファイルコントロール
        self.output_noise_vmd_file_ctrl = BaseFilePickerCtrl(frame, self, u"出力対象VMD", u"出力対象VMDファイルを開く", ("vmd"), wx.FLP_OVERWRITE_PROMPT | wx.FLP_SAVE | wx.FLP_USE_TEXTCTRL, \
                                                             u"調整結果の対象VMD出力パスを指定してください。\n対象VMDファイル名に基づいて自動生成されますが、任意のパスに変更することも可能です。", \
                                                             is_aster=False, is_save=True, set_no=1)
        self.header_sizer.Add(self.output_noise_vmd_file_ctrl.sizer, 1,
                              wx.EXPAND, 0)

        self.sizer.Add(self.header_sizer, 0, wx.EXPAND | wx.ALL, 5)

        self.setting_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # ゆらぎの大きさ
        self.noise_size_txt = wx.StaticText(self, wx.ID_ANY, u"ゆらぎの大きさ",
                                            wx.DefaultPosition, wx.DefaultSize,
                                            0)
        self.setting_sizer.Add(self.noise_size_txt, 0, wx.ALL, 5)

        self.noise_size_ctrl = wx.SpinCtrl(self,
                                           id=wx.ID_ANY,
                                           size=wx.Size(60, -1),
                                           value="8",
                                           min=0,
                                           max=99999999,
                                           initial=8)
        self.noise_size_ctrl.SetToolTip(
            u"ゆらぎの大きさを指定して下さい。値が大きいほど、ゆらぎが大きくなります。")
        self.noise_size_ctrl.Bind(wx.EVT_SPINCTRL, self.on_change_file)
        self.setting_sizer.Add(self.noise_size_ctrl, 0, wx.ALL, 5)

        # 複製数
        self.copy_cnt_txt = wx.StaticText(self, wx.ID_ANY, u"複製数",
                                          wx.DefaultPosition, wx.DefaultSize,
                                          0)
        self.setting_sizer.Add(self.copy_cnt_txt, 0, wx.ALL, 5)

        self.copy_cnt_ctrl = wx.SpinCtrl(self,
                                         id=wx.ID_ANY,
                                         size=wx.Size(60, -1),
                                         value="2",
                                         min=1,
                                         max=99999999,
                                         initial=2)
        self.copy_cnt_ctrl.SetToolTip(u"複製する数を指定して下さい。")
        self.copy_cnt_ctrl.Bind(wx.EVT_SPINCTRL, self.on_change_file)
        self.setting_sizer.Add(self.copy_cnt_ctrl, 0, wx.ALL, 5)

        # やる気係数
        self.motivation_flg_ctrl = wx.CheckBox(self, wx.ID_ANY, u"やる気係数を適用する",
                                               wx.DefaultPosition,
                                               wx.DefaultSize, 0)
        self.motivation_flg_ctrl.SetToolTip(
            u"チェックを入れると、やる気係数もランダムに発生します。\nやる気係数は値が大きいほどモーションの振り幅が大きくなります。\n値が小さいほどモーションの振り幅が小さくなります。"
        )
        self.setting_sizer.Add(self.motivation_flg_ctrl, 0, wx.ALL, 5)

        # 指ゆらぎ
        self.finger_noise_flg_ctrl = wx.CheckBox(self, wx.ID_ANY,
                                                 u"指にもゆらぎを適用する",
                                                 wx.DefaultPosition,
                                                 wx.DefaultSize, 0)
        self.finger_noise_flg_ctrl.SetToolTip(
            u"チェックを入れると、「指」をボーン名に含むボーンも揺らがせます。")
        self.setting_sizer.Add(self.finger_noise_flg_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(self.setting_sizer, 0, wx.EXPAND | wx.ALL, 5)

        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # 実行ボタン
        self.noise_btn_ctrl = wx.Button(self, wx.ID_ANY,
                                        u"ゆらぎ複製", wx.DefaultPosition,
                                        wx.Size(200, 50), 0)
        self.noise_btn_ctrl.SetToolTip(u"ゆらぎを付与したモーションを複製します")
        self.noise_btn_ctrl.Bind(wx.EVT_LEFT_DOWN, self.on_convert_noise)
        self.noise_btn_ctrl.Bind(wx.EVT_LEFT_DCLICK, self.on_doubleclick)
        btn_sizer.Add(self.noise_btn_ctrl, 0, wx.ALL, 5)

        self.sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.SHAPED, 5)

        # コンソール
        self.console_ctrl = ConsoleCtrl(self, self.frame.logging_level, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size(-1, 420), \
                                        wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL | wx.WANTS_CHARS)
        self.console_ctrl.SetBackgroundColour(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DLIGHT))
        self.console_ctrl.Bind(
            wx.EVT_CHAR,
            lambda event: MFormUtils.on_select_all(event, self.console_ctrl))
        self.sizer.Add(self.console_ctrl, 1, wx.ALL | wx.EXPAND, 5)

        # ゲージ
        self.gauge_ctrl = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition,
                                   wx.DefaultSize, wx.GA_HORIZONTAL)
        self.gauge_ctrl.SetValue(0)
        self.sizer.Add(self.gauge_ctrl, 0, wx.ALL | wx.EXPAND, 5)

        self.Layout()
        self.fit()

        # フレームに変換完了処理バインド
        self.frame.Bind(EVT_SMOOTH_THREAD, self.on_convert_noise_result)

    def on_wheel_spin_ctrl(self, event: wx.Event, inc=1):
        # self.frame.on_wheel_spin_ctrl(event, inc)
        self.set_output_vmd_path(event)

    # ファイル変更時の処理
    def on_change_file(self, event: wx.Event):
        self.set_output_vmd_path(event, is_force=True)

    def set_output_vmd_path(self, event, is_force=False):
        output_noise_vmd_path = MFileUtils.get_output_noise_vmd_path(
            self.noise_vmd_file_ctrl.file_ctrl.GetPath(),
            self.output_noise_vmd_file_ctrl.file_ctrl.GetPath(),
            self.noise_size_ctrl.GetValue(), is_force)

        self.output_noise_vmd_file_ctrl.file_ctrl.SetPath(
            output_noise_vmd_path)

        if len(output_noise_vmd_path) >= 255 and os.name == "nt":
            logger.error("生成予定のファイルパスがWindowsの制限を超えています。\n生成予定パス: {0}".format(
                output_noise_vmd_path),
                         decoration=MLogger.DECORATION_BOX)

    # フォーム無効化
    def disable(self):
        self.noise_vmd_file_ctrl.disable()
        self.output_noise_vmd_file_ctrl.disable()
        self.noise_btn_ctrl.Disable()

    # フォーム無効化
    def enable(self):
        self.noise_vmd_file_ctrl.enable()
        self.output_noise_vmd_file_ctrl.enable()
        self.noise_btn_ctrl.Enable()

    def on_doubleclick(self, event: wx.Event):
        self.timer.Stop()
        logger.warning("ダブルクリックされました。", decoration=MLogger.DECORATION_BOX)
        event.Skip(False)
        return False

    # 多段分割変換
    def on_convert_noise(self, event: wx.Event):
        self.timer.Start(200)
        self.Bind(wx.EVT_TIMER, self.on_convert, id=TIMER_ID)

    # 多段分割変換
    def on_convert(self, event: wx.Event):
        self.timer.Stop()
        self.Unbind(wx.EVT_TIMER, id=TIMER_ID)
        # フォーム無効化
        self.disable()
        # タブ固定
        self.fix_tab()
        # コンソールクリア
        self.console_ctrl.Clear()
        # 出力先を多段分割パネルのコンソールに変更
        sys.stdout = self.console_ctrl

        self.noise_vmd_file_ctrl.save()

        # JSON出力
        MFileUtils.save_history(self.frame.mydir_path,
                                self.frame.file_hitories)

        self.elapsed_time = 0
        result = True
        result = self.noise_vmd_file_ctrl.is_valid() and result

        if not result:
            # 終了音
            self.frame.sound_finish()
            # タブ移動可
            self.release_tab()
            # フォーム有効化
            self.enable()

            return result

        # ゆらぎ複製変換開始
        if self.noise_btn_ctrl.GetLabel(
        ) == "ゆらぎ複製停止" and self.convert_noise_worker:
            # フォーム無効化
            self.disable()
            # 停止状態でボタン押下時、停止
            self.convert_noise_worker.stop()

            # タブ移動可
            self.frame.release_tab()
            # フォーム有効化
            self.frame.enable()
            # ワーカー終了
            self.convert_noise_worker = None
            # プログレス非表示
            self.gauge_ctrl.SetValue(0)

            logger.warning("ゆらぎ複製を中断します。", decoration=MLogger.DECORATION_BOX)
            self.noise_btn_ctrl.SetLabel("ゆらぎ複製")

            event.Skip(False)
        elif not self.convert_noise_worker:
            # フォーム無効化
            self.disable()
            # タブ固定
            self.fix_tab()
            # コンソールクリア
            self.console_ctrl.Clear()
            # ラベル変更
            self.noise_btn_ctrl.SetLabel("ゆらぎ複製停止")
            self.noise_btn_ctrl.Enable()

            self.convert_noise_worker = NoiseWorkerThread(
                self.frame, NoiseThreadEvent, self.frame.is_saving,
                self.frame.is_out_log)
            self.convert_noise_worker.start()

            event.Skip()
        else:
            logger.error("まだ処理が実行中です。終了してから再度実行してください。",
                         decoration=MLogger.DECORATION_BOX)
            event.Skip(False)

        return result

    # 多段分割変換完了処理
    def on_convert_noise_result(self, event: wx.Event):
        self.elapsed_time = event.elapsed_time
        logger.info("\n処理時間: %s", self.show_worked_time())
        self.noise_btn_ctrl.SetLabel("ゆらぎ複製")

        # 終了音
        self.frame.sound_finish()

        # タブ移動可
        self.release_tab()
        # フォーム有効化
        self.enable()
        # ワーカー終了
        self.convert_noise_worker = None
        # プログレス非表示
        self.gauge_ctrl.SetValue(0)

    def show_worked_time(self):
        # 経過秒数を時分秒に変換
        td_m, td_s = divmod(self.elapsed_time, 60)

        if td_m == 0:
            worked_time = "{0:02d}秒".format(int(td_s))
        else:
            worked_time = "{0:02d}分{1:02d}秒".format(int(td_m), int(td_s))

        return worked_time