erpicci

Villager
Member
Joined
Feb 3, 2015
Messages
29
Reaction score
21
First Language
Italian
Primarily Uses
Text_Input 1.1
Author: erpicci


Introduction


This script allows the player to insert a medium-sized text by typing directly with the keyboard. Inserted text is returned as a string.


Requires Neon Black's Keyboard Input Script to work.


It is completely free, both for commercial and non-commercial use. All you are asked to do is to give me credits for the script.


Features

  • Plug and play
  • Type directly from keyboard
  • Use enter to confirm your input
  • Use backspace to delete last character
  • Use "Esc" to quit the input mode (input process will result in an empty string)
  • No known compatibility issues
  • Integrates seamlessly with window system
  • Additional window configuration (position, size, opacity)



Screenshots
As simple as calling a script. These shots shows how to implement an echo message and how to use other options.

input.jpgecho.jpg03.jpg04.jpg



How to Use


Be sure to have Neon Black's Keyboard Input Script installed.


Place this script in the "Materials" section of the scripts above main.


To insert a text using an event, create a script event like:


text_var = text_input("Window Title")


To have a script call the text input, use:


text_var = Scene_Text.read("Window Title")


Only window title is mandatory. As optional arguments, you can set:

  • alignment: "center" (default), "left", "right"
  • maximum number of character: default is 104
  • left-to-right: default is true, use false to get a right-to-left input
  • configuration object (see examples)



Examples

# Open a window whose title is "Talk to Bobby", text is centered,
# allows to enter up to 20 characters, writing is right-to-left
variable = Scene_Text.read("Talk to Bobby", "center", 20, false)

# Open a window whose title is "Tell me something", text is aligned
# to right, allows to enter up to 88 characters, writing is
# left-to-right (default)
variable = Scene_Text.read("Tell me something", "center", 88)

# Open a window whose title is "Insert text", text is centered
# (default), accepts up to 104 characters (default), writing is
# left-to-right (default)
variable = Scene_Text.read("Insert text")

# Open a window whose title is "Text:", text is centered, allows
# to enter up to 20 characters, writing is left-to-right,
# window is resized, centered in the screen and semi-transparent
config = Scene_Text_Config.new
config.width = 256
config.height = 128
config.verticalAlignment = "center"
config.horizontalAlignment = "center"
config.opacity = 64
variable = Scene_Text.read("Text:", "center", 20, true, config)

# Open a window whose title is "Text:", text is centered, allows
# to enter up to 30 characters, writing is left-to-right,
# window is resized, aligned on the top-right corner and fully transparent
config = Scene_Text_Config.new
config.width = 128
config.height = 256
config.verticalAlignment = "top"
config.horizontalAlignment = "right"
config.opacity = 0
variable = Scene_Text.read("Text:", "center", 30, true, config)

# Open a window whose title is "Text:", text is centered, allows to enter
# up to 20 characters, writing is left-to-right, window is partially
# transparent
config = Scene_Text_Config.new
config.opacity = 160
variable = Scene_Text.read("Text:", "center", 20, true, config)



Script

Code:
#==============================================================================
# ** Text Input script
#------------------------------------------------------------------------------
# author:  erpicci
# version: 1.1
# require: CP Keyboard Input script by Neon Black
#
#------------------------------------------------------------------------------
# * Introduction
#------------------------------------------------------------------------------
# This script allows the player to insert a medium-sized text by typing
# directly from the keyboard. Inserted text is returned as a string.
#
# Requires Neon Black's Keyboard Input Script to work.
#
# It is completely free, both for commercial and non-commercial use. All you
# are asked to do is to give me credits for the script.
#
#------------------------------------------------------------------------------
# * Installation
#------------------------------------------------------------------------------
# Be sure to have Neon Black's Keyboard Input Script installed.
# Place this script in the "Materials" section of the scripts above main.
#
# To insert a text using an event, create a script event like:
#   text_var = text_input("Window Title")
#
# To have a script call the text input, use:
#   text_var = Scene_Text.read("Window Title")
#
# Only window title is mandatory. As optional arguments, you can set:
#  * alignment: "center" (default), "left", "right"
#  * maximum number of character: default is 104
#  * left-to-right: default is true, use false to get a right-to-left input
#  * configuration object (see examples)
#
#------------------------------------------------------------------------------
# * Changelog and notes
#------------------------------------------------------------------------------
# -1.1:   Fixed a memoty leak
#
# -1.1rc: Added options to manipulate the text edit window (position, size,
#         opacity); manipulation is obtained through the new Scene_Text_Config
#         class. Backward compatibile.
#
#------------------------------------------------------------------------------
# * Examples
#------------------------------------------------------------------------------
#   # Open a window whose title is "Talk to Bobby", text is centered, allows
#   # to enter up to 20 characters, writing is right-to-left
#   variable = Scene_Text.read("Talk to Bobby", "center", 20, false)
#
#   # Open a window whose title is "Tell me something", text is aligned to
#   # right, allows to enter up to 88 characters, writing is left-to-right
#   # (default)
#   variable = Scene_Text.read("Talk to Bobby", "center", 20)
#
#   # Open a window whose title is "Insert text", text is centered (default),
#   # accepts up to 104 characters (default), writing is left-to-right (default)
#   variable = Scene_Text.read("Talk to Bobby")
#
#   # Open a window whose title is "Text:", text is centered, allows
#   # to enter up to 20 characters, writing is right-to-left,
#   # window is resized, centered in the screen and semi-transparent
#   config = Scene_Text_Config.new
#   config.width = 256
#   config.height = 128
#   config.verticalAlignment = "center"
#   config.horizontalAlignment = "center"
#   config.opacity = 64
#   variable = Scene_Text.read("Text:", "center", 20, true, config)
#
#   # Open a window whose title is "Text:", text is centered, allows
#   # to enter up to 30 characters, writing is right-to-left,
#   # window is resized, aligned on the top-right corner and fully transparent
#   config = Scene_Text_Config.new
#   config.width = 128
#   config.height = 256
#   config.verticalAlignment = "top"
#   config.horizontalAlignment = "right"
#   config.opacity = 0
#   variable = Scene_Text.read("Text:", "center", 30, true, config)
#
#   # Open a window whose title is "Text:", text is centered, allows to enter
#   # up to 20 characters, writing is left-to-right, window is partially
#   # transparent
#   # config = Scene_Text_Config.new
#   # config.opacity = 128
#   # variable = Scene_Text.read("Text:", "center", 20, true, config)
#==============================================================================
 
module Text_Input
  ACCEPTED_KEYS = {
    :k0 => 48, :k1 => 49, :k2 => 50, :k3 => 51, :k4 => 52,
    :k5 => 53, :k6 => 54, :k7 => 55, :k8 => 56, :k9 => 57,
   
    :kA => 65, :kB => 66, :kC => 67, :kD => 68, :kE => 69, :kF => 70,
    :kG => 71, :kH => 72, :kI => 73, :kJ => 74, :kK => 75, :kL => 76,
    :kM => 77, :kN => 78, :kO => 79, :kP => 80, :kQ => 81, :kR => 82,
    :kS => 83, :kT => 84, :kU => 85, :kV => 86, :kW => 87, :kX => 88,
    :kY => 89, :kZ => 90,
   
    :kCOLON     => 186, :kQUOTE     => 222, :kSPACE      => 32,
    :kCOMMA     => 188, :kPERIOD    => 190, :kSLASH      => 191,
    :kBACKSLASH => 220, :kLEFTBRACE => 219, :kRIGHTBRACE => 221,
    :kMINUS     => 189, :kEQUAL     => 187, :kTILDE      => 192,          
  }
end
 
 
 
#==============================================================================
# ** Scebe_Text_Config
#------------------------------------------------------------------------------
#  This object contains additional configuration for the text edit window
#==============================================================================
 
class Scene_Text_Config
  attr_accessor :lines
  attr_accessor :x
  attr_accessor :y
  attr_accessor :width
  attr_accessor :height
  attr_accessor :opacity
 
  #--------------------------------------------------------------------------
  # * Object Initialization: set default values
  #--------------------------------------------------------------------------
  def initialize
    @window  = nil
    @lines   = 6
    @x       = 0
    @y       = Graphics.height - window.fitting_height(lines)
    @width   = Graphics.width
    @height  = window.fitting_height(lines)
    @opacity = 256
    window.dispose
  end
  #--------------------------------------------------------------------------
  # * Access to Properties of Windows
  #--------------------------------------------------------------------------
  def window
    if (@window.nil?)
      @window = Window_Base.new(0, 0, 0, 0)
    end
    @window
  end
  #--------------------------------------------------------------------------
  # * Sets Horizontal Alignment
  #--------------------------------------------------------------------------
  def horizontalAlignment=(position = "center")
    if (position == "left")
      @x = 0
    elsif (position == "right")
      @x = Graphics.width - @width
    else
      @x = (Graphics.width - @width) / 2
    end
  end
  #--------------------------------------------------------------------------
  # * Sets Vertical Alignment
  #--------------------------------------------------------------------------
  def verticalAlignment=(position = "bottom")
    if (position == "top")
      @y = 0
    elsif (position == "center")
      @y = (Graphics.height - @height) / 2
    else
      @y = Graphics.height - @height
    end
  end
end
 
 
 
#==============================================================================
# ** Scene_Text
#------------------------------------------------------------------------------
#  This class shows an input field for the player.
#==============================================================================
 
class Scene_Text < Scene_MenuBase
  ALIGN    = "center"
  MAX_CHAR = 104
  LTR      = true
 
  #--------------------------------------------------------------------------
  # * Show a dialog window to the player
  #--------------------------------------------------------------------------
  def self.read(title, align = ALIGN, max_char = MAX_CHAR, ltr = LTR, opts = nil)
    @@text     = ""
    @@title    = title
    @@align    = align
    @@max_char = max_char
    @@ltr      = ltr
    @@opts     = opts.nil? ? Scene_Text_Config.new : opts
    SceneManager.call(Scene_Text)
    Fiber.yield while SceneManager.scene_is?(Scene_Text)
    return @@text
  end
  #--------------------------------------------------------------------------
  # * Start Processing
  #--------------------------------------------------------------------------
  def start
    super
    @edit_window  = Window_TextEdit.new(@@title, @@align, @@max_char, @@ltr,
      @@opts)
    @edit_window.set_handler(:ok, method(:on_input_ok))
  end
  #--------------------------------------------------------------------------
  # * Set text when done
  #--------------------------------------------------------------------------
  def on_input_ok
    @@text = @edit_window.text
    @@opts.window.dispose
    return_scene
  end
end
 
 
 
#==============================================================================
# ** Window_TextEdit
#------------------------------------------------------------------------------
#  This window allows to edit a text.
#==============================================================================
 
class Window_TextEdit < Window_Selectable
  include Text_Input
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :text
 
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize(title, align = "center", max_char = 104, ltr = true, opts = nil)
    opts = opts.nil? ? Scene_Text_Config.new : opts
    super(opts.x, opts.y, opts.width, opts.height)
    self.opacity = opts.opacity
   
    @text     = ""
    @title    = title
    @align    = align
    @max_char = max_char
    @ltr      = ltr
    @opts     = opts
    @index    = @text.size
    activate
    refresh
  end
  #--------------------------------------------------------------------------
  # * Revert to Default Text
  #--------------------------------------------------------------------------
  def restore_default
    @text = ""
    @index = @text.size
    refresh
    return !@text.empty?
  end
  #--------------------------------------------------------------------------
  # * Get Character Width
  #--------------------------------------------------------------------------
  def char_width
    text_size($game_system.japanese? ? "‚ " : "A").width
  end
  #--------------------------------------------------------------------------
  # * Get Number of Columns
  #--------------------------------------------------------------------------
  def max_col
    [(@opts.width - 32) / char_width, @max_char].min
  end
  #--------------------------------------------------------------------------
  # * Get Left Padding
  #--------------------------------------------------------------------------
  def left(n)
    return 10                                if @align == "left"
    return (width - 32 - n * char_width)     if @align == "right"
    return (width - 32 - n * char_width) / 2 # if align == "center"
  end
  #--------------------------------------------------------------------------
  # * Get Rectangle for Displaying Item
  #--------------------------------------------------------------------------
  def item_rect(index)
    index -= 1 if index == @max_char
    x = index % max_col
    y = index / max_col
    n = [(@max_char - y * max_col), max_col].min
   
    x = left(n) + x * char_width
    x = width   - x - 48 if not @ltr
    y = 24      + y * (line_height + 4)
    Rect.new(x, y, char_width, line_height)
  end
  #--------------------------------------------------------------------------
  # * Get Underline Rectangle
  #--------------------------------------------------------------------------
  def underline_rect(index)
    rect = item_rect(index)
    rect.x += 1
    rect.y += rect.height
    rect.width -= 2
    rect.height = 2
    rect
  end
  #--------------------------------------------------------------------------
  # * Get Underline Color
  #--------------------------------------------------------------------------
  def underline_color
    color = normal_color
    color.alpha = 48
    color
  end
  #--------------------------------------------------------------------------
  # * Draw Underline
  #--------------------------------------------------------------------------
  def draw_underline(index)
    contents.fill_rect(underline_rect(index), underline_color)
  end
  #--------------------------------------------------------------------------
  # * Draw Text
  #--------------------------------------------------------------------------
  def draw_char(index)
    rect       = item_rect(index)
    rect.x     += 4
    rect.width += 4
    change_color(normal_color)
    draw_text(rect, @text[index] || "")
  end
  #--------------------------------------------------------------------------
  # * Draw Title
  #--------------------------------------------------------------------------
  def draw_title
    draw_text(0, 0, self.width, line_height, @title, 1)
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    draw_title
    @text.size.times {|i| draw_char(i) }
    @max_char.times  {|i| draw_underline(i) }
    cursor_rect.set(item_rect(@index))
  end
  #--------------------------------------------------------------------------
  # * Handle Process
  #--------------------------------------------------------------------------
  def process_handling
    return unless open? && active
    process_delete if Input.repeat?(:kBACKSPACE)
    process_abort  if Input.trigger?(:kESC)
    process_ok     if Input.trigger?(:kENTER)
    process_keyboard
  end
  #--------------------------------------------------------------------------
  # * Check Input From Keyboard
  #--------------------------------------------------------------------------
  def process_keyboard
    ACCEPTED_KEYS.each {|key|
      if Input.repeat?(key[0])
        c = (key[0] != :kSPACE) ? Keyboard.add_char(Ascii::SYM[key[0]]) : " "
        process_add(c)
        Sound.play_ok
      end
    }
  end
  #--------------------------------------------------------------------------
  # * Add One Character
  #--------------------------------------------------------------------------
  def process_add(c)
    return if @index > @max_char
    if @index == @max_char
      @text[@index - 1] = c
    else
      @text  += c
      @index += 1
    end
    refresh
  end
  #--------------------------------------------------------------------------
  # * Delete One Character
  #--------------------------------------------------------------------------
  def process_delete
    return if @index == 0
    @index -= 1
    @text  = @text[0, @index]
    Sound.play_cancel
    refresh
  end
  #--------------------------------------------------------------------------
  # * Abort Text Input
  #--------------------------------------------------------------------------
  def process_abort
    restore_default
    Sound.play_cancel
    call_ok_handler
  end
  #--------------------------------------------------------------------------
  # * Complete Text Input
  #--------------------------------------------------------------------------
  def process_ok
    Sound.play_ok
    call_ok_handler
  end
end
 
 
 
 
 
#==============================================================================
# ** Game_Interpreter
#------------------------------------------------------------------------------
#  An interpreter for executing event commands. This class is used within the
# Game_Map, Game_Troop, and Game_Event classes.
#==============================================================================
 
class Game_Interpreter
  #--------------------------------------------------------------------------
  # * Insert a text
  #--------------------------------------------------------------------------
  def text_input(title, align = "center", max_char = 103, ltr = true, opts = nil)
    Scene_Text.read(title, align, max_char, ltr, opts)
  end
end

This script is also available on PasteBin: http://pastebin.com/dh16PCaj.


Changelog:

  • 1.1 [http://pastebin.com/HST0A6bJ] Fixed a memory leak: windows did not get properly disposed. Backward compatible.
  • 1.1rc [http://pastebin.com/dh16PCaj] Added options to manipulate the text edit window (position, size, opacity); manipulation is obtained through the new Scene_Text_Config class. Backward compatibile. Activating the scene with no additional config object falls back to previous version.
  • 1.0 [http://pastebin.com/TYtbDDPy] Initial release.



FAQ


Q: How do I store the inserted text into a game variable?


A: See this comment.


Q: How do I insert newlines?


A: This is currently not supported. A workaround is explained in this comment.


Q: How do I check inserted text to prepare a response?


A: You can use the script to store inserted text into a variable, then you can perform any check you like. For an example, see this comment.


Q: How can I change windows size, position and opacity?


A: Be sure to have version 1.1rc (or later) installed, then check examples in this page.




Credit and Thanks
- erpicci, author
- Neon Black, for his Keyboard Input Script
- Tsukihime, for his Simple Text Input script, which I studied to make my own


Sixth, for spotting a memory leak in version <1.1 and suggesting how to fix
 
Last edited by a moderator:

LeoHalliwell

Villager
Member
Joined
Jan 12, 2014
Messages
27
Reaction score
3
First Language
English
Primarily Uses
Okay, so I got the basics of the script down, and I totally love it! But how would I be able to consistently recall the text that was input either as a variable or some other thing like that? I want to be able to input the text, and have the player view that elsewhere, outside of that one event. 
 

LeoHalliwell

Villager
Member
Joined
Jan 12, 2014
Messages
27
Reaction score
3
First Language
English
Primarily Uses
Nevermind! I figured it out! All I had to do was put the script inside "Control Variables" and I was able to recall the text in another location! 
 

erpicci

Villager
Member
Joined
Feb 3, 2015
Messages
29
Reaction score
21
First Language
Italian
Primarily Uses
Glad you found this script usefull.


About your problem, although you already found a solution, it is worth saying that the easiest way to store a text into a variable is with:


# This will put inserted text into variable 1
$game_variables[1] = Scene_Text.read("Tell me something")


which will store inserted text into variable 1. You can later display that content in a regular text box with \V[1].


Hope that helps :)
 
Last edited by a moderator:

c0rp53

Villager
Member
Joined
Dec 4, 2015
Messages
5
Reaction score
0
First Language
Spanish
Primarily Uses
While displaying the stored text in a regular text box, I can't get it to use multilines so it display the whole thing and not everything in a line with the 32 char limit. Is there a solution? Thanks in advance!
 

erpicci

Villager
Member
Joined
Feb 3, 2015
Messages
29
Reaction score
21
First Language
Italian
Primarily Uses
Hello!

Currently it is not possibile: text is displayed "as it is", so if no newline character is inserted, no newlines are created.

A workaround is to insert a dummy character where you want a newline and have a script replace that character with a newline:

variable = Scene_Text.read("Tell me something").gsub("*", "\n")In this case a new line is started every time a * (star) appears in the string.

I haven't found a way to handle multi-lines which would satisfy everybody. If yuo have specific needs, PM me and I can modify the script for you based on your needs. :cutesmile:
 

Oatilis

Veteran
Veteran
Joined
Mar 16, 2016
Messages
49
Reaction score
25
First Language
Hebrew
Primarily Uses
Would you kindly add a pastebin / dropbox link?


The hidden quoted script is all messed up and the lines are jambled.
 

erpicci

Villager
Member
Joined
Feb 3, 2015
Messages
29
Reaction score
21
First Language
Italian
Primarily Uses
Thanks for reporting this issue.


I don't know how the code became so messed-up, it looks like all newline characters simply vanished.


As soon as I find the original script on my computer, I'll upload it with proper formatting.
 

Oatilis

Veteran
Veteran
Joined
Mar 16, 2016
Messages
49
Reaction score
25
First Language
Hebrew
Primarily Uses
Thanks for reporting this issue.


I don't know how the code became so messed-up, it looks like all newline characters simply vanished.


As soon as I find the original script on my computer, I'll upload it with proper formatting.

No problem! I'll be waiting! :)


Tried to just add the new lines back manually. It's a pain.
 

erpicci

Villager
Member
Joined
Feb 3, 2015
Messages
29
Reaction score
21
First Language
Italian
Primarily Uses
Thanks for waiting,


I updated the original post with the properly formatted code. I also added a link to pastebin.


Hope you'll find the script useful  :) !
 

Oatilis

Veteran
Veteran
Joined
Mar 16, 2016
Messages
49
Reaction score
25
First Language
Hebrew
Primarily Uses
I can confirm it's all good now. Works like a charm.


Thanks!
 

Newbie

Villager
Member
Joined
Mar 26, 2016
Messages
11
Reaction score
0
First Language
Indonesian
Primarily Uses
thanks a loot dude


this is the main script in my project
 

erpicci

Villager
Member
Joined
Feb 3, 2015
Messages
29
Reaction score
21
First Language
Italian
Primarily Uses
Thank you for using and enjoying this script  :) !
 

RavenBlueIndigo

Veteran
Veteran
Joined
May 3, 2012
Messages
136
Reaction score
281
Primarily Uses
Is there a way to check what you input in a conditional branch? Like, let's say I input "Who are you?", and then because I put that, I get a response.
 

erpicci

Villager
Member
Joined
Feb 3, 2015
Messages
29
Reaction score
21
First Language
Italian
Primarily Uses
Hello,


yes, this is possible. You can have a script call my text input and store the result in a variable, then you can check the inserted text, for example with conditional branches.


The code would result in something like:


text = Scene_Text.read("Window Title")

if text == "Who are you?"
answer = "I am a Ruby Script"
elsif text == "How are you?"
answer = "I'm fine, thanks!"
else
answer = "I don't understand"
end

# Print your answer


( I haven't been programming in Ruby for a while, so please check that for possible syntax errors.)


You may improve it by performing case insensitive matches, or deploying artificial intelligence techniques such as topic recognition. It really depends on what you need  :) .
 
Last edited by a moderator:

RavenBlueIndigo

Veteran
Veteran
Joined
May 3, 2012
Messages
136
Reaction score
281
Primarily Uses
Mn, but how do I do case insensitive matches? I know you can do it with dummy names by doing $game_actors[2].name.upcase == "" , but with this I've no idea.
 

Sixth

Veteran
Veteran
Joined
Jul 4, 2014
Messages
2,201
Reaction score
862
First Language
Hungarian
Primarily Uses
RMVXA
You do it the same way you described, just call upcase or downcase on the entered text before you compare them.
 

RavenBlueIndigo

Veteran
Veteran
Joined
May 3, 2012
Messages
136
Reaction score
281
Primarily Uses
Hmm. I must be doing something wrong. I put in a script call of "$game_variables[50].upcase", didn't work.
 

Sixth

Veteran
Veteran
Joined
Jul 4, 2014
Messages
2,201
Reaction score
862
First Language
Hungarian
Primarily Uses
RMVXA
That will return a new string with only upper case letters, but without actually storing it, it does nothing.


$game_variables[50] = $game_variables[50].upcase


This will store the modified text, but it is really not needed to do this.


In the conditional branch command, use the "Script" option with this code:


$game_variables[50].downcase == "lowercase answer goes here"


Set that right part to any string you want, but use only lowercase letters. I always use lowercase for checks, because who likes to toggle caps lock or holding shift all the time while typing the answers, right? :p
 

RavenBlueIndigo

Veteran
Veteran
Joined
May 3, 2012
Messages
136
Reaction score
281
Primarily Uses
Thanks! It worked! :D. My only qualm with the script is that there is no way to make the window background transparent, lol.
 

Latest Threads

Latest Posts

Latest Profile Posts

Update on the Unity thing: I had to redo all my map graphics for Unity because the originals were from XP, but it actually looks so much better now in Unity, so I genuinely might make the switch.
Messing around with fragment shaders (filters). This thing is HUGE and I'm surprised almost no one makes good use of. Even the number of plugins that do this stuff are limited.
ScreenShot_6_28_2022_3_2_40.png

There's 7 main areas in the game that are all connected. This train get's you from an underground lab to the center of someone's subconscious. inside the train you can talk to some of the passengers. but going to the top of it, there's battles.
Speedrunning all character portraits just so they all have the same quality. Not sure if this was a good idea, but now I'm almost done.
We now have a gameplay video!

Forum statistics

Threads
123,154
Messages
1,154,460
Members
161,505
Latest member
ashaki01
Top