Esempio n. 1
0
class ACLIBCollapsable(ACLabel):
    TEXTURES = {
        'plus': path(TEXTURE_DIR, 'plus.png'),
        'minus': path(TEXTURE_DIR, 'minus.png')
    }

    def __init__(self, parent: ACWidget, target: ACWidget):
        super().__init__(parent)

        self._collapsed = False

        self._grid = ACGrid(3, 2, self)
        self._button = ACButton(self._grid)
        self._content = ACLabel(self._grid)

        self._button.background_color = WHITE
        self._button.background_texture = ACLIBCollapsable.TEXTURES['plus']

        self._grid.add(self._button, 0, 0)
        self._grid.add(self._content, 0, 1)

        self.content = target

    @property
    def content(self):
        return self._content.child

    @content.setter
    def content(self, content: ACWidget):
        self._content.child = content

    @property
    def collapsed(self) -> bool:
        return self._collapsed

    @collapsed.setter
    def collapsed(self, collapsed: bool):
        self._collapsed = collapsed

        if collapsed:
            self._button.background_texture = ACLIBCollapsable.TEXTURES[
                'minus']
            self._content.visible = False
        else:
            self._button.background_texture = ACLIBCollapsable.TEXTURES['plus']
            self._content.visible = True
Esempio n. 2
0
class Tyres(ACApp):
    def __init__(self, data: ACData = None, meta: ACMeta = None):
        super().__init__('ACLIB Tyres', 200, 200, 98, 160, True, True)

        self.hide_decoration()
        self.background = False
        self.border = False

        self._data = data
        self._meta = meta

        self._grid = ACGrid(5, 9, self)

        # For each tyre there is a separate class to avoid redundancy of index checking.
        self.fl = Tyre(Tyre.FL, self._grid, self._data, self._meta)
        self.fr = Tyre(Tyre.FR, self._grid, self._data, self._meta)
        self.rl = Tyre(Tyre.RL, self._grid, self._data, self._meta)
        self.rr = Tyre(Tyre.RR, self._grid, self._data, self._meta)

        self._grid.add(self.fl, 0, 0, 2, 4)
        self._grid.add(self.fr, 3, 0, 2, 4)
        self._grid.add(self.rl, 0, 5, 2, 4)
        self._grid.add(self.rr, 3, 5, 2, 4)
Esempio n. 3
0
class Fuel(ACApp):
    def __init__(self, data: ACData = None, meta: ACMeta = None):
        super().__init__('ACLIB Fuel', 200, 200, 300, 100, True, True)
        self.hide_decoration()

        self._data = data
        self._meta = meta

        # Init

        self._normal_font = Font('Roboto Mono')
        self._normal_font.bold = 1
        self._normal_font.color = WHITE

        self._main_grid = ACGrid(5, 4, self)

        self._grid = ACGrid(3, 3, self._main_grid)

        self._avg_km = ACLabel(self._grid, 'Ø 00.0  l/km', 'center',
                               self._normal_font)
        self._avg_lap = ACLabel(self._grid, 'Ø 00.0   l/L', 'center',
                                self._normal_font)
        self._avg_min = ACLabel(self._grid, 'Ø 00.0 l/min', 'center',
                                self._normal_font)

        self._fuel = ACLabel(self._grid, '+ 00.0   l', 'center',
                             self._normal_font)
        self._km = ACLabel(self._grid, '+ 00.0  km', 'center',
                           self._normal_font)
        self._lap = ACLabel(self._grid, '+ 00.0   L', 'center',
                            self._normal_font)
        self._min = ACLabel(self._grid, '+ 00.0 min', 'center',
                            self._normal_font)

        # Style

        self.background_color = Color(0, 0, 0, 0.5)

        #self._fuel.background_color = Color(0.75, 0.75, 0, 0.75)

        self._main_grid.add(self._fuel, 3, 0, 2, 1)
        self._main_grid.add(self._avg_km, 1, 1, 2, 1)
        self._main_grid.add(self._km, 3, 1, 2, 1)
        self._main_grid.add(self._avg_lap, 1, 2, 2, 1)
        self._main_grid.add(self._lap, 3, 2, 2, 1)
        self._main_grid.add(self._avg_min, 1, 3, 2, 1)
        self._main_grid.add(self._min, 3, 3, 2, 1)

        # Data

        self._monitor = False
        self._timer = 0
        self._track_len = 0

        self._km_fuel_ref = 0
        self._lap_fuel_ref = 0
        self._min_fuel_ref = 0

        self._km_fuel_avg = 0
        self._lap_fuel_avg = 0
        self._min_fuel_avg = 0

        self._data.on(ACData.EVENT.READY, self._on_ready)

    def _timer(self):
        pass

    def _reset(self):
        self._km_fuel_ref = self.fuel
        self._lap_fuel_ref = self.fuel
        self._min_fuel_ref = self.fuel

    def _on_ready(self):
        self._reset()
        self._track_len = self._data.environment.track_length / 1000

        self._avg_km.text = 'Ø 00.0  l/km'
        self._avg_lap.text = 'Ø 00.0   l/L'
        self._avg_min.text = 'Ø 00.0 l/min'

        self._fuel.text = '{:2.1f} l'.format(self.fuel)
        self._km.text = '+ 00.0  km'
        self._lap.text = '+ 00.0   L'
        self._min.text = '+ 00.0 min'

        self._data.on(ACData.EVENT.SESSION_CHANGED, self.on_session)
        self._data.on(ACData.EVENT.SESSION_STATUS_CHANGED,
                      self.on_session_status)
        self._data.on(ACData.EVENT.PIT_ENTERED, self.on_pit_entered)
        self._data.on(ACData.EVENT.PIT_LEFT, self.on_pit_left)
        self._data.on(ACData.EVENT.KM_CHANGED, self.on_km)
        self._data.on(ACData.EVENT.LAP_CHANGED, self.on_lap)
        self._data.on(ACData.EVENT.FUEL_CHANGED, self.on_fuel)

    def on_session(self, session: int):
        self._monitor = False

    def on_session_status(self, status: int):
        self._monitor = False

    def on_pit_entered(self):
        self._monitor = False

    def on_pit_left(self):
        self._reset()
        self._monitor = True

    def on_fuel(self, fuel: float):
        self._fuel.text = '{} l'.format(self.fuel)

    def on_km(self, km: int):
        if not self._monitor:
            return

        self._km_fuel_avg = self.avg(self._km_fuel_avg, self._km_fuel_ref)
        self._km_fuel_ref = self.fuel

        enough_for = self.enough_for(self._km_fuel_avg)

        self._avg_km.text = 'Ø {:2.1f}  l/km'.format(self._km_fuel_avg)
        self._km.text = '+ {:2.1f}  km'.format(
            self.enough_for(self._km_fuel_avg))

        #if self._data.session.session == Type.RACE:
        if enough_for < self.race_dist_left(True):
            self._km.background_color = Color(1, 0, 0, 1)
        else:
            self._km.background_color = Color(0, 0, 0, 0)

    def on_lap(self, lap: int):
        if not self._monitor:
            self._monitor = True
            return

        self._lap_fuel_avg = self.avg(self._lap_fuel_avg, self._lap_fuel_ref)
        self._lap_fuel_ref = self.fuel

        enough_for = self.enough_for(self._lap_fuel_avg)

        self._avg_lap.text = 'Ø {:2.1f}   l/L'.format(self._lap_fuel_avg)
        self._lap.text = '+ {:2.1f}   L'.format(enough_for)

        #if self._data.session.session == Type.RACE:
        if enough_for < self.race_dist_left():
            self._lap.background_color = Color(1, 0, 0, 1)
        else:
            self._lap.background_color = Color(0, 0, 0, 0)

    def on_min(self, km: int):
        if not self._monitor:
            return

        self._min_fuel_avg = self.avg(self._min_fuel_avg, self._min_fuel_ref)
        self._min_fuel_ref = self.fuel

        enough_for = self.enough_for(self._min_fuel_avg)

        self._avg_min.text = 'Ø {:2.1f} l/min'.format(self._min_fuel_avg)
        self._min.text = '+ {:2.1f} min'.format(enough_for)

        # if self._data.session.session == Type.RACE:
        if enough_for < self.race_dist_left():
            self._min.background_color = Color(1, 0, 0, 1)
        else:
            self._min.background_color = Color(0, 0, 0, 0)

    @property
    def fuel(self):
        return round(self._data.car.fuel, 1)

    def race_dist(self, km: bool = False):
        if self._data.session.is_timed_race:
            return self._data.session.time_left
        else:
            if km:
                return self._data.session.laps * self._track_len
            else:
                return self._data.session.laps

    def race_dist_left(self, km: bool = False):
        if self._data.session.is_timed_race:
            return self._data.session.time_left
        else:
            if km:
                return (self._data.session.laps -
                        self._data.timing.lap) * self._track_len
            else:
                return self._data.session.laps - self._data.timing.lap

    def enough_for(self, avg: float):
        if avg == 0:
            return 0
        return round(self._data.car.fuel / avg, 1)

    def avg(self, last: float, ref: float):
        if last == 0:
            return ref - self.fuel
        return round((last + (ref - self.fuel)) / 2, 1)
Esempio n. 4
0
class Comparator(ACApp):
    TEXTURES = {
        'left': path(TEXTURE_DIR, 'arrow-left-slim.png'),
        'right': path(TEXTURE_DIR, 'arrow-right-slim.png')
    }

    MODE = ['Lap Time', 'Sector Time']

    def __init__(self, data: ACData = None, meta: ACMeta = None):
        super().__init__('ACLIB Comparator', 200, 200, 300, 55, True)

        self.hide_decoration()
        self.background_color = Color(0.1, 0.1, 0.1, 0.5)

        self._data = data
        self._meta = meta

        self._mode = 0
        self._opponents = []

        self._grid = ACGrid(12, 11, self)
        self._header = CR_Header(self._grid, 'Lap Time')
        self._left = CR_Icon(self._grid, Comparator.TEXTURES['left'])
        self._right = CR_Icon(self._grid, Comparator.TEXTURES['right'])
        self._add = CR_Button(self._grid, 'Add Opponent')
        self._remove = CR_Button(self._grid, 'Remove Opponent')

        self._grid.add(self._left, 0, 0, 1, 6)
        self._grid.add(self._header, 1, 0, 10, 6)
        self._grid.add(self._right, 11, 0, 1, 6)
        self._grid.add(self._add, 0, 6, 6, 5)
        self._grid.add(self._remove, 6, 6, 6, 5)

        self._left.on(ACWidget.EVENT.ON_MOUSE_DOWN, self._on_left)
        self._right.on(ACWidget.EVENT.ON_MOUSE_DOWN, self._on_right)
        #self._add.on(ACWidget.EVENT.ON_MOUSE_DOWN, self._on_add)
        #self._remove.on(ACWidget.EVENT.ON_MOUSE_DOWN, self._on_remove)

        self._add_opponent(0)
        self._add_opponent(1)

    def _add_opponent(self, i):
        w, h = self.size

        opponent = ComparatorRow(self._grid, self._data, self._meta)
        opponent.position = 0, h + i * 50
        opponent.size = w, 50
        self._opponents.append(opponent)

        # self._grid.add_rows(2)
        # w, h = self.size
        # self.size = w, h + 40
        # self._grid.add(opponent, 0, 4 + len(self._opponents) * 2, 12, 2)

    def _on_mode_changed(self):
        for opponent in self._opponents:
            opponent.change_mode(self._mode)

    def _on_left(self, *args):
        if self._mode > 0:
            self._mode -= 1
        else:
            self._mode = len(Comparator.MODE) - 1
        self._header.text = Comparator.MODE[self._mode]

        self._on_mode_changed()

    def _on_right(self, *args):
        if self._mode < len(Comparator.MODE) - 1:
            self._mode += 1
        else:
            self._mode = 0
        self._header.text = Comparator.MODE[self._mode]

        self._on_mode_changed()

    def _on_add(self, *args):
        self._grid.add_rows(2)
        w, h = self.size
        self.size = w, h + 40

    def _on_remove(self, *args):
        if len(self._opponents) > 0:
            self._grid.remove_rows(2)
            w, h = self.size
            self.size = w, h - 40

    def update(self, delta: float):
        super().update(delta)

        for o in self._opponents:
            o.update(delta)
Esempio n. 5
0
class Camera(ACApp):
    def __init__(self, data: ACData = None, meta: ACMeta = None):
        super().__init__('ACLIB_Camera', 200, 200, 150, 250)

        self.hide_decoration()
        self.background_color = TRANSPARENT

        self._data = data

        self._grid = ACGrid(2, 11, self)
        self._prev = ACLabel(self._grid, '<-', 'center')
        self._next = ACLabel(self._grid, '->', 'center')

        self._prev.background_color = DARKGRAY
        self._next.background_color = DARKGRAY

        self._grid.add(self._prev, 0, 0)
        self._grid.add(self._next, 1, 0)

        self._prev.on(ACWidget.EVENT.ON_MOUSE_DOWN, self.prev)
        self._next.on(ACWidget.EVENT.ON_MOUSE_DOWN, self.next)

        self._cameras = ['Cockpit', 'Car', 'Drivable', 'Track', 'Helicopter', 'OnBoardFree', 'Free', 'Random', 'ImageGeneratorCamera', 'Start']

        self._labels = []
        self._cam_id = 0

        self._active_font = Font('Roboto Mono')
        self._active_font.size = 12
        self._active_font.color = WHITE

        self._inactive_font = Font('Roboto Mono')
        self._inactive_font.size = 12
        self._inactive_font.color = WHITE

        i = 0
        for cam_id, name in enumerate(self._cameras):
            label = ACLabel(self._grid, name, 'center', self._inactive_font)
            label.background_color = BLACK
            label.on(ACWidget.EVENT.ON_MOUSE_DOWN, self.select)
            setattr(label, 'cam', cam_id)
            self._labels.append(label)

            self._grid.add(label, 0, i + 1, 2, 1)
            i += 1
            console(label.size)

        self._data.on(ACData.EVENT.READY, self.init)

    def init(self):
        self._cam_id = ac.getCameraMode()
        self._labels[self._cam_id].font = self._active_font
        self._labels[self._cam_id].background_color = RED

    def by_id(self, cam_id):
        if 0 <= cam_id <= 9:
            self._labels[self._cam_id].font = self._inactive_font
            self._labels[self._cam_id].background_color = BLACK

            ac.setCameraMode(cam_id)
            self._cam_id = cam_id

            self._labels[self._cam_id].font = self._active_font
            self._labels[self._cam_id].background_color = RED

    def select(self, widget: ACWidget, *args):
        self.by_id(widget.cam)

    def next(self, widget: ACWidget, *args):
        if self._cam_id == 9:
            self.by_id(0)
        else:
            self.by_id(self._cam_id + 1)

    def prev(self, widget: ACWidget, *args):
        if self._cam_id == 0:
            self.by_id(9)
        else:
            self.by_id(self._cam_id - 1)
Esempio n. 6
0
class UIDebug(ACApp):
    def __init__(self, data: ACData = None, meta: ACMeta = None):
        super().__init__('ACLIB UIDebug', 200, 200, 550, 80)

        self.hide_decoration()
        self.background_color = BLACK

        self._data = data
        self._active_widgets = []
        self._timer = time()

        self._font = Font('Roboto Mono', WHITE)

        self._grid = ACGrid(4, 4, self)

        self._widget_label = ACLabel(self._grid, 'Widget:', font=self._font)
        self._widget_text = ACLabel(self._grid, '', font=self._font)

        self._position_label = ACLabel(self._grid,
                                       'Position:',
                                       font=self._font)
        self._position_text = ACLabel(self._grid, '', font=self._font)

        self._size_label = ACLabel(self._grid, 'Size:', font=self._font)
        self._size_text = ACLabel(self._grid, '', font=self._font)

        self._property_name = ACLIBListBox(self._grid, 4)
        self._property_value = ACLIBListBox(self._grid, 4)

        col, row = 0, 0
        self._grid.add(self._widget_label, col, row)
        self._grid.add(self._position_label, col, row + 1)
        self._grid.add(self._size_label, col, row + 2)

        col, row = 1, 0
        self._grid.add(self._widget_text, col, row)
        self._grid.add(self._position_text, col, row + 1)
        self._grid.add(self._size_text, col, row + 2)

        col, row = 2, 0
        self._grid.add(self._property_name, col, row, 1, 4)

        col, row = 3, 0
        self._grid.add(self._property_value, col, row, 1, 4)

        self._data.on(ACData.EVENT.READY, self.init)
        self.on(ACWidget.EVENT.DISMISSED, self.dismissed)

    def _reset_active(self):
        for widget, border_color, no_render in self._active_widgets:
            widget.border_color = border_color
            widget.no_render = no_render
        self._active_widgets = []
        self._property_name.clear()
        self._property_value.clear()

    def init(self):
        for _, widget in ACWidget.IDS.items():
            widget.on(ACWidget.EVENT.ON_MOUSE_DOWN, self.get_info)

    def get_info(self, widget: ACWidget, *args):
        if self.active:
            # Children of the widget should also be highlighted.
            # It is expected that the next click takes at least 10ms
            # (otherwise it would be a pretty sick reaction time for the clicker).
            if time() - self._timer > 0.01:
                self._reset_active()

            self._timer = time()

            # Store the state of the widget.
            self._active_widgets.append(
                (widget, widget.border_color, widget.no_render))

            # Highlight newly selected widgets.
            set_render(widget, False)
            widget.border_color = RED

            # Set Properties
            self._widget_text.text = widget.__class__.__name__
            self._position_text.text = str(widget.position)
            self._size_text.text = str(widget.size)

            # self._property_name.add(ACLabel(self._property_name, 'Name'))
            # self._property_value.add(ACLabel(self._property_value, widget.__class__.__name__))

    def dismissed(self, *args):
        self._reset_active()
Esempio n. 7
0
class Tyre(ACLabel):
    COLORS = {}
    FL = 0
    FR = 1
    RL = 2
    RR = 3

    def __init__(self, index: int, parent: ACWidget, data: ACData,
                 meta: ACMeta):
        super().__init__(parent)

        self.background_color = TRANSPARENT

        self._data = data
        self._meta = meta

        self._index = index
        self._wear_min, self._wear_max = 96, 100

        self._grid = ACGrid(9, 12, self)

        # Each tyre has inner, outer, center, core and brake temperature.
        # Each of these locations is rendered separately by a colored texture.
        self._left = TyreTile(TyreTile.LEFT, self._grid, self._index,
                              self._data, self._meta)
        self._right = TyreTile(TyreTile.RIGHT, self._grid, self._index,
                               self._data, self._meta)
        self._center_top = TyreTile(TyreTile.CENTER, self._grid, self._index,
                                    self._data, self._meta)
        self._center_bot = TyreTile(TyreTile.CENTER, self._grid, self._index,
                                    self._data, self._meta)
        self._core = TyreTile(TyreTile.CORE, self._grid, self._index,
                              self._data, self._meta)
        self._brake = TyreTile(TyreTile.BRAKE, self._grid, self._index,
                               self._data, self._meta)
        self._wear = ACLIBProgressBar(self._grid, self._wear_max,
                                      self._wear_min, self._wear_max)

        # Left tyre
        if self._index % 2 == 0:
            self._grid.add(self._left, 0, 0, 2, 10)
            self._grid.add(self._center_top, 3, 0, 2, 3)
            self._grid.add(self._core, 3, 4, 2, 2)
            self._grid.add(self._center_bot, 3, 7, 2, 3)
            self._grid.add(self._right, 6, 0, 2, 10)
            self._grid.add(self._brake, 8, 2, 1, 6)
        # Right tyre
        else:
            self._grid.add(self._left, 1, 0, 2, 10)
            self._grid.add(self._center_top, 4, 0, 2, 3)
            self._grid.add(self._core, 4, 4, 2, 2)
            self._grid.add(self._center_bot, 4, 7, 2, 3)
            self._grid.add(self._right, 7, 0, 2, 10)
            self._grid.add(self._brake, 0, 2, 1, 6)

        self._grid.add(self._wear, 0, 11, 9, 1)

        self._data.on(ACData.EVENT.TYRE_WEAR_CHANGED, self._calculate_wear)

    # Private
    def _wear_value(self):
        return self._data.tyres.wear[self._index]

    def _wear_color(self, val: float):
        val = round(val, 1)

        if val in Tyre.COLORS:
            return Tyre.COLORS[val]

        color = interpolate(val, self._wear_min, self._wear_max, RED, GREEN)

        Tyre.COLORS[val] = color
        return color

    def _calculate_wear(self, *args):
        self._wear.value = self._wear_value()
        self._wear.progress_color = self._wear_color(self._wear_value())
Esempio n. 8
0
class ACLIBDockableWidget(ACApp):
    """
    Widget that allows DockWidgets to attach them to it.
    """
    DOCK_WIDGETS = []

    def __init__(self, name: str, x: int, y: int, w: int, h: int):
        super().__init__(name, x, y, w, h)

        self._dragged = False
        self._dockable_color = Color(0.0, 0.25, 1.0, 0.75)

        self._grid = ACGrid(3, 3, self)

        self._top = ACLabel(self._grid)
        self._left = ACLabel(self._grid)
        self._bottom = ACLabel(self._grid)
        self._right = ACLabel(self._grid)

        self._grid.add(self._top, 0, 0, 3, 1)
        self._grid.add(self._left, 0, 0, 1, 3)
        self._grid.add(self._bottom, 0, 2, 3, 1)
        self._grid.add(self._right, 2, 0, 1, 3)

        ACLIBDockableWidget.DOCK_WIDGETS.append(self)

        self.on(ACWidget.EVENT.ON_MOUSE_DOWN, self._on_mouse_down)
        self.on(ACWidget.EVENT.ON_MOUSE_UP, self._on_mouse_up)

    def _on_mouse_down(self, *args):
        self._dragged = True

    def _on_mouse_up(self, *args):
        self._dragged = False

    def highlight(self, other, dist: tuple):
        x1, y1 = other.position
        x2, y2 = self.position

        self.reset_highlight()

        if dist[0] > dist[1]:
            if x1 <= x2:
                self._left.background_color = self._dockable_color
            elif x1 > x2:
                self._right.background_color = self._dockable_color
        elif dist[0] < dist[1]:
            if y1 <= y2:
                self._top.background_color = self._dockable_color
            elif y1 > y2:
                self._bottom.background_color = self._dockable_color
        else:
            if x1 <= x2:
                self._left.background_color = self._dockable_color
            elif x1 > x2:
                self._right.background_color = self._dockable_color

            if y1 <= y2:
                self._top.background_color = self._dockable_color
            elif y1 > y2:
                self._bottom.background_color = self._dockable_color

    def reset_highlight(self):
        self._top.background_color = TRANSPARENT
        self._left.background_color = TRANSPARENT
        self._bottom.background_color = TRANSPARENT
        self._right.background_color = TRANSPARENT