How can i get full chinese characters using userarea BFM_INPUT_ASC
-
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 codedef 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
i write 'test' and pressed enter
it will only return 't' , but i want to get fully return of 'test' at once
-
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,
FerdinandResult:
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)
-
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~