2025-07-01
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
'''
|
||||
Copyright (C) 2023 CG Cookie
|
||||
|
||||
https://github.com/CGCookie/retopoflow
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
'''
|
||||
|
||||
import sys
|
||||
import copy
|
||||
import math
|
||||
import time
|
||||
import random
|
||||
|
||||
import bpy
|
||||
from bpy.types import Operator
|
||||
|
||||
from ..common.blender import perform_redraw_all, get_view3d_area
|
||||
from ..common.debug import debugger, tprint
|
||||
from ..common.profiler import profiler
|
||||
|
||||
|
||||
class CookieCutter_Modal:
|
||||
def modal(self, context, event):
|
||||
self.context = context
|
||||
self.event = event
|
||||
|
||||
if self._cc_stage == 'quit': return {'FINISHED'}
|
||||
|
||||
# if we're not yet in the main loop, create a NOP event so that we can
|
||||
# work our way through the initialization stuff as quickly as possible!
|
||||
if self._cc_stage != 'main loop': self._cc_fsm_force_event()
|
||||
else: self._cc_fsm_stop_force_event()
|
||||
|
||||
# get the method corresponding to the current stage
|
||||
fn_modal = {
|
||||
'prestart': self.modal_prestart,
|
||||
'start when ready': self.modal_start_when_ready,
|
||||
'init CC internals': self.modal_init_cc_internals,
|
||||
'init CC start': self.modal_init_cc_start,
|
||||
'init CC UI': self.modal_init_cc_ui,
|
||||
'main loop': self.modal_mainloop,
|
||||
}.get(self._cc_stage, None)
|
||||
assert fn_modal, f"Unhandled CC stage: '{self._cc_stage}'"
|
||||
|
||||
ret = fn_modal()
|
||||
# if ret == {'PASS_THROUGH'}:
|
||||
# print(f'passing through {random.random()}')
|
||||
return ret
|
||||
|
||||
def modal_prestart(self):
|
||||
with self.try_exception('prestarting'):
|
||||
self.prestart()
|
||||
self._cc_stage = 'start when ready'
|
||||
return {'RUNNING_MODAL'}
|
||||
self.cc_break()
|
||||
return {'CANCELLED'}
|
||||
|
||||
def modal_start_when_ready(self):
|
||||
with self.try_exception('waiting for start readiness'):
|
||||
if self.is_ready_to_start():
|
||||
self._cc_stage = 'init CC internals'
|
||||
return {'RUNNING_MODAL'}
|
||||
self.cc_break()
|
||||
return {'CANCELLED'}
|
||||
|
||||
def modal_init_cc_internals(self):
|
||||
with self.try_exception('initialize internals (Exception Callbacks, FSM, UI, Actions)'):
|
||||
self._nav = False
|
||||
self._nav_time = 0
|
||||
self._done = False
|
||||
self._start_time = time.time()
|
||||
self._tmp_time = self._start_time
|
||||
self._cc_exception_init()
|
||||
self._cc_fsm_init()
|
||||
self._cc_ui_init()
|
||||
self._cc_actions_init()
|
||||
self._cc_stage = 'init CC start'
|
||||
return {'RUNNING_MODAL'}
|
||||
self.cc_break()
|
||||
return {'CANCELLED'}
|
||||
|
||||
def modal_init_cc_start(self):
|
||||
with self.try_exception('initialize start'):
|
||||
self.start()
|
||||
self._cc_stage = 'init CC UI'
|
||||
return {'RUNNING_MODAL'}
|
||||
self.cc_break()
|
||||
return {'CANCELLED'}
|
||||
|
||||
def modal_init_cc_ui(self):
|
||||
with self.try_exception('initialize ui'):
|
||||
self._cc_ui_start()
|
||||
self._cc_stage = 'main loop'
|
||||
return {'RUNNING_MODAL'}
|
||||
self.cc_break()
|
||||
return {'CANCELLED'}
|
||||
|
||||
def modal_mainloop(self):
|
||||
self.drawcallbacks.reset_pre()
|
||||
|
||||
if time.time() - self._tmp_time >= 1:
|
||||
self._tmp_time = time.time()
|
||||
# print('--- %d ---' % int(self._tmp_time - self._start_time))
|
||||
profiler.printfile()
|
||||
|
||||
if self._done:
|
||||
self.modal_maindone()
|
||||
self._cc_ui_end()
|
||||
self._cc_actions_end()
|
||||
self._cc_exception_done()
|
||||
return {'FINISHED'} if self._done=='finish' else {'CANCELLED'}
|
||||
|
||||
ret = None
|
||||
|
||||
if self._nav:
|
||||
self._nav = False
|
||||
self._nav_time = time.time()
|
||||
self._cc_actions_update()
|
||||
|
||||
if self._cc_ui_update():
|
||||
# UI handled the action
|
||||
ret = {'RUNNING_MODAL'}
|
||||
elif self._cc_actions.using('blender window action'):
|
||||
# allow window actions to pass through to Blender
|
||||
ret = {'PASS_THROUGH'}
|
||||
elif self._cc_actions.is_navigating or (self._cc_actions.timer and self._nav):
|
||||
self._nav = True
|
||||
return {'PASS_THROUGH'}
|
||||
|
||||
with self.try_exception('call update'):
|
||||
self.update()
|
||||
if self.should_pass_through(self.context, self.event):
|
||||
ret = {'PASS_THROUGH'}
|
||||
|
||||
if not ret:
|
||||
self._cc_fsm_update()
|
||||
ret = {'RUNNING_MODAL'}
|
||||
|
||||
perform_redraw_all(only_area=get_view3d_area(self.context))
|
||||
return ret
|
||||
|
||||
def modal_maindone(self):
|
||||
if self._done == 'bail':
|
||||
return
|
||||
|
||||
try:
|
||||
fn_end = self.end_commit if self._done == 'commit' else self.end_cancel
|
||||
fn_end()
|
||||
self.end()
|
||||
self.stop_running()
|
||||
except Exception as e:
|
||||
self._handle_exception(e, 'call end() with %s' % self._done)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user