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

radial_bar_graph.py (8566B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\dynamicresources\client\ui\radial_bar_graph.py
      2 from __future__ import division
      3 import math
      4 import chroma
      5 import eveui
      6 import threadutils
      7 from carbonui import uiconst
      8 from carbonui.primitives.container import Container
      9 from carbonui.primitives.polygon import Polygon
     10 
     11 class RadialBarGraph(Container):
     12 
     13     def __init__(self, parent, align, data, radius = 120, inner_radius = 100, start_angle = 0.0, end_angle = 360.0, progress = 1.0, color = (1.0, 1.0, 1.0, 1.0), background_color = (1.0, 1.0, 1.0, 0.3), bar_gap_ratio = 2.5, value_radius_modifier = 1.0):
     14         self._data = data
     15         self._radius = eveui.scale_dpi(radius)
     16         self._inner_radius = eveui.scale_dpi(inner_radius)
     17         self._start_angle = start_angle
     18         self._end_angle = end_angle
     19         self._progress = progress
     20         self._color = chroma.Color.from_any(color).rgba
     21         self._background_color = chroma.Color.from_any(background_color).rgba
     22         self._bar_gap_ratio = bar_gap_ratio
     23         self._value_radius_modifier = value_radius_modifier
     24         super(RadialBarGraph, self).__init__(parent=parent, align=align, height=self._radius * 2, width=self._radius * 2)
     25         self._polygon = Polygon(parent=self, align=uiconst.CENTER)
     26         self._need_redraw = True
     27         self._start_frame_update_loop()
     28 
     29     @property
     30     def data(self):
     31         return self._data
     32 
     33     @data.setter
     34     def data(self, data):
     35         self._data = data
     36         self._need_redraw = True
     37 
     38     @property
     39     def inner_radius(self):
     40         return self._inner_radius
     41 
     42     @inner_radius.setter
     43     def inner_radius(self, radius):
     44         if self._inner_radius != radius:
     45             self._inner_radius = radius
     46             self._need_redraw = True
     47 
     48     @property
     49     def radius(self):
     50         return self._radius
     51 
     52     @radius.setter
     53     def radius(self, radius):
     54         if self.radius != radius:
     55             self._radius = radius
     56             self._need_redraw = True
     57             size = math.ceil(self._radius * 2.0)
     58             if size % 2 == 1:
     59                 size += 1
     60             self.width = size
     61             self.height = size
     62 
     63     @property
     64     def start_angle(self):
     65         return self._start_angle
     66 
     67     @start_angle.setter
     68     def start_angle(self, angle):
     69         if self._start_angle != angle:
     70             self._start_angle = angle
     71             self._need_redraw = True
     72 
     73     @property
     74     def end_angle(self):
     75         return self._end_angle
     76 
     77     @end_angle.setter
     78     def end_angle(self, angle):
     79         if self._end_angle != angle:
     80             self._end_angle = angle
     81             self._need_redraw = True
     82 
     83     @property
     84     def progress(self):
     85         return self._progress
     86 
     87     @progress.setter
     88     def progress(self, progress):
     89         if self._progress != progress:
     90             old_progress = self._progress
     91             self._progress = progress
     92             bar_count = len(self._data)
     93             if int(bar_count * old_progress) != int(bar_count * self._progress):
     94                 self._need_redraw = True
     95 
     96     @property
     97     def color(self):
     98         return self._color
     99 
    100     @color.setter
    101     def color(self, color):
    102         new_color = chroma.Color.from_any(color).rgba
    103         if new_color != self._color:
    104             self._color = new_color
    105             self._need_redraw = True
    106 
    107     @property
    108     def background_color(self):
    109         return self._background_color
    110 
    111     @background_color.setter
    112     def background_color(self, color):
    113         new_color = chroma.Color.from_any(color).rgba
    114         if new_color != self._background_color:
    115             self._background_color = new_color
    116             self._need_redraw = True
    117 
    118     @property
    119     def bar_gap_ratio(self):
    120         return self._bar_gap_ratio
    121 
    122     @bar_gap_ratio.setter
    123     def bar_gap_ratio(self, bar_gap_ratio):
    124         if self._bar_gap_ratio != bar_gap_ratio:
    125             self._bar_gap_ratio = bar_gap_ratio
    126             self._need_redraw = True
    127 
    128     @property
    129     def value_radius_modifier(self):
    130         return self._value_radius_modifier
    131 
    132     @value_radius_modifier.setter
    133     def value_radius_modifier(self, modifier):
    134         if self._value_radius_modifier != modifier:
    135             self._value_radius_modifier = modifier
    136             self._need_redraw = True
    137 
    138     def _draw(self):
    139         value_max = max(self.data)
    140         normalized_data = [ v / value_max for v in self.data ]
    141         bar_height_max = self._radius - self._inner_radius
    142         bar_count = len(normalized_data)
    143         bar_step_angle = abs(self._end_angle - self._start_angle) / bar_count
    144         gap_sweep = bar_step_angle / (self._bar_gap_ratio + 1.0)
    145         start_angle = self._start_angle - 90.0
    146         segment_count = max(1, 60 // len(normalized_data))
    147         color = self.color
    148         first_background_bar = round(self.progress * bar_count)
    149         all_vertices = []
    150         all_colors = []
    151         all_triangles = []
    152         for i, value in enumerate(normalized_data):
    153             if i == first_background_bar:
    154                 color = self.background_color
    155             vertices, colors, triangles = _create_arc_polygon(inner_radius=self._inner_radius, outer_radius=self._radius - (1.0 - value) * self._value_radius_modifier * bar_height_max, segments=segment_count, color=color, start_angle=start_angle + bar_step_angle * i, end_angle=start_angle + bar_step_angle * (i + 1) - gap_sweep)
    156             vertex_offset = len(all_vertices)
    157             all_vertices.extend(vertices)
    158             all_colors.extend(colors)
    159             all_triangles.extend(((a + vertex_offset, b + vertex_offset, c + vertex_offset) for a, b, c in triangles))
    160 
    161         self._polygon.AppendVertices(positions=all_vertices, colors=all_colors, transform=None)
    162         self._polygon.SetTriangles(all_triangles)
    163 
    164     def _redraw(self):
    165         self._polygon.Flush()
    166         self._draw()
    167 
    168     @threadutils.threaded
    169     def _start_frame_update_loop(self):
    170         while not self.destroyed:
    171             if self._need_redraw:
    172                 self._redraw()
    173                 self._need_redraw = False
    174             eveui.wait_for_next_frame()
    175 
    176 
    177 def _create_arc_polygon(inner_radius, outer_radius, start_angle, end_angle, color = (1.0, 1.0, 1.0, 1.0), segments = 10, feather = 1.0):
    178     vertices = []
    179     colors = []
    180     triangles = []
    181     total_sweep = abs(end_angle - start_angle)
    182     segment_sweep = total_sweep / segments
    183     for i in xrange(segments + 1):
    184         a = math.radians(start_angle + i * segment_sweep)
    185         x = math.cos(a)
    186         y = math.sin(a)
    187         vertices.append((x * inner_radius, y * inner_radius))
    188         vertices.append((x * outer_radius, y * outer_radius))
    189         colors.extend((color, color))
    190 
    191     for i in xrange(segments * 2):
    192         triangles.append((i, i + 1, i + 2))
    193 
    194     shift = len(vertices)
    195     fade_color = (color[0],
    196      color[1],
    197      color[2],
    198      0.0)
    199     inner_circumference = 2.0 * math.pi * inner_radius
    200     inner_px_per_deg = inner_circumference * (total_sweep / 360.0) / total_sweep
    201     inner_feather_angle = feather / inner_px_per_deg
    202     outer_circumference = 2.0 * math.pi * outer_radius
    203     outer_px_per_deg = outer_circumference * (total_sweep / 360.0) / total_sweep
    204     outer_feather_angle = feather / outer_px_per_deg
    205     radius_inner_feather = inner_radius - feather
    206     radius_outer_feather = outer_radius + feather
    207     for i in xrange(segments + 1):
    208         if i == 0:
    209             inner_angle = math.radians(start_angle - inner_feather_angle)
    210             outer_angle = math.radians(start_angle - outer_feather_angle)
    211         elif i == segments:
    212             inner_angle = math.radians(start_angle + i * segment_sweep + inner_feather_angle)
    213             outer_angle = math.radians(start_angle + i * segment_sweep + outer_feather_angle)
    214         else:
    215             inner_angle = outer_angle = math.radians(start_angle + i * segment_sweep)
    216         vertices.extend([(math.cos(inner_angle) * radius_inner_feather, math.sin(inner_angle) * radius_inner_feather), (math.cos(outer_angle) * radius_outer_feather, math.sin(outer_angle) * radius_outer_feather)])
    217         colors.extend((fade_color, fade_color))
    218 
    219     for i in xrange(segments * 2):
    220         triangles.append((i, shift + i, shift + i + 2))
    221         triangles.append((shift + i + 2, i + 2, i))
    222 
    223     vertex_count = len(vertices)
    224     triangles.append((0, 1, shift))
    225     triangles.append((shift, shift + 1, 1))
    226     triangles.append((shift - 2, shift - 1, vertex_count - 2))
    227     triangles.append((vertex_count - 2, vertex_count - 1, shift - 1))
    228     return (vertices, colors, triangles)