Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extends Control
- tool
- const CALLBACK_CHAR = '@'
- # Signal triggered when a callback is found
- signal callback_signal(callback)
- # Text display properties
- export(String, MULTILINE) var text setget set_text
- #export(int, "Left","Center","Right") var align
- #export(int, "Top","Center","Bottom") var valign
- export(int) var visible_characters = -1 setget set_visible_characters
- export(Resource) var font setget set_font
- export(Color) var default_color = Color.white setget set_default_text_color
- export(bool) var animate_text = true
- # Text display variables
- var parsed_text : String # The text to display, without any fancy formatting included
- var formatting_data : Dictionary # Dictionary holding formatting data for the string. Keys are string indices and values are arrays of formatting things to apply
- var callback_data : Dictionary # Dictionary holding callback data for the string
- var anim_time : float
- # Handle text animation
- func _process(delta:float) -> void:
- if animate_text:
- anim_time += delta
- update()
- # Set the text to display and generate the formatting necessary to display it
- func set_text(txt:String) -> void:
- text = txt
- parsed_text = ""
- formatting_data.clear()
- # Initialize counters
- var i = 0
- var j = 0
- var k = 0
- var bracket_count = 0
- while i < text.length():
- # If we have found an opening bracket
- if text[i] == '[':
- # Find a matching bracket
- bracket_count = 1
- j = i
- while bracket_count > 0:
- j += 1
- if j >= text.length():
- break
- # Check for brackets
- if text[j] == '[':
- bracket_count += 1
- elif text[j] == ']':
- bracket_count -= 1
- # If we found a bracket pair, add it's contents to our formatting data and save it
- if bracket_count == 0:
- # Save whatever we found to the dictionary
- var label = text.substr(i+1,j-i-1)
- if !formatting_data.has(k):
- formatting_data[k] = []
- formatting_data[k].append(label)
- # Continue
- i = j
- else:
- # Otherwise ignore it entierly and add the opening bracket to the string
- parsed_text += '['
- k += 1
- else:
- # Just add the text
- parsed_text += text[i]
- k += 1
- # Increment counter
- i += 1
- update()
- func set_visible_characters(count:int) -> void:
- # Check for a callback present. We only trigger callbacks when advancing text
- if count != -1 and count > visible_characters and formatting_data.has(count):
- for item in formatting_data[count]:
- if item[0] == CALLBACK_CHAR: # Check for the appropriate callback character
- emit_signal("callback_signal",item)
- print("Callback " + item + " triggered")
- # Update number of visible character
- visible_characters = clamp(count,-1,parsed_text.length())
- update()
- func set_font(fnt:Font) -> void:
- font = fnt
- update()
- func set_default_text_color(color:Color) -> void:
- default_color = color
- update()
- # Actually draw the text
- func _draw() -> void:
- # Where are we drawing this text?
- var cursor = Vector2(0,font.get_height())
- var char_size = Vector2() # Character width
- # The effect stack holds all effects currently in progress
- # The key is the actual string contained in the brackets, while the value is the value specified, if any
- # If a value isn't present, the value is just set to null
- # i.e. [color=white][b] would store {color:white,b:null}
- var effect_stack = {}
- # Determine number of characters to show based on 'visible characters' parameter
- var count = visible_characters
- if count == -1: count = parsed_text.length()
- # Loop over characters
- for i in range(count):
- # Determine character properties
- char_size = font.get_char_size(ord(parsed_text[i]))
- var do_newline = cursor.x+char_size.x > rect_size.x or parsed_text[i] == '\n'
- # Should we insert a newline?
- if do_newline:
- cursor.x = 0
- cursor.y += font.get_height()
- # Get formatting codes associated with this spot in text, if any
- if formatting_data.has(i):
- for item in formatting_data[i]:
- # Ignore callbacks
- if item[0] == '@': continue
- # Check if the item has an escape character
- if item[0] == '/':
- # Remove from effect stack
- var key = item.right(item.length()-1)
- effect_stack.erase(key)
- else:
- # Check for a value
- var eq = item.find('=')
- if eq == -1:
- # Just add the item to the effect stack
- effect_stack[item] = null
- else:
- # Add the identifier and value to the effect stack
- effect_stack[item.substr(0,eq)] = item.substr(eq+1,item.length()-eq)
- var color = default_color
- var offset = Vector2.ZERO
- var result = []
- # Loop over effect stack and apply modifiers
- for item in effect_stack:
- if has_method("effect_"+item):
- result = call("effect_"+item,offset,color,i,effect_stack[item])
- offset = result[0]
- color = result[1]
- # Actually draw the text
- draw_string(font,cursor+offset,parsed_text[i],color)
- #if not do_newline:
- cursor.x += char_size.x
- #--[Define Text Effect Functions]--
- func effect_c(offset:Vector2,color:Color,index:int,value) -> Array: # Change color
- if value[0] == '#':
- return [offset,Color(value)]
- else:
- return [offset,ColorN(value)]
- func effect_w(offset:Vector2,color:Color,index:int,value) -> Array: # Wavy text
- var scale = 1
- if value != null:
- scale = float(value)
- return [offset+Vector2(0,sin(index+anim_time*9)*scale),color]
- func effect_j(offset:Vector2,color:Color,index:int,value) -> Array: # Jittery text
- var scale = 0.5
- if value != null:
- scale = float(value)
- return [offset+Vector2(rand_range(-scale,scale),rand_range(-scale,scale)),color]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement