NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

panel.py (10229B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\dynamicresources\client\ess\bracket\panel.py
      2 import abc
      3 import datetime
      4 import eveui
      5 import gametime
      6 import signals
      7 import threadutils
      8 from carbonui import uiconst
      9 from carbonui.uicore import uicore
     10 from eveui import Rect
     11 from dynamicresources.client.ess.bracket.tracker import TransformTracker
     12 
     13 class BracketPanel(object):
     14     __metaclass__ = abc.ABCMeta
     15 
     16     def __init__(self, transform, layer, camera = None, clipping_dead_zone = 0, collapse_at_camera_distance = None, name = None, on_focus = None, collapsed = False):
     17         self._transform = transform
     18         self._layer = layer
     19         self._camera = camera
     20         self._clipping_dead_zone = clipping_dead_zone
     21         self._collapse_at_camera_distance = collapse_at_camera_distance
     22         self._is_forced_expanded = False
     23         self._is_collapsed = collapsed
     24         self.is_locked = False
     25         self._is_closed = False
     26         self._focused = False
     27         self._tracker = TransformTracker(name=name, parent=layer, transform=transform, curve_set=uicore.uilib.bracketCurveSet, tracker_parent=uicore.layer.inflight)
     28         self._state_requests = {}
     29         self._next_state_request_token_id = 1
     30         self.on_focus = signals.Signal()
     31         if on_focus:
     32             self.on_focus.connect(on_focus)
     33         self._clipped_state_token = None
     34         self._zoom_state_token = None
     35         self._interaction_state_token = None
     36         self._focus_state_token = None
     37         self._was_clipped = None
     38         self._start_frame_update_loop()
     39 
     40     @property
     41     def is_closed(self):
     42         return self._is_closed
     43 
     44     @property
     45     def tracker(self):
     46         return self._tracker
     47 
     48     @property
     49     def transform(self):
     50         return self._transform
     51 
     52     @property
     53     def layer(self):
     54         return self._layer
     55 
     56     @property
     57     def clipping_bounds(self):
     58         return get_absolute_bounds(self._layer)
     59 
     60     @property
     61     def is_collapsed(self):
     62         return self._is_collapsed
     63 
     64     @property
     65     def is_expanded(self):
     66         return not self._is_collapsed
     67 
     68     @property
     69     def can_expand(self):
     70         return self._is_collapsed and self._focus_state_token is None and not self._was_clipped
     71 
     72     @property
     73     def focused(self):
     74         return self._focused
     75 
     76     @focused.setter
     77     def focused(self, focused):
     78         if focused != self._focused:
     79             self._focused = focused
     80             self.on_focus(focused)
     81 
     82     def close(self):
     83         self._tracker.close()
     84         self._is_closed = True
     85 
     86     def focus(self):
     87         self.focused = True
     88 
     89     def unfocus(self):
     90         self.focused = False
     91 
     92     @threadutils.threaded
     93     def _start_frame_update_loop(self):
     94         collapse_at_cursor_distance = 150.0
     95         cursor_distance_grace_period = datetime.timedelta(seconds=1.0)
     96         cursor_last_within_distance_at = None
     97         while not self._is_closed:
     98             clipping_bounds = self.clipping_bounds
     99             content_bounds = self.content_bounds
    100             if self._is_forced_expanded:
    101                 cursor_distance = content_bounds.distance_from_point(*eveui.Mouse.position())
    102                 if cursor_distance < collapse_at_cursor_distance:
    103                     cursor_last_within_distance_at = gametime.now()
    104                 else:
    105                     if cursor_last_within_distance_at is None:
    106                         cursor_last_within_distance_at = gametime.now()
    107                     dt = gametime.now() - cursor_last_within_distance_at
    108                     if dt >= cursor_distance_grace_period:
    109                         self._is_forced_expanded = False
    110             if not self._is_forced_expanded and self._interaction_state_token is not None:
    111                 self._interaction_state_token.clear()
    112                 self._interaction_state_token = None
    113             if self._was_clipped is not None:
    114                 dead_zone_sign = 1 if self._was_clipped else -1
    115                 dead_zone_delta = dead_zone_sign * (self._clipping_dead_zone / 2.0)
    116                 content_bounds = content_bounds.inflate(dead_zone_delta)
    117             if content_bounds.is_empty:
    118                 is_enveloped = clipping_bounds.contains(*content_bounds.center)
    119             else:
    120                 is_enveloped = clipping_bounds.envelops(content_bounds)
    121             if is_enveloped and (self._was_clipped is None or self._was_clipped):
    122                 self._was_clipped = False
    123                 if self._clipped_state_token is not None:
    124                     self._clipped_state_token.clear()
    125                     self._clipped_state_token = None
    126             elif not is_enveloped and not self._was_clipped:
    127                 self._was_clipped = True
    128                 if self._clipped_state_token is None:
    129                     self._clipped_state_token = self.request_collapse(Priority.clipped)
    130             if self._collapse_at_camera_distance is not None and self._camera.is_valid:
    131                 camera_distance = self._camera.distance_from_transform(self._transform)
    132                 out_of_range = camera_distance > self._collapse_at_camera_distance
    133                 if out_of_range and self._zoom_state_token is None:
    134                     self._zoom_state_token = self.request_collapse(Priority.zoomed_out)
    135                 elif not out_of_range and self._zoom_state_token is not None:
    136                     self._zoom_state_token.clear()
    137                     self._zoom_state_token = None
    138             should_expand, should_lock = self._should_be_expanded()
    139             if self._is_collapsed and should_expand:
    140                 self.expand()
    141                 self.is_locked = False
    142                 self._is_collapsed = False
    143             elif not self._is_collapsed and not should_expand:
    144                 self.collapse(lock=should_lock)
    145                 self.is_locked |= should_lock
    146                 self._is_collapsed = True
    147             elif self._is_collapsed and not should_expand and not self.is_locked and should_lock:
    148                 self.collapse(lock=should_lock)
    149                 self._is_collapsed = True
    150                 self.is_locked = True
    151             elif self._is_collapsed and not should_expand and self.is_locked and not should_lock:
    152                 self.collapse(lock=should_lock)
    153                 self._is_collapsed = True
    154                 self.is_locked = False
    155             self._update_interaction_point_in_frame()
    156             eveui.wait_for_next_frame()
    157 
    158     def request_collapse(self, priority = 0, lock = False):
    159         return self._allocate_state_request(priority, expand=False, lock=lock)
    160 
    161     def request_expand(self, priority = 0):
    162         return self._allocate_state_request(priority, expand=True)
    163 
    164     def _allocate_state_request(self, priority, expand, lock = False):
    165         token_id = self._next_state_request_token_id
    166         self._next_state_request_token_id += 1
    167         self._state_requests[token_id] = StateRequest(priority, expand, lock)
    168         return StateRequestToken(token_id, on_clear=self._clear_state_request)
    169 
    170     def _clear_state_request(self, token_id):
    171         try:
    172             del self._state_requests[token_id]
    173         except KeyError:
    174             pass
    175 
    176     def _should_be_expanded(self):
    177         if not self._state_requests:
    178             return (True, False)
    179         highest_priority = 0
    180         expand = False
    181         lock = False
    182         for request in self._state_requests.values():
    183             lock |= request.lock
    184             if request.priority > highest_priority:
    185                 highest_priority = request.priority
    186                 expand = request.expand
    187             elif request.priority == highest_priority:
    188                 expand |= request.expand
    189 
    190         return (expand, lock)
    191 
    192     def force_expand(self):
    193         if not self._is_forced_expanded and self._is_collapsed:
    194             self._is_forced_expanded = True
    195             self._interaction_state_token = self.request_expand(Priority.player)
    196             uicore.uilib.RegisterForTriuiEvents([uiconst.UI_MOUSEDOWN], self._on_global_mouse_down)
    197 
    198     def force_collapse(self):
    199         if self._focus_state_token is None:
    200             self._focus_state_token = self.request_collapse(Priority.player)
    201 
    202     def clear_force_collapse(self):
    203         if self._focus_state_token is not None:
    204             self._focus_state_token.clear()
    205             self._focus_state_token = None
    206 
    207     def _update_interaction_point_in_frame(self):
    208         pass
    209 
    210     def _on_global_mouse_down(self, target, *args, **kwargs):
    211         if target is None:
    212             return True
    213         if not self._is_forced_expanded:
    214             return False
    215         click_captured = self.content_bounds.contains(*eveui.Mouse.position())
    216         if self._is_forced_expanded and not click_captured:
    217             self._is_forced_expanded = False
    218             return False
    219         return True
    220 
    221     @abc.abstractproperty
    222     def content_bounds(self):
    223         pass
    224 
    225     @abc.abstractmethod
    226     def expand(self):
    227         pass
    228 
    229     @abc.abstractmethod
    230     def collapse(self, lock = False):
    231         pass
    232 
    233 
    234 class Priority(object):
    235     control_point = 5
    236     player = 4
    237     no_content = 3
    238     zoomed_out = 2
    239     clipped = 1
    240 
    241 
    242 class StateRequest(object):
    243 
    244     def __init__(self, priority, expand, lock):
    245         self.priority = priority
    246         self.expand = expand
    247         self.lock = lock
    248 
    249     @property
    250     def collapse(self):
    251         return not self.expand
    252 
    253 
    254 class StateRequestToken(object):
    255 
    256     def __init__(self, token_id, on_clear):
    257         self._token_id = token_id
    258         self._cleared = False
    259         self.on_clear = signals.Signal()
    260         if on_clear:
    261             self.on_clear.connect(on_clear)
    262 
    263     def clear(self):
    264         if not self._cleared:
    265             self._cleared = True
    266             self.on_clear(self._token_id)
    267 
    268     def __del__(self):
    269         self.clear()
    270 
    271 
    272 def get_absolute_bounds(ui_object, allow_alignment = False):
    273     if ui_object.destroyed:
    274         return Rect.zero()
    275     if allow_alignment:
    276         left, top, width, height = ui_object.GetAbsolute()
    277     else:
    278         left, top = ui_object.GetCurrentAbsolutePosition()
    279         width, height = ui_object.GetCurrentAbsoluteSize()
    280     return Rect(left, top, width, height)
    281 
    282 
    283 from dynamicresources.client.ess.bracket.debug import __reload_update__