class TextScrolledFrame(object):
    def __init__(self, parent=None, scale=0.05, limitText=1, frameSize=(0, 1.3, 0.2, 0.697), pos=(0, 0, 0.1)):

        self.__scale = scale
        self.__frameSize = frameSize
        self.__canvasSize = (frameSize[0], frameSize[2] - 0.01, frameSize[2], frameSize[3])
        self.__limitText = limitText
        self.__countLine = []

        self.dsf = DirectScrolledFrame(
            parent=parent,
            canvasSize=self.__canvasSize,
            frameSize=self.__frameSize,
            pos=pos,
            frameColor=COR_OPACITY_03_PRETO,
            autoHideScrollBars=1,
            scrollBarWidth=0.05,
            borderWidth=(0, 0),
            verticalScroll_value=1,
            verticalScroll_decButton_frameColor=(1, 1, 1, 0.3),
            verticalScroll_decButton_rolloverSound=None,
            verticalScroll_decButton_clickSound=None,
            verticalScroll_incButton_frameColor=(1, 1, 1, 0.3),
            verticalScroll_incButton_rolloverSound=None,
            verticalScroll_incButton_clickSound=None,
            verticalScroll_thumb_frameColor=(1, 1, 1, 0.3),
            verticalScroll_thumb_rolloverSound=None,
            verticalScroll_thumb_clickSound=None,
        )

        self.__textoHeight = scale
        self.__canvasHeight = self.dsf.getHeight()
        self.__canvas = self.dsf.getCanvas()

    def __command_clear_msg(self):
        self.etyMsg.set("")

    def __reposicionaTexto(self, obj_text):
        height = obj_text.getScale() * obj_text.textNode.getNumRows()

        for text in self.__countLine:
            lastPos = text.textNodePath.getPos()
            text.setPos((lastPos[0], 0, lastPos[2] + height))

    def __resizeCanvasSize(self, text):

        self.__textoHeight += text.getScale() * text.textNode.getNumRows()

        if self.__textoHeight > self.__canvasHeight:
            self.__canvasHeight += self.__textoHeight - self.__canvasHeight

        self.dsf["canvasSize"] = (
            self.dsf["canvasSize"][0],
            self.dsf["canvasSize"][1],
            self.dsf["canvasSize"][2],
            self.dsf["canvasSize"][2] + self.__canvasHeight,
        )
        self.dsf.setCanvasSize()

    def show(self, texto, cor=(1, 1, 1, 1)):

        dfs_pos = self.dsf.getPos()

        pos = (dfs_pos[0] + 0.01, 0, dfs_pos[1] + 0.16)

        text = Text(parent=self.__canvas, scale=self.__scale, text=texto, wordwrap=25, pos=pos, cor=cor)

        numText = len(self.__countLine)
        if numText > 0:
            self.__reposicionaTexto(text)

        self.__countLine.append(text)

        if numText > self.__limitText:
            self.__countLine[0].remove()
            self.__countLine.pop(0)
        else:
            self.__resizeCanvasSize(text)

        self.dsf["verticalScroll_value"] = 1
Example #2
0
class DeviceConnectivityMonitor(DirectObject):
    def __init__(self):
        super().__init__()
        self.mgr = InputDeviceManager.get_global_ptr()
        self.create_device_menu()

        self.devices = {}
        for device in self.mgr.get_devices():
            self.connect_device(device)

        self.accept("connect-device", self.connect_device)
        self.accept("disconnect-device", self.disconnect_device)

    def create_device_menu(self):
        self.current_panel = None
        self.buttons = {}
        self.devices_frame = DirectScrolledFrame(
            frameSize=VBase4(
                0,
                base.a2dLeft*-0.75,
                base.a2dBottom - base.a2dTop,
                0,
            ),
            frameColor=VBase4(0, 0, 0.25, 1.0),
            canvasSize=VBase4(
                0,
                base.a2dLeft*-0.75,
                0,
                0,
            ),
            scrollBarWidth=0.08,
            manageScrollBars=True,
            autoHideScrollBars=True,
            pos=(base.a2dLeft, 0, base.a2dTop),
            parent=base.aspect2d,
        )

        self.devices_frame.setCanvasSize()

    def create_menu_button(self, device):
        button = DirectButton(
            command=self.switch_to_panel,
            extraArgs=[device],
            text=device.name,
            text_scale=0.05,
            text_align=TextNode.ALeft,
            text_fg=VBase4(0.0, 0.0, 0.0, 1.0),
            text_pos=Vec2(0.01, base.a2dBottom / 10.0),
            relief=1,
            pad=Vec2(0.01, 0.01),
            frameColor=VBase4(0.8, 0.8, 0.8, 1.0),
            frameSize=VBase4(
                0.0,
                base.a2dLeft*-0.75 - 0.081,  # 0.08=Scrollbar, 0.001=inaccuracy
                base.a2dBottom / 5.0,
                0.0,
            ),
            parent=self.devices_frame.getCanvas(),
        )
        self.buttons[device] = button

    def destroy_menu_button(self, device):
        self.buttons[device].detach_node()
        del self.buttons[device]

    def refresh_device_menu(self):
        self.devices_frame['canvasSize'] = VBase4(
            0,
            base.a2dLeft*-0.75,
            base.a2dBottom / 5.0 * len(self.buttons),
            0,
        )
        self.devices_frame.setCanvasSize()
        sorted_buttons = sorted(self.buttons.items(), key=lambda i: i[0].name)
        for idx, (dev, button) in enumerate(sorted_buttons):
            button.set_pos(
                0,
                0,
                (base.a2dBottom / 5.0) * idx,
            )

    def switch_to_panel(self, device):
        if self.current_panel is not None:
            self.devices[self.current_panel].hide()
        self.current_panel = device
        self.devices[self.current_panel].show()

    def connect_device(self, device):
        self.devices[device] = DeviceMonitor(device)
        self.switch_to_panel(device)
        self.create_menu_button(device)
        self.refresh_device_menu()

    def disconnect_device(self, device):
        self.devices[device].deactivate()
        del self.devices[device]
        if self.current_panel == device:
            self.current_panel = None
            if len(self.devices) > 0:
                active_device = sorted(
                    self.devices.keys(),
                    key=lambda d: d.name,
                )[0]
                self.switch_to_panel(active_device)

        self.destroy_menu_button(device)
        self.refresh_device_menu()
Example #3
0
class DeviceMonitor(DirectObject):
    def __init__(self, device):
        super().__init__()
        self.device = device
        self.create_panel()
        self.activate()
        self.hide()

    def activate(self):
        print("Device connected")
        print("  Name        : {}".format(self.device.name))
        print("  Type        : {}".format(self.device.device_class.name))
        print("  Manufacturer: {}".format(self.device.manufacturer))
        print("  ID          : {:04x}:{:04x}".format(self.device.vendor_id,
                                                     self.device.product_id))
        axis_names = [axis.axis.name for axis in self.device.axes]
        print("  Axes        : {} ({})".format(len(self.device.axes),
                                               ', '.join(axis_names)))
        button_names = [button.handle.name for button in self.device.buttons]
        print("  Buttons     : {} ({})".format(len(self.device.buttons),
                                               ', '.join(button_names)))

        base.attachInputDevice(self.device)

        self.task = base.taskMgr.add(
            self.update,
            "Monitor for {}".format(self.device.name),
            sort=10,
        )

    def deactivate(self):
        print("\"{}\" disconnected".format(self.device.name))
        base.taskMgr.remove(self.task)
        self.panel.detach_node()

    def create_panel(self):
        panel_width = base.a2dLeft * -0.25 + base.a2dRight
        scroll_bar_width = 0.08
        # NOTE: -0.001 because thanks to inaccuracy the vertical bar appears...
        canvas_width = panel_width - scroll_bar_width - 0.001
        canvas_height = base.a2dBottom - base.a2dTop

        self.panel = DirectScrolledFrame(
            frameSize=VBase4(
                0,
                panel_width,
                canvas_height,
                0,
            ),
            frameColor=VBase4(0.8, 0.8, 0.8, 1),
            canvasSize=VBase4(
                0,
                canvas_width,
                canvas_height,
                0,
            ),
            scrollBarWidth=scroll_bar_width,
            manageScrollBars=True,
            autoHideScrollBars=True,
            pos=(base.a2dLeft * 0.25, 0, base.a2dTop),
            parent=base.aspect2d,
        )
        panel_canvas = self.panel.getCanvas()
        offset = -0.0

        # Style sheets

        half_width_entry = dict(
            frameSize=VBase4(
                0,
                canvas_width / 2,
                -0.1,
                0,
            ),
            parent=panel_canvas,
            frameColor=VBase4(0.8, 0.8, 0.8, 1),
        )
        left_aligned_small_text = dict(
            text_align=TextNode.ALeft,
            text_scale=0.05,
            text_fg=VBase4(0,0,0,1),
            text_pos=(0.05, -0.06),
        )
        half_width_text_frame = dict(
            **half_width_entry,
            **left_aligned_small_text,
        )

        header = dict(
            frameSize=VBase4(
                0,
                canvas_width,
                -0.1,
                0,
            ),
            parent=panel_canvas,
            frameColor=VBase4(0.6, 0.6, 0.6, 1),
            text_align=TextNode.ALeft,
            text_scale=0.1,
            text_fg=VBase4(0,0,0,1),
            text_pos=(0.05, -0.075),
        )

        # Basic device data (name, device class, manufacturer, USB ID)

        self.device_header = DirectLabel(
            text="Device data",
            pos=(0, 0, offset),
            **header,
        )
        offset -= 0.1

        def add_data_entry(offset, label, text):
            self.name = DirectLabel(
                text=label,
                pos=(0, 0, offset),
                **half_width_text_frame,
            )
            self.name = DirectLabel(
                text=text,
                pos=(canvas_width / 2, 0, offset),
                **half_width_text_frame,
            )

        metadata = [
            ('Name', self.device.name),
            ('Device class', self.device.device_class.name),
            ('Manufacturer', self.device.manufacturer),
            ('USB ID',
             "{:04x}:{:04x}".format(
                 self.device.vendor_id,
                 self.device.product_id,
             ),
            ),
        ]
        for label, text in metadata:
            add_data_entry(offset, label, text)
            offset -= 0.1

        # Axes

        self.axis_sliders = []
        if len(self.device.axes) > 0:
            offset -= 0.1
            self.axes_header = DirectLabel(
                text="Axes",
                pos=(0, 0, offset),
                **header,
            )
            offset -= 0.1

            def add_axis(offset, axis_name):
                slider_width = canvas_width / 2
                label = DirectLabel(
                    text=axis_name,
                    **left_aligned_small_text,
                    pos=(0.05, 0, offset),
                    parent=panel_canvas,
                )
                slider = DirectSlider(
                    value=0.0,
                    range=(-1.0, 1.0),
                    state=DGG.DISABLED,
                    frameSize=VBase4(
                        0,
                        slider_width,
                        -0.1,
                        0,
                    ),
                    thumb_frameSize=VBase4(
                        0.0,
                        0.04,
                        -0.04,
                        0.04),
                    frameColor=VBase4(0.3, 0.3, 0.3, 1),
                    pos=(canvas_width - slider_width, 0, offset),
                    parent=panel_canvas,
                )
                return slider

            for axis in self.device.axes:
                axis_slider = add_axis(offset, axis.axis.name)
                self.axis_sliders.append(axis_slider)
                offset -= 0.1

        # Buttons

        self.button_buttons = []
        if len(self.device.buttons) > 0:
            offset -= 0.1
            self.buttons_header = DirectLabel(
                text="Buttons",
                pos=(0, 0, offset),
                **header,
            )
            offset -= 0.1

            def add_button(offset, button_name):
                button_width = canvas_width / 2
                label = DirectLabel(
                    text=button_name,
                    **left_aligned_small_text,
                    pos=(0.05, 0, offset),
                    parent=panel_canvas,
                )
                button = DirectFrame(
                    frameSize=VBase4(
                        0,
                        button_width,
                        -0.1,
                        0,
                    ),
                    text="",
                    text_align=TextNode.ACenter,
                    text_scale=0.05,
                    text_fg=VBase4(0,0,0,1),
                    text_pos=(button_width / 2, -0.06),
                    frameColor=VBase4(0.3, 0.3, 0.3, 1),
                    pos=(canvas_width - button_width, 0, offset),
                    parent=panel_canvas,
                )
                return button

            for i in range(len(self.device.buttons)):
                button_name = self.device.buttons[i].handle.name
                button_button = add_button(offset, button_name)
                self.button_buttons.append(button_button)
                offset -= 0.1

        # Vibration

        self.vibration = []
        if self.device.has_feature(InputDevice.Feature.vibration):
            offset -= 0.1
            self.vibration_header = DirectLabel(
                text="Vibration",
                pos=(0, 0, offset),
                **header,
            )
            offset -= 0.1

            def add_vibration(offset, axis_name, index):
                slider_width = canvas_width / 2
                label = DirectLabel(
                    text=axis_name,
                    **left_aligned_small_text,
                    pos=(0.05, 0, offset),
                    parent=panel_canvas,
                )
                slider = DirectSlider(
                    value=0.0,
                    range=(0.0, 1.0),
                    command=self.update_vibration,
                    frameSize=VBase4(
                        0,
                        slider_width,
                        -0.1,
                        0,
                    ),
                    thumb_frameSize=VBase4(
                        0.0,
                        0.04,
                        -0.04,
                        0.04),
                    frameColor=VBase4(0.3, 0.3, 0.3, 1),
                    pos=(canvas_width - slider_width, 0, offset),
                    parent=panel_canvas,
                )
                return slider

            for index, name in enumerate(["low frequency", "high frequency"]):
                self.vibration.append(add_vibration(offset, name, index))
                offset -= 0.1

        # Resize the panel's canvas to the widgets actually in it.
        if -offset > -canvas_height:
            self.panel['canvasSize'] = VBase4(
                0,
                canvas_width,
                offset,
                0,
            )
        self.panel.setCanvasSize()

    def show(self):
        # FIXME: Activate update task here, and deactivate it in hide()?
        self.panel.show()

    def hide(self):
        self.panel.hide()

    def update_vibration(self):
        low = self.vibration[0]['value']
        high = self.vibration[1]['value']
        self.device.set_vibration(low, high)

    def update(self, task):
        # FIXME: There needs to be a demo of events here, too.
        for idx, slider in enumerate(self.axis_sliders):
            slider["value"] = self.device.axes[idx].value
        for idx, button in enumerate(self.button_buttons):
            if self.device.buttons[idx].known:
                if self.device.buttons[idx].pressed:
                    button['frameColor'] = VBase4(0.0, 0.8, 0.0, 1)
                    button['text'] = "down"
                else:
                    button['frameColor'] = VBase4(0.3, 0.3, 0.3, 1)
                    button['text'] = "up"
            else:
                # State is InputDevice.S_unknown. This happens if the device
                # manager hasn't polled yet, and in some cases before a button
                # has been pressed after the program's start.
                button['frameColor'] = VBase4(0.8, 0.8, 0.0, 1)
                button['text'] = "unknown"
        return task.cont
Example #4
0
class MappingGUIDemo(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.setBackgroundColor(0, 0, 0)
        # make the font look nice at a big scale
        DGG.getDefaultFont().setPixelsPerUnit(100)

        # Store our mapping, with some sensible defaults.  In a real game, you
        # will want to load these from a configuration file.
        self.mapping = InputMapping()
        self.mapping.mapAxis("Move forward", InputDevice.Axis.left_y)
        self.mapping.mapAxis("Move backward", InputDevice.Axis.left_y)
        self.mapping.mapAxis("Move left", InputDevice.Axis.left_x)
        self.mapping.mapAxis("Move right", InputDevice.Axis.left_x)
        self.mapping.mapButton("Jump", GamepadButton.face_a())
        self.mapping.mapButton("Use", GamepadButton.face_b())
        self.mapping.mapButton("Break", GamepadButton.face_x())
        self.mapping.mapButton("Fix", GamepadButton.face_y())

        # The geometry for our basic buttons
        maps = loader.loadModel("models/button_map")
        self.buttonGeom = (maps.find("**/ready"), maps.find("**/click"),
                           maps.find("**/hover"), maps.find("**/disabled"))

        # Change the default dialog skin.
        DGG.setDefaultDialogGeom("models/dialog.png")

        # create a sample title
        self.textscale = 0.1
        self.title = DirectLabel(scale=self.textscale,
                                 pos=(base.a2dLeft + 0.05, 0.0,
                                      base.a2dTop - (self.textscale + 0.05)),
                                 frameColor=VBase4(0, 0, 0, 0),
                                 text="Button Mapping",
                                 text_align=TextNode.ALeft,
                                 text_fg=VBase4(1, 1, 1, 1),
                                 text_shadow=VBase4(0, 0, 0, 0.75),
                                 text_shadowOffset=Vec2(0.05, 0.05))
        self.title.setTransparency(1)

        # Set up the list of actions that we can map keys to
        # create a frame that will create the scrollbars for us
        # Load the models for the scrollbar elements
        thumbMaps = loader.loadModel("models/thumb_map")
        thumbGeom = (thumbMaps.find("**/thumb_ready"),
                     thumbMaps.find("**/thumb_click"),
                     thumbMaps.find("**/thumb_hover"),
                     thumbMaps.find("**/thumb_disabled"))
        incMaps = loader.loadModel("models/inc_map")
        incGeom = (incMaps.find("**/inc_ready"), incMaps.find("**/inc_click"),
                   incMaps.find("**/inc_hover"),
                   incMaps.find("**/inc_disabled"))
        decMaps = loader.loadModel("models/dec_map")
        decGeom = (decMaps.find("**/dec_ready"), decMaps.find("**/dec_click"),
                   decMaps.find("**/dec_hover"),
                   decMaps.find("**/dec_disabled"))

        # create the scrolled frame that will hold our list
        self.lstActionMap = DirectScrolledFrame(
            # make the frame occupy the whole window
            frameSize=VBase4(base.a2dLeft, base.a2dRight, 0.0, 1.55),
            # make the canvas as big as the frame
            canvasSize=VBase4(base.a2dLeft, base.a2dRight, 0.0, 0.0),
            # set the frames color to white
            frameColor=VBase4(0, 0, 0.25, 0.75),
            pos=(0, 0, -0.8),
            verticalScroll_scrollSize=0.2,
            verticalScroll_frameColor=VBase4(0.02, 0.02, 0.02, 1),
            verticalScroll_thumb_relief=1,
            verticalScroll_thumb_geom=thumbGeom,
            verticalScroll_thumb_pressEffect=False,
            verticalScroll_thumb_frameColor=VBase4(0, 0, 0, 0),
            verticalScroll_incButton_relief=1,
            verticalScroll_incButton_geom=incGeom,
            verticalScroll_incButton_pressEffect=False,
            verticalScroll_incButton_frameColor=VBase4(0, 0, 0, 0),
            verticalScroll_decButton_relief=1,
            verticalScroll_decButton_geom=decGeom,
            verticalScroll_decButton_pressEffect=False,
            verticalScroll_decButton_frameColor=VBase4(0, 0, 0, 0),
        )

        # creat the list items
        idx = 0
        self.listBGEven = base.loader.loadModel("models/list_item_even")
        self.listBGOdd = base.loader.loadModel("models/list_item_odd")
        self.actionLabels = {}
        for action in self.mapping.actions:
            mapped = self.mapping.formatMapping(action)
            item = self.__makeListItem(action, mapped, idx)
            item.reparentTo(self.lstActionMap.getCanvas())
            idx += 1

        # recalculate the canvas size to set scrollbars if necesary
        self.lstActionMap["canvasSize"] = (base.a2dLeft + 0.05,
                                           base.a2dRight - 0.05,
                                           -(len(self.mapping.actions) * 0.1),
                                           0.09)
        self.lstActionMap.setCanvasSize()

    def closeDialog(self, action, newInputType, newInput):
        """Called in callback when the dialog is closed.  newInputType will be
        "button" or "axis", or None if the remapping was cancelled."""

        self.dlgInput = None

        if newInputType is not None:
            # map the event to the given action
            if newInputType == "axis":
                self.mapping.mapAxis(action, newInput)
            else:
                self.mapping.mapButton(action, newInput)

            # actualize the label in the list that shows the current
            # event for the action
            self.actionLabels[action]["text"] = self.mapping.formatMapping(
                action)

        # cleanup
        for bt in base.buttonThrowers:
            bt.node().setSpecificFlag(True)
            bt.node().setButtonDownEvent("")
        for bt in base.deviceButtonThrowers:
            bt.node().setSpecificFlag(True)
            bt.node().setButtonDownEvent("")
        taskMgr.remove("checkControls")

        # Now detach all the input devices.
        for device in self.attachedDevices:
            base.detachInputDevice(device)
        self.attachedDevices.clear()

    def changeMapping(self, action):
        # Create the dialog window
        self.dlgInput = ChangeActionDialog(action,
                                           button_geom=self.buttonGeom,
                                           command=self.closeDialog)

        # Attach all input devices.
        devices = base.devices.getDevices()
        for device in devices:
            base.attachInputDevice(device)
        self.attachedDevices = devices

        # Disable regular button events on all button event throwers, and
        # instead broadcast a generic event.
        for bt in base.buttonThrowers:
            bt.node().setSpecificFlag(False)
            bt.node().setButtonDownEvent("keyListenEvent")
        for bt in base.deviceButtonThrowers:
            bt.node().setSpecificFlag(False)
            bt.node().setButtonDownEvent("deviceListenEvent")

        self.accept("keyListenEvent", self.dlgInput.buttonPressed)
        self.accept("deviceListenEvent", self.dlgInput.buttonPressed)

        # As there are no events thrown for control changes, we set up a task
        # to check if the controls were moved
        # This list will help us for checking which controls were moved
        self.axisStates = {None: {}}
        # fill it with all available controls
        for device in devices:
            for axis in device.axes:
                if device not in self.axisStates.keys():
                    self.axisStates.update({device: {axis.axis: axis.value}})
                else:
                    self.axisStates[device].update({axis.axis: axis.value})
        # start the task
        taskMgr.add(self.watchControls, "checkControls")

    def watchControls(self, task):
        # move through all devices and all it's controls
        for device in self.attachedDevices:
            if device.device_class == InputDevice.DeviceClass.mouse:
                # Ignore mouse axis movement, or the user can't even navigate
                # to the OK/Cancel buttons!
                continue

            for axis in device.axes:
                # if a control got changed more than the given dead zone
                if self.axisStates[device][axis.axis] + DEAD_ZONE < axis.value or \
                   self.axisStates[device][axis.axis] - DEAD_ZONE > axis.value:
                    # set the current state in the dict
                    self.axisStates[device][axis.axis] = axis.value

                    # Format the axis for being displayed.
                    if axis.axis != InputDevice.Axis.none:
                        #label = axis.axis.name.replace('_', ' ').title()
                        self.dlgInput.axisMoved(axis.axis)

        return task.cont

    def __makeListItem(self, action, event, index):
        def dummy():
            pass

        if index % 2 == 0:
            bg = self.listBGEven
        else:
            bg = self.listBGOdd
        item = DirectFrame(text=action,
                           geom=bg,
                           geom_scale=(base.a2dRight - 0.05, 1, 0.1),
                           frameSize=VBase4(base.a2dLeft + 0.05,
                                            base.a2dRight - 0.05, -0.05, 0.05),
                           frameColor=VBase4(1, 0, 0, 0),
                           text_align=TextNode.ALeft,
                           text_scale=0.05,
                           text_fg=VBase4(1, 1, 1, 1),
                           text_pos=(base.a2dLeft + 0.3, -0.015),
                           text_shadow=VBase4(0, 0, 0, 0.35),
                           text_shadowOffset=Vec2(-0.05, -0.05),
                           pos=(0.05, 0, -(0.10 * index)))
        item.setTransparency(True)
        lbl = DirectLabel(
            text=event,
            text_fg=VBase4(1, 1, 1, 1),
            text_scale=0.05,
            text_pos=Vec2(0, -0.015),
            frameColor=VBase4(0, 0, 0, 0),
        )
        lbl.reparentTo(item)
        lbl.setTransparency(True)
        self.actionLabels[action] = lbl

        buttonScale = 0.15
        btn = DirectButton(text="Change",
                           geom=self.buttonGeom,
                           scale=buttonScale,
                           text_scale=0.25,
                           text_align=TextNode.ALeft,
                           text_fg=VBase4(0.898, 0.839, 0.730, 1.0),
                           text_pos=Vec2(-0.9, -0.085),
                           relief=1,
                           pad=Vec2(0.01, 0.01),
                           frameColor=VBase4(0, 0, 0, 0),
                           frameSize=VBase4(-1.0, 1.0, -0.25, 0.25),
                           pos=(base.a2dRight - (0.898 * buttonScale + 0.3), 0,
                                0),
                           pressEffect=False,
                           command=self.changeMapping,
                           extraArgs=[action])
        btn.setTransparency(True)
        btn.reparentTo(item)
        return item
Example #5
0
class TextScrolledFrame(object):
    def __init__(self,
                 parent=None,
                 scale=.05,
                 limitText=1,
                 frameSize=(0, 1.3, .2, .697),
                 pos=(0, 0, .1)):

        self.__scale = scale
        self.__frameSize = frameSize
        self.__canvasSize = (frameSize[0], frameSize[2] - .01, frameSize[2],
                             frameSize[3])
        self.__limitText = limitText
        self.__countLine = []

        self.dsf = DirectScrolledFrame(
            parent=parent,
            canvasSize=self.__canvasSize,
            frameSize=self.__frameSize,
            pos=pos,
            frameColor=COR_OPACITY_03_PRETO,
            autoHideScrollBars=1,
            scrollBarWidth=0.05,
            borderWidth=(0, 0),
            verticalScroll_value=1,
            verticalScroll_decButton_frameColor=(1, 1, 1, 0.3),
            verticalScroll_decButton_rolloverSound=None,
            verticalScroll_decButton_clickSound=None,
            verticalScroll_incButton_frameColor=(1, 1, 1, 0.3),
            verticalScroll_incButton_rolloverSound=None,
            verticalScroll_incButton_clickSound=None,
            verticalScroll_thumb_frameColor=(1, 1, 1, 0.3),
            verticalScroll_thumb_rolloverSound=None,
            verticalScroll_thumb_clickSound=None)

        self.__textoHeight = scale
        self.__canvasHeight = self.dsf.getHeight()
        self.__canvas = self.dsf.getCanvas()

    def __command_clear_msg(self):
        self.etyMsg.set("")

    def __reposicionaTexto(self, obj_text):
        height = obj_text.getScale() * obj_text.textNode.getNumRows()

        for text in self.__countLine:
            lastPos = text.textNodePath.getPos()
            text.setPos((lastPos[0], 0, lastPos[2] + height))

    def __resizeCanvasSize(self, text):

        self.__textoHeight += text.getScale() * text.textNode.getNumRows()

        if self.__textoHeight > self.__canvasHeight:
            self.__canvasHeight += self.__textoHeight - self.__canvasHeight

        self.dsf['canvasSize'] = (self.dsf['canvasSize'][0],
                                  self.dsf['canvasSize'][1],
                                  self.dsf['canvasSize'][2],
                                  self.dsf['canvasSize'][2] +
                                  self.__canvasHeight)
        self.dsf.setCanvasSize()

    def show(self, texto, cor=(1, 1, 1, 1)):

        dfs_pos = self.dsf.getPos()

        pos = (dfs_pos[0] + .01, 0, dfs_pos[1] + 0.16)

        text = Text(parent=self.__canvas,
                    scale=self.__scale,
                    text=texto,
                    wordwrap=25,
                    pos=pos,
                    cor=cor)

        numText = len(self.__countLine)
        if numText > 0:
            self.__reposicionaTexto(text)

        self.__countLine.append(text)

        if numText > self.__limitText:
            self.__countLine[0].remove()
            self.__countLine.pop(0)
        else:
            self.__resizeCanvasSize(text)

        self.dsf['verticalScroll_value'] = 1
Example #6
0
class MappingGUIDemo(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.setBackgroundColor(0, 0, 0)
        # make the font look nice at a big scale
        DGG.getDefaultFont().setPixelsPerUnit(100)

        # Store our mapping, with some sensible defaults.  In a real game, you
        # will want to load these from a configuration file.
        self.mapping = InputMapping()
        self.mapping.mapAxis("Move forward", InputDevice.Axis.left_y)
        self.mapping.mapAxis("Move backward", InputDevice.Axis.left_y)
        self.mapping.mapAxis("Move left", InputDevice.Axis.left_x)
        self.mapping.mapAxis("Move right", InputDevice.Axis.left_x)
        self.mapping.mapButton("Jump", GamepadButton.face_a())
        self.mapping.mapButton("Use", GamepadButton.face_b())
        self.mapping.mapButton("Break", GamepadButton.face_x())
        self.mapping.mapButton("Fix", GamepadButton.face_y())

        # The geometry for our basic buttons
        maps = loader.loadModel("models/button_map")
        self.buttonGeom = (
            maps.find("**/ready"),
            maps.find("**/click"),
            maps.find("**/hover"),
            maps.find("**/disabled"))

        # Change the default dialog skin.
        DGG.setDefaultDialogGeom("models/dialog.png")

        # create a sample title
        self.textscale = 0.1
        self.title = DirectLabel(
            scale=self.textscale,
            pos=(base.a2dLeft + 0.05, 0.0, base.a2dTop - (self.textscale + 0.05)),
            frameColor=VBase4(0, 0, 0, 0),
            text="Button Mapping",
            text_align=TextNode.ALeft,
            text_fg=VBase4(1, 1, 1, 1),
            text_shadow=VBase4(0, 0, 0, 0.75),
            text_shadowOffset=Vec2(0.05, 0.05))
        self.title.setTransparency(1)

        # Set up the list of actions that we can map keys to
        # create a frame that will create the scrollbars for us
        # Load the models for the scrollbar elements
        thumbMaps = loader.loadModel("models/thumb_map")
        thumbGeom = (
            thumbMaps.find("**/thumb_ready"),
            thumbMaps.find("**/thumb_click"),
            thumbMaps.find("**/thumb_hover"),
            thumbMaps.find("**/thumb_disabled"))
        incMaps = loader.loadModel("models/inc_map")
        incGeom = (
            incMaps.find("**/inc_ready"),
            incMaps.find("**/inc_click"),
            incMaps.find("**/inc_hover"),
            incMaps.find("**/inc_disabled"))
        decMaps = loader.loadModel("models/dec_map")
        decGeom = (
            decMaps.find("**/dec_ready"),
            decMaps.find("**/dec_click"),
            decMaps.find("**/dec_hover"),
            decMaps.find("**/dec_disabled"))

        # create the scrolled frame that will hold our list
        self.lstActionMap = DirectScrolledFrame(
            # make the frame occupy the whole window
            frameSize=VBase4(base.a2dLeft, base.a2dRight, 0.0, 1.55),
            # make the canvas as big as the frame
            canvasSize=VBase4(base.a2dLeft, base.a2dRight, 0.0, 0.0),
            # set the frames color to white
            frameColor=VBase4(0, 0, 0.25, 0.75),
            pos=(0, 0, -0.8),

            verticalScroll_scrollSize=0.2,
            verticalScroll_frameColor=VBase4(0.02, 0.02, 0.02, 1),

            verticalScroll_thumb_relief=1,
            verticalScroll_thumb_geom=thumbGeom,
            verticalScroll_thumb_pressEffect=False,
            verticalScroll_thumb_frameColor=VBase4(0, 0, 0, 0),

            verticalScroll_incButton_relief=1,
            verticalScroll_incButton_geom=incGeom,
            verticalScroll_incButton_pressEffect=False,
            verticalScroll_incButton_frameColor=VBase4(0, 0, 0, 0),

            verticalScroll_decButton_relief=1,
            verticalScroll_decButton_geom=decGeom,
            verticalScroll_decButton_pressEffect=False,
            verticalScroll_decButton_frameColor=VBase4(0, 0, 0, 0),)

        # creat the list items
        idx = 0
        self.listBGEven = base.loader.loadModel("models/list_item_even")
        self.listBGOdd = base.loader.loadModel("models/list_item_odd")
        self.actionLabels = {}
        for action in self.mapping.actions:
            mapped = self.mapping.formatMapping(action)
            item = self.__makeListItem(action, mapped, idx)
            item.reparentTo(self.lstActionMap.getCanvas())
            idx += 1

        # recalculate the canvas size to set scrollbars if necesary
        self.lstActionMap["canvasSize"] = (
            base.a2dLeft+0.05, base.a2dRight-0.05,
            -(len(self.mapping.actions)*0.1), 0.09)
        self.lstActionMap.setCanvasSize()

    def closeDialog(self, action, newInputType, newInput):
        """Called in callback when the dialog is closed.  newInputType will be
        "button" or "axis", or None if the remapping was cancelled."""

        self.dlgInput = None

        if newInputType is not None:
            # map the event to the given action
            if newInputType == "axis":
                self.mapping.mapAxis(action, newInput)
            else:
                self.mapping.mapButton(action, newInput)

            # actualize the label in the list that shows the current
            # event for the action
            self.actionLabels[action]["text"] = self.mapping.formatMapping(action)

        # cleanup
        for bt in base.buttonThrowers:
            bt.node().setSpecificFlag(True)
            bt.node().setButtonDownEvent("")
        for bt in base.deviceButtonThrowers:
            bt.node().setSpecificFlag(True)
            bt.node().setButtonDownEvent("")
        taskMgr.remove("checkControls")

        # Now detach all the input devices.
        for device in self.attachedDevices:
            base.detachInputDevice(device)
        self.attachedDevices.clear()

    def changeMapping(self, action):
        # Create the dialog window
        self.dlgInput = ChangeActionDialog(action, button_geom=self.buttonGeom, command=self.closeDialog)

        # Attach all input devices.
        devices = base.devices.getDevices()
        for device in devices:
            base.attachInputDevice(device)
        self.attachedDevices = devices

        # Disable regular button events on all button event throwers, and
        # instead broadcast a generic event.
        for bt in base.buttonThrowers:
            bt.node().setSpecificFlag(False)
            bt.node().setButtonDownEvent("keyListenEvent")
        for bt in base.deviceButtonThrowers:
            bt.node().setSpecificFlag(False)
            bt.node().setButtonDownEvent("deviceListenEvent")

        self.accept("keyListenEvent", self.dlgInput.buttonPressed)
        self.accept("deviceListenEvent", self.dlgInput.buttonPressed)

        # As there are no events thrown for control changes, we set up a task
        # to check if the controls were moved
        # This list will help us for checking which controls were moved
        self.axisStates = {None: {}}
        # fill it with all available controls
        for device in devices:
            for axis in device.axes:
                if device not in self.axisStates.keys():
                    self.axisStates.update({device: {axis.axis: axis.value}})
                else:
                    self.axisStates[device].update({axis.axis: axis.value})
        # start the task
        taskMgr.add(self.watchControls, "checkControls")

    def watchControls(self, task):
        # move through all devices and all it's controls
        for device in self.attachedDevices:
            if device.device_class == InputDevice.DeviceClass.mouse:
                # Ignore mouse axis movement, or the user can't even navigate
                # to the OK/Cancel buttons!
                continue

            for axis in device.axes:
                # if a control got changed more than the given dead zone
                if self.axisStates[device][axis.axis] + DEAD_ZONE < axis.value or \
                   self.axisStates[device][axis.axis] - DEAD_ZONE > axis.value:
                    # set the current state in the dict
                    self.axisStates[device][axis.axis] = axis.value

                    # Format the axis for being displayed.
                    if axis.axis != InputDevice.Axis.none:
                        #label = axis.axis.name.replace('_', ' ').title()
                        self.dlgInput.axisMoved(axis.axis)

        return task.cont

    def __makeListItem(self, action, event, index):
        def dummy(): pass
        if index % 2 == 0:
            bg = self.listBGEven
        else:
            bg = self.listBGOdd
        item = DirectFrame(
            text=action,
            geom=bg,
            geom_scale=(base.a2dRight-0.05, 1, 0.1),
            frameSize=VBase4(base.a2dLeft+0.05, base.a2dRight-0.05, -0.05, 0.05),
            frameColor=VBase4(1,0,0,0),
            text_align=TextNode.ALeft,
            text_scale=0.05,
            text_fg=VBase4(1,1,1,1),
            text_pos=(base.a2dLeft + 0.3, -0.015),
            text_shadow=VBase4(0, 0, 0, 0.35),
            text_shadowOffset=Vec2(-0.05, -0.05),
            pos=(0.05, 0, -(0.10 * index)))
        item.setTransparency(True)
        lbl = DirectLabel(
            text=event,
            text_fg=VBase4(1, 1, 1, 1),
            text_scale=0.05,
            text_pos=Vec2(0, -0.015),
            frameColor=VBase4(0, 0, 0, 0),
            )
        lbl.reparentTo(item)
        lbl.setTransparency(True)
        self.actionLabels[action] = lbl

        buttonScale = 0.15
        btn = DirectButton(
            text="Change",
            geom=self.buttonGeom,
            scale=buttonScale,
            text_scale=0.25,
            text_align=TextNode.ALeft,
            text_fg=VBase4(0.898, 0.839, 0.730, 1.0),
            text_pos=Vec2(-0.9, -0.085),
            relief=1,
            pad=Vec2(0.01, 0.01),
            frameColor=VBase4(0, 0, 0, 0),
            frameSize=VBase4(-1.0, 1.0, -0.25, 0.25),
            pos=(base.a2dRight-(0.898*buttonScale+0.3), 0, 0),
            pressEffect=False,
            command=self.changeMapping,
            extraArgs=[action])
        btn.setTransparency(True)
        btn.reparentTo(item)
        return item