Example #1
0
class Query:
    def __init__(self, scale, font, color, text_size, suggestions_text_size,
                 query_delay):
        self.scale = scale
        self.font = font
        self.color = color
        self.text_size = text_size
        self.suggestions_text_size = suggestions_text_size
        self.query_delay = query_delay
        self.background = None
        self.prefix = None
        self.query = None
        self.suggestions = None
        self.owner = None
        self.current_selection = None
        self.current_list = []
        self.completion_task = None
        self.max_columns = 4
        self.max_lines = 3
        self.max_elems = self.max_columns * self.max_lines

    def do_query(self, text):
        body = None
        if self.current_selection is not None:
            if self.current_selection < len(self.current_list):
                body = self.current_list[self.current_selection][1]
        else:
            text = self.query.get()
            body = self.owner.get_object(text)
        self.owner.select_object(body)
        self.close()

    def close(self):
        self.background.destroy()
        self.background = None
        self.prefix.destroy()
        self.prefix = None
        self.query.destroy()
        self.query = None
        self.suggestions.destroy()
        self.suggestions = None
        self.current_selection = None
        self.current_list = []
        if self.completion_task is not None:
            taskMgr.remove(self.completion_task)
            self.completion_task = None

    def escape(self, event):
        self.close()

    def update_suggestions(self):
        if self.current_selection is not None:
            page = self.current_selection // self.max_elems
        else:
            page = 0
        start = page * self.max_elems
        end = min(start + self.max_elems - 1, len(self.current_list) - 1)
        suggestions = ""
        for i in range(start, end + 1):
            if i != start and ((i - start) % self.max_columns) == 0:
                suggestions += '\n'
            if i == self.current_selection:
                suggestions += "\1md_bold\1%s\2" % self.current_list[i][0]
            else:
                suggestions += self.current_list[i][0]
            suggestions += '\t'
        self.suggestions.setText(suggestions)

    def completion(self, event):
        text = self.query.get()
        if text != '':
            self.current_list = self.owner.list_objects(text)
        else:
            self.current_list = []
        self.current_selection = None
        if self.completion_task is not None:
            taskMgr.remove(self.completion_task)
        self.completion_task = taskMgr.doMethodLater(self.query_delay,
                                                     self.update_suggestions,
                                                     'completion task',
                                                     extraArgs=[])

    def select(self, event):
        modifiers = event.getModifierButtons()
        if modifiers.isDown(KeyboardButton.shift()):
            incr = -1
        else:
            incr = 1
        if self.current_selection is not None:
            new_selection = self.current_selection + incr
        else:
            new_selection = 0
        if new_selection < 0:
            new_selection = len(self.current_list) - 1
        if new_selection >= len(self.current_list):
            new_selection = 0
        self.current_selection = new_selection
        self.update_suggestions()

    def open_query(self, owner):
        self.owner = owner
        bg_color = LColor(*self.color)
        bg_color[3] = 0.2
        scale3 = LVector3(self.scale[0], 1.0, self.scale[1])
        self.background = DirectFrame(
            frameColor=bg_color,
            frameSize=(-1 / self.scale[0], 1.0 / self.scale[0],
                       0.15 + self.scale[1] * self.text_size, 0.0),
            parent=base.a2dBottomLeft)
        self.prefix = OnscreenText(
            text=_("Target name:"),
            font=self.font,
            fg=self.color,
            align=TextNode.ALeft,
            parent=base.a2dBottomLeft,
            scale=tuple(self.scale * self.text_size),
            pos=(0, .15),
        )
        bounds = self.prefix.getTightBounds()
        length = bounds[1][0] - bounds[0][
            0] + self.scale[0] * self.text_size / 2
        self.query = DirectEntry(text="",
                                 text_fg=self.color,
                                 scale=tuple(scale3 * self.text_size),
                                 command=self.do_query,
                                 parent=base.a2dBottomLeft,
                                 frameColor=(0, 0, 0, 0),
                                 pos=(length, 0, .15),
                                 initialText="",
                                 numLines=1,
                                 width=200,
                                 entryFont=self.font,
                                 focus=1,
                                 suppressKeys=1)
        self.query.bind("press-escape-", self.escape)
        self.query.bind("press-tab-", self.select)
        self.query.accept(self.query.guiItem.getTypeEvent(), self.completion)
        self.query.accept(self.query.guiItem.getEraseEvent(), self.completion)
        pos = self.prefix.getPos()
        bounds = self.query.getBounds()
        llz = bounds[2] / self.text_size
        self.suggestions = OnscreenText(
            text="",
            font=self.font,
            fg=self.color,
            align=TextNode.ALeft,
            mayChange=True,
            parent=base.a2dBottomLeft,
            scale=tuple(self.scale * self.suggestions_text_size),
            pos=(pos[0], pos[1] + llz),
        )
Example #2
0
    def __init__(self, services: Services,
                 mouse1_press_callbacks: List[Callable[[], None]]):
        self.__services = services
        self.__services.ev_manager.register_listener(self)
        self.__base = self.__services.graphics.window
        self.__text = " t - find the path between the agent and goal\n\n" \
                      " mouse click - moves agent to mouse location \n\n mouse right click - moves goal to" \
                      " mouse location\n\n arrow keys, PgUp, PgDn - move agent / goal (Alt down)\n\n x - toggle trace" \
                      " animation (animations required)\n\n m - toggle map between Sparse and Dense\n\n o - take a " \
                      "default screenshot of the map\n\n p - take a custom screenshot of the scene\n\n w, a, s, d " \
                      "- orbit around the map\n\n q - top view of the map\n\n c, v - toggle Simulator Configuration /" \
                      " View Editor\n\n i - toggle Debug Overlay"

        self.__algorithms = self.__services.settings.algorithms
        self.__maps = self.__services.settings.maps

        self.__map_keys = list(self.__maps.keys())
        self.__algorithm_keys = list(self.__algorithms.keys())
        self.__animation_keys = list(self.__animations.keys())

        self.__window = Window(self.__base,
                               "simulator_config",
                               mouse1_press_callbacks,
                               borderWidth=(0.0, 0.0),
                               frameColor=WINDOW_BG_COLOUR,
                               pos=(-1, 0.5, 0.5),
                               frameSize=(-1.7, 1.3, -5.68, 0.85))
        # spacer #
        DirectFrame(parent=self.__window.frame,
                    borderWidth=(.0, .0),
                    frameColor=WIDGET_BG_COLOUR,
                    frameSize=(-1.4, 1.4, -0.011, 0.011),
                    pos=(-0.2, 0.0, 0.4))

        DirectFrame(parent=self.__window.frame,
                    borderWidth=(.0, .0),
                    frameColor=WIDGET_BG_COLOUR,
                    frameSize=(-1.4, 1.4, -0.01, 0.01),
                    pos=(-0.2, 0.0, -2.96))

        self.sim_config = DirectLabel(parent=self.__window.frame,
                                      text="Simulator Configuration",
                                      text_fg=WHITE,
                                      text_bg=WINDOW_BG_COLOUR,
                                      frameColor=WINDOW_BG_COLOUR,
                                      borderWidth=(.0, .0),
                                      pos=(-0.53, 0.0, 0.56),
                                      scale=(0.2, 3, 0.2))
        # Zoom buttons
        self.btn_zoom_out = DirectButton(text="-",
                                         text_fg=WHITE,
                                         pressEffect=1,
                                         command=self.__window.zoom_out,
                                         pos=(0.71, 0., 0.55),
                                         parent=self.__window.frame,
                                         scale=(0.3, 4.15, 0.35),
                                         frameColor=TRANSPARENT)

        self.btn_zoom_in = DirectButton(text="+",
                                        text_fg=WHITE,
                                        pressEffect=1,
                                        command=self.__window.zoom_in,
                                        pos=(0.92, 0., 0.56),
                                        parent=self.__window.frame,
                                        scale=(0.3, 4.15, 0.35),
                                        frameColor=TRANSPARENT)

        # Quit button
        self.btn = DirectButton(text='x',
                                text_fg=WHITE,
                                command=self.__window.toggle_visible,
                                pos=(1.12, 0., 0.576),
                                parent=self.__window.frame,
                                scale=(0.3, 2.9, 0.2),
                                pressEffect=1,
                                frameColor=TRANSPARENT)

        self.user_information = DirectLabel(parent=self.__window.frame,
                                            text=self.__text,
                                            text_fg=WHITE,
                                            text_bg=WINDOW_BG_COLOUR,
                                            frameColor=WINDOW_BG_COLOUR,
                                            text_align=TextNode.ALeft,
                                            borderWidth=(.0, .0),
                                            pos=(-1.55, 0.0, -3.2),
                                            scale=(0.11, 1.1, 0.11))

        self.map_label = DirectLabel(parent=self.__window.frame,
                                     text="Map:",
                                     text_fg=WHITE,
                                     text_bg=WINDOW_BG_COLOUR,
                                     text_align=TextNode.ALeft,
                                     frameColor=WINDOW_BG_COLOUR,
                                     borderWidth=(.0, .0),
                                     pos=(-1.52, 0.4, 0.),
                                     scale=(0.17, 1.09, 0.13))

        self.algo_label = DirectLabel(parent=self.__window.frame,
                                      text="Algorithm:",
                                      text_fg=WHITE,
                                      text_bg=WINDOW_BG_COLOUR,
                                      frameColor=WINDOW_BG_COLOUR,
                                      text_align=TextNode.ALeft,
                                      borderWidth=(.0, .0),
                                      pos=(-1.52, 0.4, -0.5),
                                      scale=(0.17, 1.09, 0.13))

        self.animation_label = DirectLabel(parent=self.__window.frame,
                                           text="Animation:",
                                           text_fg=WHITE,
                                           text_bg=WINDOW_BG_COLOUR,
                                           frameColor=WINDOW_BG_COLOUR,
                                           text_align=TextNode.ALeft,
                                           borderWidth=(.0, .0),
                                           pos=(-1.52, 0.4, -1),
                                           scale=(0.17, 1.09, 0.13))

        self.agent_label = DirectLabel(parent=self.__window.frame,
                                       text="Agent:",
                                       text_fg=WHITE,
                                       text_bg=WINDOW_BG_COLOUR,
                                       frameColor=WINDOW_BG_COLOUR,
                                       text_align=TextNode.ALeft,
                                       borderWidth=(.0, .0),
                                       pos=(-1.52, 0.4, -1.5),
                                       scale=(0.17, 1.09, 0.13))

        self.goal_label = DirectLabel(parent=self.__window.frame,
                                      text="Goal:",
                                      text_fg=WHITE,
                                      text_bg=WINDOW_BG_COLOUR,
                                      frameColor=WINDOW_BG_COLOUR,
                                      text_align=TextNode.ALeft,
                                      borderWidth=(.0, .0),
                                      pos=(-1.52, 0.4, -2),
                                      scale=(0.17, 1.09, 0.13))

        # Creating goal and agent's entry fields
        self.__entries = []
        self.__entry_hovered = False
        mouse1_press_callbacks.append(self.__entry_mouse_click_callback)
        for i in range(0, 6):
            e = DirectEntry(parent=self.__window.frame,
                            scale=0.12,
                            pos=(-0.24 + (i % 3) * 0.57, 0.4,
                                 -1.5 - 0.5 * (i // 3)),
                            numLines=1,
                            width=3,
                            suppressKeys=True,
                            text_align=TextNode.ACenter,
                            focusInCommand=self.clear_text,
                            focusInExtraArgs=[i])
            self.__entries.append(e)
            e.bind(DGG.EXIT, self.__entry_exit_callback)
            e.bind(DGG.ENTER, self.__entry_enter_callback)
            e.bind(DGG.B1PRESS, self.__entry_mouse_click_callback)
            self.accept("mouse1", self.__entry_mouse_click_callback)

        self.__agent_disable_overlay = DirectButton(parent=self.__window.frame,
                                                    frameColor=TRANSPARENT,
                                                    borderWidth=(0.0, 0.0),
                                                    frameSize=(-0.6, 1.4, -0.2,
                                                               0.2),
                                                    pos=(-0.24, 0.4, -1.5),
                                                    suppressMouse=True)
        self.__agent_disable_overlay.hide()

        self.__maps_option = DirectOptionMenu(
            text="options",
            scale=0.14,
            parent=self.__window.frame,
            initialitem=self.__map_keys.index("Labyrinth")
            if "Labyrinth" in self.__map_keys else 0,
            items=self.__map_keys,
            pos=(-0.65, 0.4, 0.),
            highlightColor=(0.65, 0.65, 0.65, 1),
            textMayChange=1,
            command=self.__use_default_map_positions)

        self.__algorithms_option = DirectOptionMenu(
            text="options",
            scale=0.14,
            parent=self.__window.frame,
            initialitem=self.__algorithm_keys.index("A*")
            if "A*" in self.__algorithm_keys else 0,
            items=self.__algorithm_keys,
            pos=(-0.46, 0.4, -0.5),
            highlightColor=(0.65, 0.65, 0.65, 1),
            textMayChange=1)

        self.__animations_option = DirectOptionMenu(
            text="options",
            scale=0.14,
            parent=self.__window.frame,
            initialitem=self.__animation_keys.index("Fast"),
            items=self.__animation_keys,
            pos=(-0.45, 0.4, -1),
            highlightColor=(0.65, 0.65, 0.65, 1),
            textMayChange=1)

        self._update_frame = DirectFrame(parent=self.__window.frame,
                                         frameColor=WHITE,
                                         pos=(-1, 0.4, -2.6),
                                         borderWidth=(0.25, 0.15),
                                         frameSize=(-0.5, 0.95, -0.54, 0.54),
                                         scale=(0.50, 3.1, 0.25))

        self._reset_frame = DirectFrame(parent=self.__window.frame,
                                        frameColor=WHITE,
                                        pos=(0.412, 0.4, -2.6),
                                        borderWidth=(0.25, 0.15),
                                        frameSize=(-0.5, 0.92, -0.54, 0.54),
                                        scale=(0.50, 3.1, 0.25))

        self.btn_update = DirectButton(
            text="Update",
            text_fg=(0.3, 0.3, 0.3, 1.0),
            pressEffect=1,
            command=self.__update_simulator_callback,
            pos=(-0.9, 0.4, -2.65),
            parent=self.__window.frame,
            scale=(0.20, 2.1, 0.15),
            frameColor=TRANSPARENT)

        self.btn_reset = DirectButton(text="Reset",
                                      text_fg=(0.4, 0.3, 0.3, 1.0),
                                      pressEffect=1,
                                      command=self.__reset_simulator_callback,
                                      pos=(0.51, 0.4, -2.65),
                                      parent=self.__window.frame,
                                      scale=(0.20, 2.1, 0.15),
                                      frameColor=TRANSPARENT)

        # setup state & use saved state if possible
        self.__state = None
        for so in self.__services.state.objects:
            if isinstance(so, SimulatorConfigState):
                self.__state = so
                cmd = self.__maps_option['command']
                try:
                    self.__maps_option.set(self.__map_keys.index(so.mp))
                    self.__algorithms_option.set(
                        self.__algorithm_keys.index(so.algo))
                    self.__animations_option.set(
                        self.__animation_keys.index(so.ani))
                    self.__update_position_entries()
                except:
                    msg = "Failed to load Simulator Config state:\n{}".format(
                        traceback.format_exc())
                    self.__services.debug.write(msg, DebugLevel.NONE)
                    break
                finally:
                    self.__maps_option['command'] = cmd
                return
        new_state = self.__state is None
        if new_state:
            self.__state = SimulatorConfigState(self.__services.state)
        self.__state.mp = self.__maps_option.get()
        self.__state.algo = self.__algorithms_option.get()
        self.__state.ani = self.__animations_option.get()
        self.__use_default_map_positions()
        if new_state:
            self.__services.state.add(self.__state)
        else:
            self.__services.state.save()
class PlacerToolSpinner(DirectFrame):
    def __init__(self,
                 parent=render2d,
                 pos=(0.0, 0.0, 0.0),
                 scale=1.0,
                 value=0,
                 callback=None,
                 increment=0.01):
        DirectFrame.__init__(self, parent, pos=pos, scale=1.0)
        self.increment = increment
        self.value = Decimal(value)
        self.callback = callback

        self.display = DirectEntry(parent=self,
                                   relief=None,
                                   initialText="%.2f" % value,
                                   scale=1,
                                   text_scale=0.055,
                                   text_align=TextNode.ACenter,
                                   pos=(0.0, 0.0, 0.0),
                                   frameColor=(0.8, 0.8, 0.5, 1),
                                   borderWidth=(0.1, 0.1),
                                   numLines=1,
                                   width=6,
                                   frameSize=(-0.1, 0.1, -0.1, 0.1),
                                   cursorKeys=1)
        self.display.bind(DGG.TYPE, self.typeCallback)
        # This allows the text box to handle mouse events
        self.display.guiItem.setActive(True)

        gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui.bam')
        image = (gui.find('**/tt_t_gui_mat_shuffleArrowUp'),
                 gui.find('**/tt_t_gui_mat_shuffleArrowDown'),
                 gui.find('**/tt_t_gui_mat_shuffleArrowUp'),
                 gui.find('**/tt_t_gui_mat_shuffleArrowDisabled'))
        self.upArrow = DirectButton(self,
                                    relief=None,
                                    image=image,
                                    image_scale=(0.6, 0.6, 0.6),
                                    image1_scale=(0.7, 0.7, 0.7),
                                    image2_scale=(0.7, 0.7, 0.7),
                                    pos=(0.0, 0.0, 0.08),
                                    command=self.__handleUpClicked)
        self.upArrow.setR(90)
        self.downArrow = DirectButton(self,
                                      relief=None,
                                      image=image,
                                      image_scale=(0.6, 0.6, 0.6),
                                      image1_scale=(0.7, 0.7, 0.7),
                                      image2_scale=(0.7, 0.7, 0.7),
                                      pos=(0.0, 0.0, -0.05),
                                      command=self.__handleDownClicked)
        self.downArrow.setR(-90)

    def typeCallback(self, e):
        if self.display is None:
            return
        value = self.display.get()
        value = re.sub("[^0-9\.-]", "", value)
        if value == '':
            value = '000.00'
        elif value == '-':
            return
        if '.' not in value:
            try:
                value = int(value)
            except:
                return
        else:
            try:
                value = '%.2f' % float(value)
            except:
                return
        self.setValue(value)

    def setValue(self, value):
        getcontext().prec = 2
        self.value = Decimal(value)
        self.display.enterText('%.2f' % float(value))
        if self.callback:
            self.callback(self.value)

    def __handleUpClicked(self):
        getcontext().prec = 2
        self.setValue(float(self.value) + float(self.increment))

    def __handleDownClicked(self):
        getcontext().prec = 2
        self.setValue(float(self.value) - float(self.increment))
Example #4
0
class ColourChannel(DirectObject):
    __slider_edit_callback: Callable[['ColourChannel', float], None]
    __entry_edit_callback: Callable[['ColourChannel', float], None]

    __frame: DirectFrame
    __label: DirectLabel
    __slider: DirectSlider
    __entry: DirectEntry
    __disable_frame_overlay: DirectButton
    __enabled: bool

    def __init__(self, parent: DirectFrame, text: str, value: float,
                 slider_edit_callback: Callable[['ColourChannel', float],
                                                None],
                 entry_edit_callback: Callable[['ColourChannel', float], None],
                 mouse1_press_callbacks: List[Callable[[], None]]):
        self.__frame = DirectFrame(parent=parent)
        self.__slider_edit_callback = slider_edit_callback
        self.__entry_edit_callback = entry_edit_callback

        self.__label = DirectLabel(parent=self.__frame,
                                   text=text,
                                   text_fg=WHITE,
                                   text_bg=WINDOW_BG_COLOUR,
                                   pos=(-0.5, 0.0, 0.0),
                                   scale=(0.1, 1.0, 0.1))

        self.__slider = DirectSlider(parent=self.__frame,
                                     orientation=DGG.HORIZONTAL,
                                     borderWidth=(0.0, 0.0),
                                     frameColor=WIDGET_BG_COLOUR,
                                     frameSize=(-1.0, 1.0, -0.4, 0.4),
                                     thumb_frameSize=(-0.075, 0.075, -0.2,
                                                      0.2),
                                     value=value,
                                     pos=(0.05, 0.0, 0.0255),
                                     scale=(0.45, 1.0, 0.5))

        self.__entry_hovered = False
        mouse1_press_callbacks.append(self.__entry_mouse_click_callback)
        self.__entry = DirectEntry(parent=self.__frame,
                                   frameColor=WIDGET_BG_COLOUR,
                                   text_fg=WHITE,
                                   initialText=str(value),
                                   scale=0.1,
                                   width=3,
                                   suppressKeys=True,
                                   pos=(0.55, 0.0, -0.01105))
        self.__entry.bind(DGG.EXIT, self.__entry_exit_callback)
        self.__entry.bind(DGG.ENTER, self.__entry_enter_callback)
        self.__entry.bind(DGG.B1PRESS, self.__entry_mouse_click_callback)
        self.accept("mouse1", self.__entry_mouse_click_callback)

        self.__disable_frame_overlay = DirectButton(parent=self.__frame,
                                                    frameColor=TRANSPARENT,
                                                    borderWidth=(0.0, 0.0),
                                                    frameSize=(-0.6, 0.9, -0.2,
                                                               0.2),
                                                    suppressMouse=True)
        self.__disable_frame_overlay.hide()
        self.__enabled = True

        self.__set_callbacks()

    def __entry_exit_callback(self, *discard) -> None:
        self.__entry_hovered = False

    def __entry_enter_callback(self, *discard) -> None:
        self.__entry_hovered = True

    def __entry_mouse_click_callback(self, *discard) -> None:
        if self.__entry_hovered:
            s = self.__entry.get()
            try:
                f = float(s)
            except:
                return
            self.__entry_edit_callback(self, f)
        else:
            self.__entry['focus'] = False

    def __unset_callbacks(self):
        self.__slider['command'] = None
        self.__entry['command'] = None

    def __set_callbacks(self):
        def slider_callback() -> None:
            self.__slider_edit_callback(self, self.__slider['value'])

        def entry_callback(s) -> None:
            try:
                f = float(s)
            except:
                return
            self.__entry_edit_callback(self, f)

        self.__slider['command'] = slider_callback
        self.__entry['command'] = entry_callback

    @property
    def frame(self) -> DirectFrame:
        return self.__frame

    def update_slider(self, value: float):
        if not self.__enabled:
            return
        self.__unset_callbacks()
        self.__slider['value'] = value
        self.__set_callbacks()

    def update_entry(self, value: float):
        if not self.__enabled:
            return
        self.__unset_callbacks()
        self.__entry.enterText(f'{value:.3f}')
        self.__set_callbacks()

    def update(self, value: float):
        self.update_slider(value)
        self.update_entry(value)

    @property
    def value(self) -> float:
        return self.__slider['value']

    @property
    def enabled(self) -> str:
        return 'enabled'

    @enabled.setter
    def enabled(self, enabled: bool) -> None:
        if self.__enabled == enabled:
            return
        self.__enabled = enabled
        if enabled:
            self.__disable_frame_overlay.hide()
        else:
            self.__disable_frame_overlay.show()

    @enabled.getter
    def enabled(self) -> bool:
        return self.__enabled