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

polygon.py (20077B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\drawingpolygon\polygon.py
      2 from drawingpolygon.components.fill import PolygonFill
      3 from drawingpolygon.components.perimeter import PolygonPerimeter, PolygonSegment
      4 from drawingpolygon.components.vertex import PolygonVertex
      5 import drawingpolygon.cursors as cursors
      6 from carbon.common.script.util.timerstuff import AutoTimer
      7 from carbonui import uiconst
      8 from carbonui.primitives.container import Container
      9 from gametime import GetTimeDiffInMs, GetWallclockTime
     10 from signals.signal import Signal
     11 import trinity
     12 DRAG_UPDATE_TIMER_MSEC = 50
     13 IS_RIGHT_CLICK_DELETE_ENABLED = False
     14 VERTEX_CLOSED_TEXTURE_PATH = 'res:/UI/Texture/classes/DrawingTool/vertex.png'
     15 VERTEX_OPEN_TEXTURE_PATH = 'res:/UI/Texture/classes/DrawingTool/vertex_open_ended.png'
     16 VERTEX_DRAGGING_TEXTURE_PATH = 'res:/UI/Texture/classes/DrawingTool/vertex_moving.png'
     17 
     18 def read(attributes, name, default):
     19     value = attributes.get(name, default)
     20     if value is not None:
     21         return value
     22     return default
     23 
     24 
     25 class Polygon(Container):
     26     default_state = uiconst.UI_PICKCHILDREN
     27     default_align = uiconst.TOALL
     28     default_idx = 0
     29     default_max_vertices = 10
     30     default_perimeter_width = 2
     31     default_perimeter_width_factor = 2
     32     default_show_vertices = True
     33     default_show_fill = True
     34     default_fill_bg_color_selected = (0.0, 0.0, 0.0, 0.6)
     35     default_fill_bg_color_hovered = (0.0, 0.0, 0.0, 0.6)
     36     default_fill_bg_color_deselected = (0.0, 0.0, 0.0, 0.0)
     37     default_fill_color_selected = (0.2, 1.0, 1.0, 0.7)
     38     default_fill_color_hovered = (0.2, 1.0, 1.0, 0.4)
     39     default_fill_color_deselected = (0.0, 0.0, 0.0, 0.0)
     40     default_perimeter_color = (0.2, 1.0, 1.0, 1.0)
     41     default_perimeter_color_outer = (0.0, 0.0, 0.0, 1.0)
     42     FILL_COLOR_SELECTED_INVALID = (0.97, 0.09, 0.13, 0.7)
     43     FILL_COLOR_HOVERED_INVALID = (0.97, 0.09, 0.13, 0.5)
     44     FILL_COLOR_DESELECTED_INVALID = (0.0, 0.0, 0.0, 0.0)
     45     PERIMETER_COLOR_INVALID = (0.97, 0.09, 0.13, 1.0)
     46     NO_COLOR = (0.0, 0.0, 0.0, 0.0)
     47 
     48     def ApplyAttributes(self, attributes):
     49         self.drawing_area = attributes.get('area')
     50         self.max_vertices = read(attributes, 'max_vertices', self.default_max_vertices)
     51         self.perimeter_width = read(attributes, 'perimeter_width', self.default_perimeter_width)
     52         self.perimeter_width_factor = read(attributes, 'perimeter_width_factor', self.default_perimeter_width_factor)
     53         self.show_vertices = read(attributes, 'show_vertices', self.default_show_vertices)
     54         self.show_fill = read(attributes, 'show_fill', self.default_show_fill)
     55         self.fill_bg_color_selected = read(attributes, 'fill_bg_color_selected', self.default_fill_bg_color_selected)
     56         self.fill_bg_color_hovered = read(attributes, 'fill_bg_color_hovered', self.default_fill_bg_color_hovered)
     57         self.fill_bg_color_deselected = read(attributes, 'fill_bg_color_deselected', self.default_fill_bg_color_deselected)
     58         self.fill_color_selected = read(attributes, 'fill_color_selected', self.default_fill_color_selected)
     59         self.fill_color_hovered = read(attributes, 'fill_color_hovered', self.default_fill_color_hovered)
     60         self.fill_color_deselected = read(attributes, 'fill_color_deselected', self.default_fill_color_deselected)
     61         self.perimeter_color = read(attributes, 'perimeter_color', self.default_perimeter_color)
     62         self.perimeter_color_outer = read(attributes, 'perimeter_color_outer', self.default_perimeter_color_outer)
     63         self.set_order(order=attributes.get('order'))
     64         self.vertices = []
     65         self.active_vertex = None
     66         self.is_complete = False
     67         self.is_selected = True
     68         self.is_valid = True
     69         self.is_moving = False
     70         self.is_vertex_moving = False
     71         self.is_hovered = False
     72         self.time_of_start = GetWallclockTime()
     73         self.time_of_last_edit = GetWallclockTime()
     74         self.vertex_drag_updates_thread = None
     75         self.drag_updates_thread = None
     76         self.drag_mouse_position = None
     77         self.original_vertex_mouse_position = None
     78         self.wip_segment = None
     79         self.on_edit_started = Signal(signalName='on_edit_started')
     80         self.on_deleted = Signal(signalName='on_deleted')
     81         self.on_completed = Signal(signalName='on_completed')
     82         self.on_wip_segment_added = Signal(signalName='on_wip_segment_added')
     83         self.on_wip_segment_removed = Signal(signalName='on_wip_segment_removed')
     84         super(Polygon, self).ApplyAttributes(attributes)
     85         self._draw_fill()
     86         self._draw_perimeter()
     87 
     88     def Close(self):
     89         self._set_active_vertex(None)
     90         self._remove_x_button()
     91         self.on_deleted(self.order)
     92         super(Polygon, self).Close()
     93 
     94     def get_data(self):
     95         return {'vertices': [ self.drawing_area.transform_coordinates_to_proportions(vertex.x, vertex.y) for vertex in self.vertices ]}
     96 
     97     def _get_top_right(self):
     98         x = max([ vertex.x for vertex in self.vertices ])
     99         y = min([ vertex.y for vertex in self.vertices ])
    100         return (x, y)
    101 
    102     def _get_right(self):
    103         x, y = (0, 0)
    104         for vertex in self.vertices:
    105             if vertex.x > x:
    106                 x = vertex.x
    107                 y = vertex.y
    108 
    109         return (x, y)
    110 
    111     def get_time_spent(self):
    112         return max(0, GetTimeDiffInMs(self.time_of_start, self.time_of_last_edit))
    113 
    114     def scale(self, x_scale, y_scale):
    115         self.Hide()
    116         self._remove_x_button()
    117         for vertex in self.vertices:
    118             vertex.update_position(vertex.x * x_scale, vertex.y * y_scale)
    119 
    120         self._redraw_polygon()
    121         self._add_x_button()
    122         self.Show()
    123 
    124     def set_order(self, order):
    125         self.order = order
    126         self.name = 'Polygon%d' % order
    127 
    128     def set_arrangement_order(self, idx):
    129         self.SetOrder(idx)
    130 
    131     def set_cursor(self, cursor):
    132         self.fill.set_cursor(cursor)
    133         self.perimeter.set_cursor(cursor)
    134 
    135     def reset_cursor(self):
    136         self.fill.reset_cursor()
    137         self.perimeter.reset_cursor()
    138 
    139     def set_perimeter_color(self, perimeter_color):
    140         self.perimeter_color = perimeter_color
    141         self.perimeter_inner.Flush()
    142         self.perimeter_inner.SetRGBA(*perimeter_color)
    143         for vertex in self.vertices:
    144             self.perimeter_inner.add_vertex(vertex.x, vertex.y)
    145 
    146         if self.is_complete:
    147             self.perimeter_inner.isLoop = True
    148 
    149     def select(self):
    150         self.is_selected = True
    151         self._redraw_polygon()
    152         if self.is_complete:
    153             self.set_cursor(cursors.CURSOR_SELECTOR_TARGET)
    154         self._add_x_button()
    155 
    156     def deselect(self):
    157         self.is_selected = False
    158         self._remove_x_button()
    159         self._redraw_polygon()
    160         self.reset_cursor()
    161 
    162     def on_hover(self):
    163         self.is_hovered = True
    164         self._redraw_polygon()
    165 
    166     def on_dehover(self):
    167         self.is_hovered = False
    168         self._redraw_polygon()
    169 
    170     def enable(self):
    171         for vertex in self.vertices:
    172             vertex.Enable()
    173 
    174         self.perimeter.Enable()
    175         self.fill.Enable()
    176 
    177     def disable(self):
    178         for vertex in self.vertices:
    179             vertex.Disable()
    180 
    181         self.perimeter.Disable()
    182         self.fill.Disable()
    183 
    184     def update_validation(self, is_valid):
    185         if self.is_valid == is_valid:
    186             return
    187         self.is_valid = is_valid or not self.is_complete
    188         self._redraw_polygon()
    189 
    190     def add_point(self, x, y):
    191         if self.is_complete:
    192             return
    193         self._add_segment(x, y)
    194         self._add_vertex(x, y)
    195         if self.max_vertices and len(self.vertices) >= self.max_vertices:
    196             self.autocomplete_polygon()
    197 
    198     def remove_point(self, index):
    199         self._remove_segment(index)
    200         self._remove_vertex(index)
    201 
    202     def get_point_amount(self):
    203         return len(self.vertices)
    204 
    205     def _draw_perimeter(self):
    206         self.perimeter = PolygonPerimeter(name='Perimeter', parent=self, polygon=self, color=self.perimeter_color_outer, lineWidth=self.perimeter_width * self.perimeter_width_factor)
    207         self.perimeter.on_left_clicked.connect(self.on_left_clicked)
    208         if IS_RIGHT_CLICK_DELETE_ENABLED:
    209             self.perimeter.on_right_clicked.connect(self.on_right_clicked)
    210         self.perimeter.on_drag_started.connect(self.on_drag_started)
    211         self.perimeter.on_drag_ended.connect(self.on_drag_ended)
    212         self.perimeter.on_hover_started.connect(self.on_hover)
    213         self.perimeter.on_hover_ended.connect(self.on_dehover)
    214         self.perimeter_inner = PolygonPerimeter(name='PerimeterInner', parent=self, polygon=self, color=self._get_perimeter_color(), lineWidth=self.perimeter_width, state=uiconst.UI_DISABLED)
    215 
    216     def _draw_fill(self):
    217         fill_color = self._get_fill_color()
    218         fill_bg_color = self._get_fill_bg_color()
    219         self.fill_bg = PolygonFill(name='FillBg', parent=self, polygon=self, color=fill_bg_color, state=uiconst.UI_DISABLED)
    220         self.fill = PolygonFill(name='Fill', parent=self, polygon=self, color=fill_color, blendMode=trinity.TR2_SBM_ADD)
    221         self.fill.on_left_clicked.connect(self.on_left_clicked)
    222         if IS_RIGHT_CLICK_DELETE_ENABLED:
    223             self.fill.on_right_clicked.connect(self.on_right_clicked)
    224         self.fill.on_drag_started.connect(self.on_drag_started)
    225         self.fill.on_drag_ended.connect(self.on_drag_ended)
    226         self.fill.on_hover_started.connect(self.on_hover)
    227         self.fill.on_hover_ended.connect(self.on_dehover)
    228 
    229     def _get_invalid_fill_color(self):
    230         if self.is_selected:
    231             return self.FILL_COLOR_SELECTED_INVALID
    232         if self.is_hovered:
    233             return self.FILL_COLOR_HOVERED_INVALID
    234         return self.FILL_COLOR_DESELECTED_INVALID
    235 
    236     def _get_fill_bg_color(self):
    237         if not self.show_fill or not self.is_valid:
    238             return self.NO_COLOR
    239         if self.is_selected:
    240             return self.fill_bg_color_selected
    241         if self.is_hovered:
    242             return self.fill_bg_color_hovered
    243         return self.fill_bg_color_deselected
    244 
    245     def _get_fill_color(self):
    246         if not self.show_fill:
    247             return self.NO_COLOR
    248         if not self.is_valid:
    249             return self._get_invalid_fill_color()
    250         if self.is_selected:
    251             return self.fill_color_selected
    252         if self.is_hovered:
    253             return self.fill_color_hovered
    254         return self.fill_color_deselected
    255 
    256     def _get_perimeter_color(self):
    257         if self.is_valid:
    258             return self.perimeter_color
    259         else:
    260             return self.PERIMETER_COLOR_INVALID
    261 
    262     def _redraw_polygon(self):
    263         self.perimeter.Flush()
    264         self.fill.Flush()
    265         self.fill_bg.Flush()
    266         self.perimeter_inner.Flush()
    267         fill_color = self._get_fill_color()
    268         self.fill.SetRGBA(*fill_color)
    269         fill_bg_color = self._get_fill_bg_color()
    270         self.fill_bg.SetRGBA(*fill_bg_color)
    271         perimeter_color = self._get_perimeter_color()
    272         self.perimeter_inner.SetRGBA(*perimeter_color)
    273         for vertex in self.vertices:
    274             self._add_segment(vertex.x, vertex.y)
    275 
    276         if self.is_complete:
    277             self._complete_polygon()
    278         elif self.vertices:
    279             self._set_active_vertex(self.vertices[-1])
    280 
    281     def _redraw_vertices(self):
    282         if not self.vertices:
    283             return
    284         if self.is_complete:
    285             for vertex in self.vertices:
    286                 vertex.set_base_texture(VERTEX_CLOSED_TEXTURE_PATH)
    287 
    288         else:
    289             for vertex in self.vertices[:-1]:
    290                 vertex.set_base_texture(VERTEX_CLOSED_TEXTURE_PATH)
    291 
    292             last_vertex = self.vertices[-1]
    293             last_vertex.set_base_texture(VERTEX_OPEN_TEXTURE_PATH)
    294 
    295     def _add_vertex(self, x, y):
    296         vertex_order = len(self.vertices)
    297         vertex = PolygonVertex(name='Vertex%d' % vertex_order, parent=self, get_mouse_position=self.drawing_area.get_mouse_position, polygon=self, order=vertex_order, x=x, y=y, texturePath=VERTEX_OPEN_TEXTURE_PATH, draggingTexturePath=VERTEX_DRAGGING_TEXTURE_PATH, opacity=1.0 if self.show_vertices else 0.0)
    298         vertex.on_left_clicked.connect(self.on_vertex_left_clicked)
    299         if IS_RIGHT_CLICK_DELETE_ENABLED:
    300             vertex.on_right_clicked.connect(self.on_vertex_right_clicked)
    301         vertex.on_drag_started.connect(self.on_vertex_drag_started)
    302         vertex.on_drag_ended.connect(self.on_vertex_drag_ended)
    303         self.vertices.append(vertex)
    304         self._set_active_vertex(vertex)
    305         self._redraw_vertices()
    306 
    307     def _remove_vertex(self, index):
    308         vertex_to_remove = self.vertices[index]
    309         was_active_vertex = self.active_vertex == vertex_to_remove
    310         vertex_to_remove.Close()
    311         del self.vertices[index]
    312         for order, vertex in enumerate(self.vertices):
    313             vertex.order = order
    314 
    315         if was_active_vertex:
    316             if len(self.vertices):
    317                 self._set_active_vertex(self.vertices[-1])
    318             else:
    319                 self._set_active_vertex(None)
    320         self._redraw_vertices()
    321 
    322     def _add_segment(self, x, y):
    323         self.perimeter.add_vertex(x, y)
    324         self.fill.add_vertex(x, y)
    325         self.fill_bg.add_vertex(x, y)
    326         self.perimeter_inner.add_vertex(x, y)
    327 
    328     def _remove_segment(self, index):
    329         self.perimeter.remove_vertex(index)
    330         self.fill.remove_vertex(index)
    331         self.fill_bg.remove_vertex(index)
    332         self.perimeter_inner.remove_vertex(index)
    333 
    334     def autocomplete_polygon(self):
    335         self._complete_polygon()
    336         self._set_active_vertex(None)
    337         self._remove_wip_segment()
    338         self.on_completed(self)
    339 
    340     def _complete_polygon(self):
    341         for vertex in self.vertices:
    342             vertex.set_base_cursor(cursors.CURSOR_RESIZER_COLLAPSED)
    343             vertex.set_dragging_cursor(cursors.CURSOR_RESIZER_EXPANDED)
    344             vertex.reset_cursor()
    345 
    346         self._redraw_vertices()
    347         self.perimeter.isLoop = True
    348         self.perimeter_inner.isLoop = True
    349         self.fill.complete()
    350         self.fill_bg.complete()
    351         self.is_complete = True
    352 
    353     def _set_active_vertex(self, vertex):
    354         if self.active_vertex == vertex:
    355             return
    356         self.active_vertex = vertex
    357         self._remove_wip_segment()
    358         if self.active_vertex:
    359             self._add_wip_segment()
    360 
    361     def _move(self, start_x, start_y, end_x, end_y):
    362         x_diff = end_x - start_x
    363         y_diff = end_y - start_y
    364         for vertex in self.vertices:
    365             vertex.update_position(x=vertex.x + x_diff, y=vertex.y + y_diff)
    366 
    367         self._redraw_polygon()
    368 
    369     def _delete(self):
    370         self._start_edit()
    371         self.Close()
    372 
    373     def _start_edit(self):
    374         self.on_edit_started(self)
    375         self._update_last_edit_time()
    376 
    377     def _update_last_edit_time(self):
    378         self.time_of_last_edit = GetWallclockTime()
    379 
    380     def on_left_clicked(self, *args):
    381         self._start_edit()
    382 
    383     def on_right_clicked(self, *args):
    384         self._delete()
    385 
    386     def on_drag_started(self, *args):
    387         self._start_edit()
    388         self._remove_wip_segment()
    389         self._start_drag_updates()
    390 
    391     def on_drag_ended(self, *args):
    392         self._end_drag_updates()
    393         self._add_wip_segment()
    394 
    395     def on_vertex_left_clicked(self, vertex):
    396         self._start_edit()
    397         if len(self.vertices) > 2 and vertex.order == 0:
    398             self.autocomplete_polygon()
    399 
    400     def on_vertex_right_clicked(self, vertex):
    401         self._start_edit()
    402         is_polygon_delete = len(self.vertices) <= 1
    403         self.remove_point(vertex.order)
    404         if is_polygon_delete:
    405             self.Close()
    406 
    407     def on_vertex_drag_started(self, vertex):
    408         self._start_edit()
    409         self._remove_wip_segment()
    410         self._start_vertex_drag_updates(vertex)
    411 
    412     def on_vertex_drag_ended(self, *args):
    413         self._end_vertex_drag_updates()
    414         self._add_wip_segment()
    415 
    416     def _start_drag_updates(self):
    417         self._end_drag_updates()
    418         self.is_moving = True
    419         self.drag_mouse_position = self.drawing_area.get_mouse_position()
    420         self.drag_updates_thread = AutoTimer(DRAG_UPDATE_TIMER_MSEC, self._update_while_dragging)
    421         self._remove_x_button()
    422 
    423     def _end_drag_updates(self):
    424         if self.drag_updates_thread:
    425             self.drag_updates_thread.KillTimer()
    426         self.is_moving = False
    427         self.drag_mouse_position = None
    428         self.drag_updates_thread = None
    429         self._update_last_edit_time()
    430         self._add_x_button()
    431 
    432     def _update_drag_mouse_position(self):
    433         start_x, start_y = self.drag_mouse_position
    434         end_x, end_y = self.drawing_area.get_mouse_position()
    435         x_diff = end_x - start_x
    436         y_diff = end_y - start_y
    437         for vertex in self.vertices:
    438             vertex_end_x = vertex.x + x_diff
    439             vertex_end_y = vertex.y + y_diff
    440             if not self.drawing_area.is_position_in_area(vertex_end_x, vertex_end_y):
    441                 return False
    442 
    443         self.drag_mouse_position = (end_x, end_y)
    444         return True
    445 
    446     def _update_while_dragging(self):
    447         start_x, start_y = self.drag_mouse_position
    448         if not self._update_drag_mouse_position():
    449             return
    450         end_x, end_y = self.drag_mouse_position
    451         self._move(start_x, start_y, end_x, end_y)
    452 
    453     def _start_vertex_drag_updates(self, vertex):
    454         self._end_vertex_drag_updates()
    455         self.is_vertex_moving = True
    456         self.original_vertex_mouse_position = self.drawing_area.get_mouse_position()
    457         self.vertex_drag_updates_thread = AutoTimer(DRAG_UPDATE_TIMER_MSEC, self._update_vertex_while_dragging, vertex)
    458         self._remove_x_button()
    459 
    460     def _end_vertex_drag_updates(self):
    461         if self.vertex_drag_updates_thread:
    462             self.vertex_drag_updates_thread.KillTimer()
    463         self.is_vertex_moving = False
    464         self.original_vertex_mouse_position = None
    465         self.vertex_drag_updates_thread = None
    466         self._update_last_edit_time()
    467         self._add_x_button()
    468 
    469     def _update_vertex_while_dragging(self, vertex):
    470         x, y = self.drawing_area.get_mouse_position()
    471         vertex.update_position(x, y)
    472         should_abort_move = self.drawing_area.is_there_another_vertex_in_range(self, vertex)
    473         if should_abort_move:
    474             x, y = self.original_vertex_mouse_position
    475             vertex.update_position(x, y)
    476         self.perimeter.update_vertex(vertex.order, x, y)
    477         self.fill.update_vertex(vertex.order, x, y)
    478         self.fill_bg.update_vertex(vertex.order, x, y)
    479         self.perimeter_inner.update_vertex(vertex.order, x, y)
    480         if should_abort_move:
    481             self._end_vertex_drag_updates()
    482 
    483     def move_cursor(self):
    484         self._update_wip_segment()
    485 
    486     def _update_wip_segment(self):
    487         if self.wip_segment:
    488             x, y = self.drawing_area.get_mouse_position()
    489             self.wip_segment.update_vertex(1, x, y)
    490 
    491     def _add_wip_segment(self):
    492         if self.is_complete:
    493             return
    494         self._remove_wip_segment()
    495         self.wip_segment = PolygonSegment(name='wip_segment', parent=self.drawing_area, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, color=self.perimeter_color, lineWidth=self.perimeter_width)
    496         self.wip_segment.on_removed.connect(self.on_wip_segment_removed)
    497         self.on_wip_segment_added()
    498         last_vertex = self.vertices[-1]
    499         self.wip_segment.add_vertex(last_vertex.x, last_vertex.y)
    500         x, y = self.drawing_area.get_mouse_position()
    501         self.wip_segment.add_vertex(x, y)
    502 
    503     def _remove_wip_segment(self):
    504         if self.wip_segment:
    505             self.wip_segment.Close()
    506             self.wip_segment = None
    507 
    508     def _add_x_button(self):
    509         if not self.drawing_area.IsClickable() or not self.is_selected or not self.is_complete or self.is_moving or self.is_vertex_moving:
    510             return
    511         x, y = self._get_top_right()
    512         self.drawing_area.add_x_button(self._delete, x, y)
    513 
    514     def _remove_x_button(self):
    515         self.drawing_area.remove_x_button()