Esempio n. 1
0
    def load(self, file_idx=0, is_check=True):
        if not self.is_set_path():
            # パスが指定されてない場合、そのまま終了
            self.data = None
            return True

        if not self.is_valid():
            # 読み込み可能か
            self.data = None
            return False

        try:
            if self.set_no == 0:
                # CSVとかのファイルは番号出力なし
                display_set_no = ""
            else:
                display_set_no = "【No.{0}】 ".format(self.set_no)

            if self.is_aster and self.set_no == 1:
                base_file_path = self.file_ctrl.GetPath()

                if os.path.exists(base_file_path):
                    file_path_list = [base_file_path]
                else:
                    file_path_list = [p for p in glob.glob(base_file_path) if os.path.isfile(p)]

                if len(file_path_list) == 0:
                    # 読み込み可能か
                    self.data = None
                    return False

                file_path = file_path_list[file_idx]
            else:
                file_path = self.file_ctrl.GetPath()

            file_name, input_ext = os.path.splitext(os.path.basename(file_path))

            # 拡張子別にリーダー生成
            if input_ext.lower() == ".vmd":
                reader = VmdReader(file_path)
            elif input_ext.lower() == ".vpd":
                reader = VpdReader(file_path)
            elif input_ext.lower() == ".pmx":
                reader = PmxReader(file_path, is_check=is_check)
            else:
                logger.error("%s%s 読み込み失敗(拡張子不正): %s", display_set_no, self.title, os.path.basename(file_path), decoration=MLogger.DECORATION_BOX)
                return False
            
            # ハッシュ値取得
            new_data_digest = reader.hexdigest()

            # 新規データがあり、かつハッシュが違う場合、置き換え
            if new_data_digest and ((self.data and self.data.digest != new_data_digest) or not self.data):
                # ハッシュが取得できてて、過去データがないかハッシュが違う場合、読み込み
                self.data = reader.read_data()
                    
                logger.info("%s%s 読み込み成功: %s", display_set_no, self.title, os.path.basename(file_path))
                return True
            elif new_data_digest and self.data and self.data.digest == new_data_digest:
                # ハッシュが同じ場合、そのままスルー
                logger.info("%s%s 読み込み成功: %s", display_set_no, self.title, os.path.basename(file_path))
                return True
        except MKilledException:
            logger.warning("読み込み処理を中断します。", decoration=MLogger.DECORATION_BOX)
        except SizingException as se:
            logger.error("サイジング処理が処理できないデータで終了しました。\n\n%s", se.message, decoration=MLogger.DECORATION_BOX)
        except Exception as e:
            logger.critical("サイジング処理が意図せぬエラーで終了しました。", e, decoration=MLogger.DECORATION_BOX)
        finally:
            logging.shutdown()

        logger.error("%s%s 読み込み失敗: %s", display_set_no, self.title, os.path.basename(file_path), decoration=MLogger.DECORATION_BOX)
        return False
Esempio n. 2
0
    def execute(self):
        logging.basicConfig(level=self.options.logging_level, format="%(message)s [%(module_name)s]")

        try:
            service_data_txt = "VMDサイジング処理実行\n------------------------\nexeバージョン: {version_name}\n".format(version_name=self.options.version_name)

            for data_set_idx, data_set in enumerate(self.options.data_set_list):
                service_data_txt = "{service_data_txt}\n【No.{no}】 --------- \n".format(service_data_txt=service_data_txt, no=(data_set_idx+1)) # noqa
                service_data_txt = "{service_data_txt}  モーション: {motion}\n".format(service_data_txt=service_data_txt,
                                        motion=os.path.basename(data_set.motion.path)) # noqa
                service_data_txt = "{service_data_txt}  作成元モデル: {trace_model} ({model_name})\n".format(service_data_txt=service_data_txt,
                                        trace_model=os.path.basename(data_set.org_model.path), model_name=data_set.org_model.name) # noqa
                service_data_txt = "{service_data_txt}  変換先モデル: {replace_model} ({model_name})\n".format(service_data_txt=service_data_txt,
                                        replace_model=os.path.basename(data_set.rep_model.path), model_name=data_set.rep_model.name) # noqa
                if data_set.camera_org_model:
                    service_data_txt = "{service_data_txt}  カメラ作成元モデル: {trace_model} ({model_name})\n".format(service_data_txt=service_data_txt,
                                            trace_model=os.path.basename(data_set.camera_org_model.path), model_name=data_set.camera_org_model.name) # noqa
                    service_data_txt = "{service_data_txt}  Yオフセット: {camera_offset_y}\n".format(service_data_txt=service_data_txt,
                                            camera_offset_y=data_set.camera_offset_y) # noqa
                service_data_txt = "{service_data_txt}  スタンス追加補正有無: {detail_stance_flg}\n".format(service_data_txt=service_data_txt,
                                        detail_stance_flg=data_set.detail_stance_flg) # noqa
                if data_set.detail_stance_flg:
                    # スタンス追加補正がある場合、そのリストを表示
                    service_data_txt = "{service_data_txt}    {detail_stance_flg}\n".format(service_data_txt=service_data_txt,
                                            detail_stance_flg=", ".join(data_set.selected_stance_details)) # noqa
                    
                service_data_txt = "{service_data_txt}  捩り分散有無: {twist_flg}\n".format(service_data_txt=service_data_txt,
                                        twist_flg=data_set.twist_flg) # noqa

                morph_list = []
                for (org_morph_name, rep_morph_name, morph_ratio) in data_set.morph_list:
                    morph_list.append(f"{org_morph_name} → {rep_morph_name} ({morph_ratio})")
                morph_txt = ", ".join(morph_list)
                service_data_txt = "{service_data_txt}  モーフ置換: {morph_txt}\n".format(service_data_txt=service_data_txt,
                                        morph_txt=morph_txt) # noqa

                if data_set_idx in self.options.arm_options.avoidance_target_list:
                    service_data_txt = "{service_data_txt}  対象剛体名: {avoidance_target}\n".format(service_data_txt=service_data_txt,
                                            avoidance_target=", ".join(self.options.arm_options.avoidance_target_list[data_set_idx])) # noqa

            service_data_txt = "{service_data_txt}\n--------- \n".format(service_data_txt=service_data_txt) # noqa

            if self.options.arm_options.avoidance:
                service_data_txt = "{service_data_txt}剛体接触回避: {avoidance}\n".format(service_data_txt=service_data_txt,
                                        avoidance=self.options.arm_options.avoidance) # noqa

            if self.options.arm_options.alignment:
                service_data_txt = "{service_data_txt}手首位置合わせ: {alignment} ({distance})\n".format(service_data_txt=service_data_txt,
                                        alignment=self.options.arm_options.alignment, distance=self.options.arm_options.alignment_distance_wrist) # noqa
                service_data_txt = "{service_data_txt}指位置合わせ: {alignment} ({distance})\n".format(service_data_txt=service_data_txt,
                                        alignment=self.options.arm_options.alignment_finger_flg, distance=self.options.arm_options.alignment_distance_finger) # noqa
                service_data_txt = "{service_data_txt}床位置合わせ: {alignment} ({distance})\n".format(service_data_txt=service_data_txt,
                                        alignment=self.options.arm_options.alignment_floor_flg, distance=self.options.arm_options.alignment_distance_floor) # noqa
            
            if self.options.arm_options.arm_check_skip_flg:
                service_data_txt = "{service_data_txt}腕チェックスキップ: {arm_check_skip}\n".format(service_data_txt=service_data_txt,
                                        arm_check_skip=self.options.arm_options.arm_check_skip_flg) # noqa

            if self.options.camera_motion:
                service_data_txt = "{service_data_txt}カメラ: {camera}({camera_length})\n".format(service_data_txt=service_data_txt,
                                        camera=os.path.basename(self.options.camera_motion.path), camera_length=self.options.camera_length) # noqa
                service_data_txt = "{service_data_txt}  距離制限: {camera_length}{camera_length_umlimit}\n".format(service_data_txt=service_data_txt,
                                        camera_length=self.options.camera_length, camera_length_umlimit=("" if self.options.camera_length < 5 else "(無制限)")) # noqa

            service_data_txt = "{service_data_txt}------------------------".format(service_data_txt=service_data_txt) # noqa

            if self.options.total_process_ctrl:
                self.options.total_process_ctrl.write(str(self.options.total_process))
                self.options.now_process_ctrl.write("0")
                self.options.now_process_ctrl.write(str(self.options.now_process))

            logger.info(service_data_txt, decoration=MLogger.DECORATION_BOX)

            if self.options.is_sizing_camera_only is True:
                # カメラサイジングのみ実行する場合、出力結果VMDを読み込む
                for data_set_idx, data_set in enumerate(self.options.data_set_list):
                    reader = VmdReader(data_set.output_vmd_path)
                    data_set.motion = reader.read_data()
            else:
                for data_set_idx, data_set in enumerate(self.options.data_set_list):
                    # 足IKのXYZの比率
                    data_set.original_xz_ratio, data_set.original_y_ratio = MServiceUtils.calc_leg_ik_ratio(data_set)
                
                # 足IKの比率再計算
                self.options.calc_leg_ratio()

                # 移動補正
                if not MoveService(self.options).execute():
                    return False

                # スタンス補正
                if not StanceService(self.options).execute():
                    return False

                # 剛体接触回避
                if self.options.arm_options.avoidance:
                    if not ArmAvoidanceService(self.options).execute():
                        return False

                # 手首位置合わせ
                if self.options.arm_options.alignment:
                    if not ArmAlignmentService(self.options).execute():
                        return False

            # カメラ補正
            if self.options.camera_motion:
                if not CameraService(self.options).execute():
                    return False

            if self.options.is_sizing_camera_only is False:
                # モーフ置換
                if not MorphService(self.options).execute():
                    return False
                
                for data_set_idx, data_set in enumerate(self.options.data_set_list):
                    # 実行後、出力ファイル存在チェック
                    try:
                        # 出力
                        VmdWriter(data_set).write()

                        Path(data_set.output_vmd_path).resolve(True)

                        logger.info("【No.%s】 出力終了: %s", (data_set_idx + 1), os.path.basename(data_set.output_vmd_path), decoration=MLogger.DECORATION_BOX, title="サイジング成功")
                    except FileNotFoundError as fe:
                        logger.error("【No.%s】出力VMDファイルが正常に作成されなかったようです。\nパスを確認してください。%s\n\n%s", (data_set_idx + 1), data_set.output_vmd_path, fe, decoration=MLogger.DECORATION_BOX)
                
            if self.options.camera_motion:
                try:
                    camera_model = PmxModel()
                    camera_model.name = "カメラ・照明"
                    data_set = MOptionsDataSet(self.options.camera_motion, None, camera_model, self.options.camera_output_vmd_path, 0, 0, [], None, 0, [])
                    # 出力
                    VmdWriter(data_set).write()

                    Path(data_set.output_vmd_path).resolve(True)

                    logger.info("カメラ出力終了: %s", os.path.basename(data_set.output_vmd_path), decoration=MLogger.DECORATION_BOX, title="サイジング成功")
                except FileNotFoundError as fe:
                    logger.error("カメラ出力VMDファイルが正常に作成されなかったようです。\nパスを確認してください。%s\n\n%s", self.options.camera_output_vmd_path, fe, decoration=MLogger.DECORATION_BOX)

            if int(self.options.total_process) != int(self.options.now_process):
                logger.warning("一部処理がスキップされました。\n画面左下の進捗数をクリックすると、スキップされた処理がグレーで表示されています。", decoration=MLogger.DECORATION_BOX)

            return True
        except MKilledException:
            return False
        except SizingException as se:
            logger.error("サイジング処理が処理できないデータで終了しました。\n\n%s", se, decoration=MLogger.DECORATION_BOX)
            return False
        except Exception as e:
            logger.critical("サイジング処理が意図せぬエラーで終了しました。", e, decoration=MLogger.DECORATION_BOX)
            return False
        finally:
            logging.shutdown()
Esempio n. 3
0
    def parse(cls, version_name: str):
        parser = argparse.ArgumentParser()
        parser.add_argument("--motion_path",
                            required=True,
                            type=(lambda x: list(map(str, x.split(';')))))
        parser.add_argument("--org_model_path",
                            required=True,
                            type=(lambda x: list(map(str, x.split(';')))))
        parser.add_argument("--rep_model_path",
                            required=True,
                            type=(lambda x: list(map(str, x.split(';')))))
        parser.add_argument("--detail_stance_flg",
                            required=True,
                            type=(lambda x: list(map(int, x.split(';')))))
        parser.add_argument("--twist_flg",
                            required=True,
                            type=(lambda x: list(map(int, x.split(';')))))
        parser.add_argument("--arm_process_flg_avoidance", type=int, default=0)
        parser.add_argument("--avoidance_target_list",
                            default=[],
                            type=(lambda x: list(map(str, x.split(';')))))
        parser.add_argument("--arm_process_flg_alignment", type=int, default=0)
        parser.add_argument("--alignment_finger_flg", type=int, default=0)
        parser.add_argument("--alignment_floor_flg", type=int, default=0)
        parser.add_argument("--alignment_distance_wrist",
                            type=float,
                            default=1.7)
        parser.add_argument("--alignment_distance_finger",
                            type=float,
                            default=1.4)
        parser.add_argument("--alignment_distance_floor",
                            type=float,
                            default=1.8)
        parser.add_argument("--arm_check_skip_flg", type=int, default=0)
        parser.add_argument("--camera_motion_path", type=str, default="")
        parser.add_argument("--camera_org_model_path",
                            default=[],
                            type=(lambda x: list(map(str, x.split(';')))))
        parser.add_argument("--camera_offset_y",
                            default=[],
                            type=(lambda x: list(map(str, x.split(';')))))
        parser.add_argument("--verbose", type=int, default=20)

        args = parser.parse_args()

        # ログディレクトリ作成
        os.makedirs("log", exist_ok=True)

        MLogger.initialize(level=args.verbose, is_file=True)

        try:
            arm_process_flg_avoidance = True if args.arm_process_flg_avoidance == 1 else False
            arm_process_flg_alignment = True if args.arm_process_flg_alignment == 1 else False
            alignment_finger_flg = True if args.alignment_finger_flg == 1 else False
            alignment_floor_flg = True if args.alignment_floor_flg == 1 else False
            arm_check_skip_flg = True if args.arm_check_skip_flg == 1 else False

            arm_options = MArmProcessOptions(
                arm_process_flg_avoidance, \
                {0: [(a.strip() if len(a.strip()) > 0 else "") for a in args.avoidance_target_list]}, \
                arm_process_flg_alignment, \
                alignment_finger_flg, \
                alignment_floor_flg, \
                args.alignment_distance_wrist, \
                args.alignment_distance_finger, \
                args.alignment_distance_floor, \
                arm_check_skip_flg
            )

            # 元モデルが未指定の場合、空で処理する
            if not args.camera_org_model_path or (
                    len(args.camera_org_model_path) == 1
                    and len(args.camera_org_model_path[0]) == 0):
                args.camera_org_model_path = []
                for org_path in args.org_model_path:
                    args.camera_org_model_path.append("")

            # オフセットYが未指定の場合、0で処理する
            if not args.camera_offset_y or (len(args.camera_offset_y) == 1 and
                                            len(args.camera_offset_y[0]) == 0):
                args.camera_offset_y = []
                for org_path in args.org_model_path:
                    args.camera_offset_y.append(0)

            data_set_list = []
            for set_no, (motion_path, org_model_path, rep_model_path, detail_stance_flg_val, twist_flg_val, camera_org_model_path, camera_offset_y) in enumerate( \
                zip(args.motion_path, args.org_model_path, args.rep_model_path, args.detail_stance_flg, args.twist_flg, args.camera_org_model_path, \
                    args.camera_offset_y)): # noqa

                display_set_no = "【No.{0}】".format(set_no + 1)

                # モーションパス --------
                logger.info("%s 調整対象モーションVMD/VPDファイル 読み込み開始", display_set_no)

                file_name, input_ext = os.path.splitext(
                    os.path.basename(motion_path))
                if input_ext.lower() == ".vmd":
                    motion_reader = VmdReader(motion_path)
                elif input_ext.lower() == ".vpd":
                    motion_reader = VpdReader(motion_path)
                else:
                    raise SizingException(
                        "{0}.motion_path 読み込み失敗(拡張子不正): {1}".format(
                            display_set_no, os.path.basename(motion_path)))

                motion = motion_reader.read_data()

                logger.info("%s 調整対象モーションVMD/VPDファイル 読み込み成功 %s",
                            display_set_no, os.path.basename(motion_path))

                # 元モデル ----------
                logger.info("%s モーション作成元モデルPMXファイル 読み込み開始", display_set_no)

                file_name, input_ext = os.path.splitext(
                    os.path.basename(org_model_path))
                if input_ext.lower() == ".pmx":
                    org_model_reader = PmxReader(org_model_path)
                else:
                    raise SizingException(
                        "{0}.org_model_path 読み込み失敗(拡張子不正): {1}".format(
                            display_set_no, os.path.basename(org_model_path)))

                org_model = org_model_reader.read_data()

                logger.info("%s モーション作成元モデルPMXファイル 読み込み成功 %s", display_set_no,
                            os.path.basename(org_model_path))

                # 先モデル ----------
                logger.info("%s モーション変換先モデルPMXファイル 読み込み開始", display_set_no)

                file_name, input_ext = os.path.splitext(
                    os.path.basename(rep_model_path))
                if input_ext.lower() == ".pmx":
                    rep_model_reader = PmxReader(rep_model_path)
                else:
                    raise SizingException(
                        "{0}.rep_model_path 読み込み失敗(拡張子不正): {1}".format(
                            display_set_no, os.path.basename(rep_model_path)))

                rep_model = rep_model_reader.read_data()

                logger.info("%s モーション変換先モデルPMXファイル 読み込み成功 %s", display_set_no,
                            os.path.basename(rep_model_path))

                # 元モデル ----------
                if len(camera_org_model_path) > 0:
                    logger.info("%s カメラ作成元モデルPMXファイル 読み込み開始", display_set_no)

                    file_name, input_ext = os.path.splitext(
                        os.path.basename(camera_org_model_path))
                    if input_ext.lower() == ".pmx":
                        camera_org_model_reader = PmxReader(
                            camera_org_model_path)
                    else:
                        raise SizingException(
                            "{0}.camera_org_model_path 読み込み失敗(拡張子不正): {1}".
                            format(display_set_no,
                                   os.path.basename(camera_org_model_path)))

                    camera_org_model = camera_org_model_reader.read_data()

                    logger.info("%s カメラ作成元モデルPMXファイル 読み込み成功 %s",
                                display_set_no,
                                os.path.basename(camera_org_model_path))
                else:
                    # カメラ元モデルが未指定の場合、作成元モデルをそのまま流用
                    camera_org_model = org_model

                detail_stance_flg = True if detail_stance_flg_val == 1 else False
                twist_flg = True if twist_flg_val == 1 else False

                # 出力ファイルパス
                output_vmd_path = MFileUtils.get_output_vmd_path(
                    motion_path, rep_model_path, detail_stance_flg, twist_flg,
                    arm_process_flg_avoidance, arm_process_flg_alignment,
                    False, "", True)

                data_set = MOptionsDataSet(
                    motion, org_model, rep_model, output_vmd_path,
                    detail_stance_flg, twist_flg, [], camera_org_model,
                    camera_offset_y, [
                        "センターXZ補正", "上半身補正", "下半身補正", "足IK補正", "つま先IK補正",
                        "つま先補正", "肩補正", "センターY補正"
                    ])

                data_set_list.append(data_set)

            if len(args.camera_motion_path) != 0:
                # カメラパス --------
                logger.info("調整対象カメラVMDファイル 読み込み開始")

                file_name, input_ext = os.path.splitext(
                    os.path.basename(args.camera_motion_path))
                if input_ext.lower() == ".vmd":
                    camera_motion_reader = VmdReader(args.camera_motion_path)
                else:
                    raise SizingException(
                        "camera_motion_path 読み込み失敗(拡張子不正): %s",
                        os.path.basename(args.camera_motion_path))

                camera_motion = camera_motion_reader.read_data()
                camera_output_vmd_path = MFileUtils.get_output_camera_vmd_path(
                    args.camera_motion_path, data_set_list[0].rep_model.path,
                    "")

                logger.info("調整対象カメラVMD/VPDファイル 読み込み成功 %s",
                            os.path.basename(args.camera_motion_path))
            else:
                camera_motion = None
                camera_output_vmd_path = None

            options = MOptions(\
                version_name=version_name, \
                logging_level=args.verbose, \
                data_set_list=data_set_list, \
                arm_options=arm_options, \
                camera_motion=camera_motion, \
                camera_output_vmd_path=camera_output_vmd_path, \
                monitor=sys.stdout, \
                is_file=True, \
                outout_datetime=logger.outout_datetime, \
                max_workers=1)

            return options
        except SizingException as se:
            logger.error("サイジング処理が処理できないデータで終了しました。\n\n%s",
                         se.message,
                         decoration=MLogger.DECORATION_BOX)
        except Exception as e:
            logger.critical("サイジング処理が意図せぬエラーで終了しました。",
                            e,
                            decoration=MLogger.DECORATION_BOX)