Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    How can i get full chinese characters using userarea BFM_INPUT_ASC

    Cinema 4D SDK
    python
    2
    3
    444
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • J
      JACK0319
      last edited by

      Hi,
      I am using GeUserArea to create a text editor in python.
      but when I use BFM_ INPUT_ ASC, it will only return one character!
      How can i get full input of characters? (Here is the simplified code

      def InputEvent(self, msg):
          # i entered 'test' 
          asc = msg[c4d.BFM_INPUT_ASC]
          print(asc)
          # >>> t
          # but i only get 't' 
      
      
      
      

      i want to input 'test' here

      4ac30c7d-dd35-4b5c-bce1-5a9ffbc4e251-image.png

      i write 'test' and pressed enter

      069467c3-4531-482a-829f-908764a7fb34-image.png

      it will only return 't' , but i want to get fully return of 'test' at once

      89885a68-5e70-49e3-a9d7-1f14b5edda7d-image.png

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @JACK0319
        last edited by ferdinand

        Hello @JACK0319,

        Thank you for reaching out to us. I am struggling a bit with understanding what your goals are here.

        But it seems like you would expect input events to be automatically grouped into words. But an input event is a singular keystroke or button press in the input stream. The idea of grouping things together is ambiguous as it is up to the user, you, to decide what he or she would consider logical blocks within an input stream. Your posting unfortunately does not clarify these conditions of yours; the fact that you want to input (simplified) Chinese characters seems to be irrelevant in this case.

        Posting screenshots of code is also non-ideal. Please post executable code when possible, as we otherwise first must rewrite your code when answering. Find below a simple example for what I assume you want to do here.

        Cheers,
        Ferdinand

        Result:
        input_usr_area.gif

        Code:

        """Realizes a dialog with an UserArea element which consolidates keyboard inputs into blocks of inputs
        based on the time delta between inputs.
        
        Must be run as a Script Manager script.
        """
        
        import c4d
        import time
        
        class InputArea(c4d.gui.GeUserArea):
            """Realizes an input element which consolidates inputs into blocks of inputs based on the time
            delta between inputs.
        
            One could also use the builtin timer of GeUserArea (.Timer and .SetTimer), especially when one
            wants to manipulate the value of an instance outside of an input event, e.g., "throw away" a
            value after X milliseconds of inactivity. I went here instead with a simpler design which just 
            uses time.perf_counter and the input events themselves to measure time.
            """
            # The default time span between two input events in seconds which should be separate blocks.
            DEFAULT_MAX_INPUT_BLOCK_DELTA: float = .5
            # Default size of the gadget.
            DEFAULT_SIZE: tuple[int, int] = (50, 50) 
        
            # The drawing colors and the offset of the drawn text in relation to the origin.
            COLOR_BACKGROUND: c4d.Vector = c4d.gui.GetGuiWorldColor(c4d.COLOR_BGEDIT)
            COLOR_TEXT: c4d.Vector = c4d.gui.GetGuiWorldColor(c4d.COLOR_TEXT_EDIT)
            OFFSET_TEXT: tuple[int, int] = (5, 5)
        
            # Indicates a f block.
            NEW_BLOCK: int = -1
        
            def __init__(self) -> None:
                """Initializes the input area.
                """
                # As the class bound default values.
                self._maxInputBlockDelta: int = InputArea.DEFAULT_MAX_INPUT_BLOCK_DELTA
                self._size: tuple[int, int] = InputArea.DEFAULT_SIZE
        
                # The last time the value of the input has changed and the current value.
                self._lastInputTime: int = InputArea.NEW_BLOCK
                self._value: str = ""
        
            def GetMinSize(self) -> tuple[int, int]:
                """Returns the minimum size of the input area.
                """
                return self._size
            
            def DrawMsg(self, x1: int, y1: int, x2: int, y2: int, msg: c4d.BaseContainer) -> None:
                """Draws an edit field like representation of the current value.
        
                There is no cursor logic or anything like that.
                """
                self.DrawSetPen(InputArea.COLOR_BACKGROUND)
                self.DrawSetTextCol(InputArea.COLOR_TEXT, InputArea.COLOR_BACKGROUND)
        
                self.DrawRectangle(x1, y1, x2, y2)
                self.DrawSetFont(c4d.FONT_MONOSPACED)
                self.DrawText(self._value, *InputArea.OFFSET_TEXT)
        
                return
        
            def InputEvent(self, msg: c4d.BaseContainer) -> bool:
                """Updates the value of the instance when the user made a keyboard input.
                """
                # Bail when the input device was not the keyboard or the input value is empty.
                if (msg[c4d.BFM_INPUT_DEVICE] != c4d.BFM_INPUT_KEYBOARD) or not msg[c4d.BFM_INPUT_ASC]:
                    return True
                
                # Update the value of the instance, all the input block logic is encapsulated in the
                # property InputArea.Value. 
                self.Value = msg[c4d.BFM_INPUT_ASC]
                return True
        
            @property
            def Value(self) -> str:
                """Returns the current value of the instance.
                """
                return self._value
        
            @Value.setter
            def Value(self, value: str) -> None:
                """Sets the value of the instance.
        
                Based on the time that has elapsed since the last input, #value will either be appended
                to the value store by the instance or replace it. 
                """
                if not isinstance(value, str):
                    raise TypeError(f"{value = }")
        
                # Overwrite the instance value when we exceeded the delta or the delta is undefined, 
                # otherwise simply append the value to the instance value. Then update the last input time
                # with the current time and redraw the input area.
                t: float = time.perf_counter()
                isNewBlock: bool = ((self._lastInputTime == InputArea.NEW_BLOCK) or 
                                    (t - self._lastInputTime > self._maxInputBlockDelta))
                self._value = value if isNewBlock else self._value + value
                self._lastInputTime = t
                self.Redraw()
                
        
        class MyDialog(c4d.gui.GeDialog):
            """Realizes a simple dialog that uses and #InputArea.
            """
            ID_GRP_MAIN: int = 1000 # The identifier for the main layout group in the dialog.
            ID_INP_DATA: int = 1001 # The identifier for an #InputArea field in the dialog.
        
            def __init__(self) -> None:
                """Initializes the dialog. 
                """
                self._inputArea: InputArea = InputArea()
        
            def CreateLayout(self) -> bool:
                """Adds the InputArea gadget to the dialog inside a main layout group.
                """
                self.SetTitle("User Area Input Example")
                self.GroupBegin(MyDialog.ID_GRP_MAIN, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT)
                self.GroupBorderSpace(5, 5, 5, 5)
        
                self.AddUserArea(MyDialog.ID_INP_DATA, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT)
                self.AttachUserArea(self._inputArea, MyDialog.ID_INP_DATA)
        
                self.GroupEnd()
                return True
        
        
        if __name__ == "__main__":
            # Run the example dialog. It is not recommended to use async dialogs in Script Manager scripts
            # in a production environment. 
            dlg: MyDialog = MyDialog()
            dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=300, default=200)
        

        MAXON SDK Specialist
        developers.maxon.net

        J 1 Reply Last reply Reply Quote 0
        • J
          JACK0319 @ferdinand
          last edited by

          Hi @ferdinand ,

          First of all, I apologize for my poor explanation.

          I ran into an unexplainable situation, but your example solved my problem nicely.
          I couldn't get consecutive characters because I mistakenly called the self.GetInputState(c4d.BFM_INPUT_MOUSE, msg.GetInt32(c4d.BFM_INPUT_CHANNEL), msg) method and it would interrupt getting the original input.

          now I have solved the problem. Thank you very much you guys are the best!
          Cheers~

          1 Reply Last reply Reply Quote 0
          • First post
            Last post