Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # ===================================================================
- #
- # Script: Component_MessageTextRenderer
- #
- # $$COPYRIGHT$$
- #
- # ===================================================================
- class Component_MessageTextRenderer extends gs.Component_TextRenderer
- @objectCodecBlackList = ["onLinkClick", "onBatchDisappear"]
- ###*
- * Called if this object instance is restored from a data-bundle. It can be used
- * re-assign event-handler, anonymous functions, etc.
- *
- * @method onDataBundleRestore.
- * @param Object data - The data-bundle
- * @param gs.ObjectCodecContext context - The codec-context.
- ###
- onDataBundleRestore: (data, context) ->
- @setupEventHandlers()
- l = 0
- lastLine = null
- for message in @object.messages
- if @object.settings.useCharacterColor
- @object.font.color = new gs.Color(message.character.textColor)
- lineWidth = if @isRunningInMultiPartMode() then lastLine?.width || 0 else 0
- @lines = @calculateLines(lcsm(message.text), yes, lineWidth)
- for line in @lines
- bitmap = @createBitmap(line)
- if line == @line
- @drawLineContent(line, bitmap, @charIndex+1)
- else
- @drawLineContent(line, bitmap, -1)
- @allSprites[l].bitmap = bitmap
- lastLine = line
- l++
- for customObject in @customObjects
- SceneManager.scene.addObject(customObject)
- return null
- ###*
- * A text-renderer component to render an animated and interactive message text using
- * dimensions of the game object's destination-rectangle. The message is displayed
- * using a sprite for each line instead of drawing to the game object's bitmap object.
- *
- * @module gs
- * @class Component_MessageTextRenderer
- * @extends gs.Component_TextRenderer
- * @memberof gs
- * @constructor
- ###
- constructor: ->
- super
- ###*
- * An array containing all sprites of the current message.
- * @property sprites
- * @type gs.Sprite[]
- * @protected
- ###
- @sprites = []
- ###*
- * An array containing all sprites of all messages. In NVL mode
- * a page can contain multiple messages.
- * @property allSprites
- * @type gs.Sprite[]
- * @protected
- ###
- @allSprites = []
- ###*
- * An array containing all line-objects of the current message.
- * @property lines
- * @type gs.TextRendererLine[]
- * @readOnly
- ###
- @lines = null
- ###*
- * The line currently rendered.
- * @property line
- * @type number
- * @readOnly
- ###
- @line = 0
- ###*
- * The left and right padding per line.
- * @property padding
- * @type number
- ###
- @padding = 6
- ###*
- * The minimum height of the line currently rendered. If 0, the measured
- * height of the line will be used.
- * @property minLineHeight
- * @type number
- ###
- @minLineHeight = 0
- ###*
- * The spacing between text lines in pixels.
- * @property lineSpacing
- * @type number
- ###
- @lineSpacing = 2
- ###*
- * The line currently rendered.
- * @property currentLine
- * @type number
- * @protected
- ###
- @currentLine = 0
- ###*
- * The height of the line currently rendered.
- * @property currentLineHeight
- * @type number
- * @protected
- ###
- @currentLineHeight = 0
- ###*
- * Index of the current character to draw.
- * @property charIndex
- * @type number
- * @readOnly
- ###
- @charIndex = 0
- ###*
- * Position of the message caret. The caret is like an invisible
- * cursor pointing to the x/y coordinates of the last rendered character of
- * the message. That position can be used to display a waiting- or processing-animation for example.
- * @property caretPosition
- * @type gs.Point
- * @readOnly
- ###
- @caretPosition = new gs.Point()
- ###*
- * Indicates that the a message is currently in progress.
- * @property isRunning
- * @type boolean
- * @readOnly
- ###
- @isRunning = no
- ###*
- * The current x-coordinate of the caret/cursor.
- * @property currentX
- * @type number
- * @readOnly
- ###
- @currentX = 0
- ###*
- * The current y-coordinate of the caret/cursor.
- * @property currentY
- * @type number
- * @readOnly
- ###
- @currentY = 0
- ###*
- * The current sprites used to display the current text-line/part.
- * @property currentSprite
- * @type gs.Sprite
- * @readOnly
- ###
- @currentSprite = null
- ###*
- * Indicates if the message-renderer is currently waiting like for a user-action.
- * @property isWaiting
- * @type boolean
- * @readOnly
- ###
- @isWaiting = no
- ###*
- * Indicates if the message-renderer is currently waiting for a key-press or mouse/touch action.
- * @property waitForKey
- * @type boolean
- * @readOnly
- ###
- @waitForKey = no
- ###*
- * Number of frames the message-renderer should wait before continue.
- * @property waitCounter
- * @type number
- ###
- @waitCounter = 0
- ###*
- * Speed of the message-drawing. The smaller the value, the faster the message is displayed.
- * @property speed
- * @type number
- ###
- @speed = 1
- ###*
- * Indicates if the message should be rendered immedialtely without any animation or delay.
- * @property drawImmediately
- * @type boolean
- ###
- @drawImmediately = no
- ###*
- * Indicates if the message should wait for a user-action or a certain amount of time
- * before finishing.
- * @property waitAtEnd
- * @type boolean
- ###
- @waitAtEnd = yes
- ###*
- * The number of frames to wait before finishing a message.
- * before finishing.
- * @property waitAtEndTime
- * @type number
- ###
- @waitAtEndTime = 0
- ###*
- * Indicates if auto word-wrap should be used. Default is <b>true</b>
- * @property wordWrap
- * @type boolean
- ###
- @wordWrap = yes
- ###*
- * Custom game objects which are alive until the current message is erased. Can be used to display
- * animated icons, etc.
- * @property customObjects
- * @type gs.Object_Base[]
- ###
- @customObjects = []
- ###*
- * A hashtable/dictionary object to store custom-data useful like for token-processing. The data must be
- * serializable.
- * @property customObjects
- * @type Object
- ###
- @customData = {}
- ###*
- * A callback function called if the player clicks on a non-stylable link (LK text-code) to trigger
- * the specified common event.
- * @property onLinkClick
- * @type Function
- ###
- @onLinkClick = (e) ->
- eventId = e.data.linkData.commonEventId
- event = RecordManager.commonEvents[eventId]
- if !event
- event = RecordManager.commonEvents.first (x) => x.name == eventId
- eventId = event.index if event
- if !event
- SceneManager.scene.interpreter.jumpToLabel(eventId)
- else
- SceneManager.scene.interpreter.callCommonEvent(eventId, null, yes)
- ###*
- * A callback function called if a batched messsage has been faded out. It triggers the execution of
- * the next message.
- * @property onBatchDisappear
- * @type Function
- ###
- @onBatchDisappear = (e) =>
- @drawImmediately = no
- @isWaiting = no
- @object.opacity = 255
- @executeBatch()
- ###*
- * Serializes the message text-renderer into a data-bundle.
- * @method toDataBundle
- * @return {Object} A data-bundle.
- ###
- toDataBundle: ->
- ignore = ["object", "font", "sprites", "allSprites", "currentSprite", "currentX"]
- bundle = { currentSpriteIndex: @sprites.indexOf(@currentSprite) }
- for k of this
- if ignore.indexOf(k) == -1
- bundle[k] = this[k]
- return bundle
- ###*
- * Disposes the message text-renderer and all sprites used to display
- * the message.
- * @method dispose
- ###
- dispose: ->
- super
- @disposeEventHandlers()
- for sprite in @allSprites
- sprite.bitmap?.dispose()
- sprite.dispose()
- ###*
- * Removes all attached event handlers
- * the message.
- * @method disposeEventHandlers
- ###
- disposeEventHandlers: ->
- gs.GlobalEventManager.offByOwner("mouseUp", @object)
- gs.GlobalEventManager.offByOwner("keyUp", @object)
- ###*
- * Adds event-handlers for mouse/touch events
- *
- * @method setupEventHandlers
- ###
- setupEventHandlers: ->
- gs.GlobalEventManager.offByOwner("mouseUp", @object)
- gs.GlobalEventManager.offByOwner("keyUp", @object)
- gs.GlobalEventManager.on "mouseUp", ((e) =>
- return if @object.findComponentByName("animation") or (GameManager.settings.autoMessage.enabled and !GameManager.settings.autoMessage.stopOnAction)
- return if gs.GameManager.isCatWait();
- #if @object.dstRect.contains(Input.Mouse.x - @object.origin.x, Input.Mouse.y - @object.origin.y)
- if @isWaiting and not (@waitCounter > 0 or @waitForKey)
- e.breakChain = yes
- @continue()
- else
- e.breakChain = @isRunning
- @drawImmediately = !@waitForKey
- @waitCounter = 0
- @waitForKey = no
- @isWaiting = no
- if @waitForKey
- if Input.Mouse.buttons[Input.Mouse.LEFT] == 2
- e.breakChain = yes
- Input.clear()
- @waitForKey = no
- @isWaiting = no
- ), null, @object
- gs.GlobalEventManager.on "keyUp", ((e) =>
- return if gs.GameManager.isCatWait();
- if Input.keys[Input.C] and (!@isWaiting or (@waitCounter > 0 or @waitForKey))
- @drawImmediately = !@waitForKey
- @waitCounter = 0
- @waitForKey = no
- @isWaiting = no
- if @isWaiting and !@waitForKey and !@waitCounter and Input.keys[Input.C]
- @continue()
- if @waitForKey
- if Input.keys[Input.C]
- Input.clear()
- @waitForKey = no
- @isWaiting = no
- ), null, @object
- ###*
- * Sets up the renderer. Registers necessary event handlers.
- * @method setup
- ###
- setup: ->
- @setupEventHandlers()
- ###*
- * Restores the message text-renderer's state from a data-bundle.
- * @method restore
- * @param {Object} bundle - A data-bundle containing message text-renderer state.
- ###
- restore: (bundle) ->
- for k of bundle
- if k == "currentSpriteIndex"
- @currentSprite = @sprites[bundle.currentSpriteIndex]
- else
- this[k] = bundle[k]
- if @sprites.length > 0
- @currentY = @sprites.last().y - @object.origin.y - @object.dstRect.y
- @line = @maxLines
- @isWaiting = @isWaiting || @isRunning
- return null
- ###*
- * Continues message-processing if currently waiting.
- * @method continue
- ###
- continue: ->
- @isWaiting = no
- if @line >= @lines.length
- @isRunning = no
- @object.events?.emit("messageFinish", this)
- else
- @object.events?.emit("messageBatch", this)
- fading = GameManager.tempSettings.messageFading
- duration = if GameManager.tempSettings.skip then 0 else fading.duration
- @object.animator.disappear(fading.animation, fading.easing, duration, gs.CallBack("onBatchDisappear", this))
- ###*
- * Updates the text-renderer.
- * @method update
- ###
- update: ->
- for sprite in @allSprites
- sprite.opacity = @object.opacity
- sprite.visible = @object.visible
- sprite.ox = -@object.offset.x
- sprite.oy = -@object.offset.y
- sprite.mask.value = @object.mask.value
- sprite.mask.vague = @object.mask.vague
- sprite.mask.source = @object.mask.source
- sprite.mask.type = @object.mask.type
- for object in @customObjects
- object.opacity = @object.opacity
- object.visible = @object.visible
- if not @isRunning and @waitCounter > 0 and !gs.GameManager.isCatWait()
- @waitCounter--
- if @waitCounter == 0
- @continue()
- return
- if @object.visible and @lines?.length > 0
- @updateLineWriting()
- @updateWaitForKey()
- @updateWaitCounter()
- @updateCaretPosition()
- ###*
- * Indicates if its a batched messages.
- *
- * @method isBatched
- * @return If <b>true</b> it is a batched message. Otherwise <b>false</b>.
- ###
- isBatched: -> @lines.length > @maxLines
- ###*
- * Indicates if the batch is still in progress and not done.
- *
- * @method isBatchInProgress
- * @return If <b>true</b> the batched message is still not done. Otherwise <b>false</b>
- ###
- isBatchInProgress: -> @lines.length - @line > @maxLines
- ###*
- * Indicates if the renderer runs in multi-part message mode which
- * means that a single message might be constructed from multiple drawFormattedText
- * calls.
- *
- * @method isRunningInMultiPartMode
- * @return If <b>true</b> the renderer runs in multi-part mode. Otherwise <b>false</b>.
- ###
- isRunningInMultiPartMode: -> !@object.settings.autoErase and @object.settings.paragraphSpacing <= 0
- ###*
- * Starts displaying the next page of text if a message is too long to fit
- * into one message box.
- *
- * @method executeBatch
- ###
- executeBatch: ->
- @clearAllSprites()
- @lines = @lines.slice(@line)
- @line = 0
- @currentX = 0
- @currentY = 0
- @currentLineHeight = 0
- @tokenIndex = 0
- @charIndex = 0
- @token = @lines[@line].content[@tokenIndex] || new gs.RendererToken(null, "");
- @maxLines = @calculateMaxLines(@lines)
- @lineAnimationCount = @speed
- @sprites = @createSprites(@lines)
- @allSprites = @allSprites.concat(@sprites)
- @currentSprite = @sprites[@line]
- @currentSprite.x = @currentX + @object.origin.x + @object.dstRect.x
- @drawNext()
- ###*
- * Calculates the duration(in frames) the message-renderer needs to display
- * the message.
- *
- * @method calculateDuration
- * @return {number} The duration in frames.
- ###
- calculateDuration: ->
- duration = 0
- if @lines?
- for line in @lines
- for token in line.content
- if token?
- duration += @calculateDurationForToken(token)
- return duration
- ###*
- * Calculates the duration(in frames) the message-renderer needs to display
- * the specified line.
- *
- * @method calculateDurationForLine
- * @param {gs.RendererTextLine} line The line to calculate the duration for.
- * @return {number} The duration in frames.
- ###
- calculateDurationForLine: (line) ->
- duration = 0
- if line
- for token in line.content
- if token?
- duration += @calculateDurationForToken(token)
- return duration
- ###*
- * Calculates the duration(in frames) the message-renderer needs to process
- * the specified token.
- *
- * @method calculateDurationForToken
- * @param {string|Object} token - The token.
- * @return {number} The duration in frames.
- ###
- calculateDurationForToken: (token) ->
- duration = 0
- if token.code?
- switch token.code
- when "W"
- if token.value != "A"
- duration = token.value / 1000 * Graphics.frameRate
- else
- duration = token.value.length * @speed
- return duration
- ###*
- * Calculates the maximum of lines which can be displayed in one message.
- *
- * @method calculateMaxLines
- * @param {Array} lines - An array of line-objects.
- * @return {number} The number of displayable lines.
- ###
- calculateMaxLines: (lines) ->
- height = 0
- result = 0
- for line in lines
- height += line.height + @lineSpacing
- if @currentY+height > (@object.dstRect.height)
- break
- result++
- return Math.min(lines.length, result || 1)
- ###*
- * Displays the character or processes the next control-token.
- *
- * @method drawNext
- ###
- drawNext: ->
- token = @processToken()
- if token?.value.length > 0
- @char = @token.value.charAt(@charIndex)
- size = @font.measureTextPlain(@char)
- lineSpacing = @lineSpacing
- if @currentLine != @line
- @currentLine = @line
- # @currentY += @currentLineHeight + lineSpacing * Graphics.scale
- @currentLineHeight = 0
- @currentSprite.y = @object.origin.y + @object.dstRect.y + @currentY
- @currentSprite.visible = yes
- @drawLineContent(@lines[@line], @currentSprite.bitmap, @charIndex+1)
- @currentSprite.srcRect.width = @currentSprite.bitmap.width #Math.min(@currentSprite.srcRect.width + size.width, @currentSprite.bitmap.width)
- @currentLineHeight = @lines[@line].height
- @currentX = Math.min(@lines[@line].width, @currentX + size.width)
- ###*
- * Processes the next character/token of the message.
- * @method nextChar
- * @private
- ###
- nextChar: ->
- loop
- @charIndex++
- @lineAnimationCount = @speed
- if @token.code? or @charIndex >= @token.value.length
- @token.onEnd?()
- @tokenIndex++
- if @tokenIndex >= @lines[@line].content.length
- @tokenIndex = 0
- @line++
- @currentSprite.srcRect.width = @currentSprite.bitmap.width
- @currentSprite = @sprites[@line]
- if @currentSprite?
- @currentSprite.x = @object.origin.x + @object.dstRect.x
- if @line < @maxLines
- @currentY += (@currentLineHeight || @font.lineHeight) + @lineSpacing * Graphics.scale
- @charIndex = 0
- @currentX = 0
- @token = @lines[@line].content[@tokenIndex] || new gs.RendererToken(null, "")
- else
- @charIndex = 0
- @token = @lines[@line].content[@tokenIndex] || new gs.RendererToken(null, "")
- @token.onStart?()
- if !@token or @token.value != "\n" or !@lines[@line]
- break
- ###*
- * Finishes the message. Depending on the message configuration, the
- * message text-renderer will now wait for a user-action or a certain amount
- * of time.
- *
- * @method finish
- ###
- finish: ->
- if @waitAtEnd
- @isWaiting = yes
- @object.events?.emit("messageWaiting", this)
- else if @waitAtEndTime > 0
- @waitCounter = @waitAtEndTime
- @isWaiting = no
- @object.events?.emit("messageWaiting", this)
- else
- @object.events?.emit("messageWaiting", this)
- @continue()
- ###*
- * Returns the position of the caret in pixels. The caret is like an invisible
- * cursor pointing to the x/y coordinates of the last rendered character of
- * the message. That position can be used to display a waiting- or processing-animation for example.
- *
- * @method updateCaretPosition
- ###
- updateCaretPosition: ->
- @caretPosition.x = @currentX + @padding
- @caretPosition.y = @currentY + @currentLineHeight/2
- ###*
- * Updates the line writing.
- *
- * @method updateLineWriting
- * @private
- ###
- updateLineWriting: ->
- if @isRunning and !@isWaiting and !@waitForKey and @waitCounter <= 0
- if @lineAnimationCount <= 0
- loop
- if @line < @maxLines
- @nextChar()
- if @line >= @maxLines
- @finish()
- else
- @drawNext()
- break unless (@token.code or @lineAnimationCount <= 0 or @drawImmediately) and !@waitForKey and @waitCounter <= 0 and @isRunning and @line < @maxLines
- if GameManager.tempSettings.skip
- @lineAnimationCount = 0
- else
- @lineAnimationCount--
- ###*
- * Updates wait-for-key state. If skipping is enabled, the text renderer will
- * not wait for key press.
- *
- * @method updateWaitForKey
- * @private
- ###
- updateWaitForKey: ->
- if @waitForKey
- @isWaiting = !GameManager.tempSettings.skip
- @waitForKey = @isWaiting
- ###*
- * Updates wait counter if the text renderer is waiting for a certain amount of time to pass. If skipping is enabled, the text renderer will
- * not wait for the actual amount of time and sets the wait-counter to 1 frame instead.
- *
- * @method updateWaitForKey
- * @private
- ###
- updateWaitCounter: ->
- if @waitCounter > 0 and not gs.GameManager.isCatWait()
- if GameManager.tempSettings.skip
- @waitCounter = 1
- @isWaiting = yes
- @waitCounter--
- if @waitCounter <= 0
- @isWaiting = no
- @continue() if @line >= @maxLines
- ###*
- * Creates a token-object for a specified text-code.
- *
- * @method createToken
- * @param {string} code - The code/type of the text-code.
- * @param {string} value - The value of the text-code.
- * @return {Object} The token-object.
- ###
- createToken: (code, value) ->
- tokenObject = null
- switch code
- when "CE"
- data = value.split("/")
- value = data.shift()
- value = if isNaN(value) then value else parseInt(value)
- for i in [0...data]
- if data[i].startsWith('"') and data[i].endsWith('"')
- data[i] = data[i].substring(1, data[i].length-1)
- else
- data[i] = if isNaN(data[i]) then data[i] else parseFloat(data[i])
- tokenObject = { code: code, value: value, values: data }
- else
- tokenObject = super(code, value)
- return tokenObject
- ###*
- * <p>Measures a control-token. If a token produces a visual result like displaying an icon then it must return the size taken by
- * the visual result. If the token has no visual result, <b>null</b> must be returned. This method is called for every token when the message is initialized.</p>
- *
- * <p>This method is not called while the message is running. For that case, see <i>processControlToken</i> method which is called
- * for every token while the message is running.</p>
- *
- * @param {Object} token - A control-token.
- * @return {gs.Size} The size of the area taken by the visual result of the token or <b>null</b> if the token has no visual result.
- * @method analyzeControlToken
- * @protected
- ###
- measureControlToken: (token) -> return super(token)
- ###*
- * <p>Draws the visual result of a token, like an icon for example, to the specified bitmap. This method is called for every token when the message is initialized and the sprites for each
- * text-line are created.</p>
- *
- * <p>This method is not called while the message is running. For that case, see <i>processControlToken</i> method which is called
- * for every token while the message is running.</p>
- *
- * @param {Object} token - A control-token.
- * @param {gs.Bitmap} bitmap - The bitmap used for the current text-line. Can be used to draw something on it like an icon, etc.
- * @param {number} offset - An x-offset for the draw-routine.
- * @param {number} length - Determines how many characters of the token should be drawn. Can be ignored for tokens
- * not drawing any characters.
- * @method drawControlToken
- * @protected
- ###
- drawControlToken: (token, bitmap, offset, length) ->
- switch token.code
- when "RT" # Ruby Text
- super(token, bitmap, offset, length)
- when "SLK" # Stylable Link
- if !token.customData.offsetX?
- token.customData.offsetX = offset
- if @customData.linkData
- linkData = @customData.linkData[@line]
- if linkData then for data in linkData
- @sprites[@line].bitmap.clearRect(data.cx,
- 0,
- data.width,
- data.height)
- ###*
- * Processes a control-token. A control-token is a token which influences
- * the text-rendering like changing the fonts color, size or style. Changes
- * will be automatically applied to the game object's font.
- *
- * For message text-renderer, a few additional control-tokens like
- * speed-change, waiting, etc. needs to be processed here.
- *
- * This method is called for each token while the message is initialized and
- * also while the message is running. See <i>formattingOnly</i> parameter.
- *
- * @param {Object} token - A control-token.
- * @param {boolean} formattingOnly - If <b>true</b> the message is initializing right now and only
- * format-tokens should be processed which is necessary for the message to calculated sizes correctly.
- * @return {Object} A new token which is processed next or <b>null</b>.
- * @method processControlToken
- * @protected
- ###
- processControlToken: (token, formattingOnly) ->
- return super(token) if formattingOnly
- result = null
- switch token.code
- when "CR" # Change Current Character
- character = RecordManager.charactersArray.first (c) -> (c.name.defaultText ? c.name) == token.value
- if character
- SceneManager.scene.currentCharacter = character
- when "CE" # Call Common Event
- params = { "values": token.values }
- @object.events?.emit("callCommonEvent", @object, { commonEventId: token.value, params: params, finish: no, waiting: yes })
- when "X" # Script
- token.value?(@object)
- when "A" # Play Animation
- animation = RecordManager.animationsArray.first (a) -> a.name == token.value
- if !animation
- animation = RecordManager.animations[token.value]
- if animation?.graphic.name?
- bitmap = ResourceManager.getBitmap("Graphics/Pictures/#{animation.graphic.name}")
- object = new gs.Object_Animation(animation)
- @addCustomObject(object)
- @currentX += Math.round(bitmap.width / animation.framesX)
- @currentSprite.srcRect.width += Math.round(bitmap.width / animation.framesX)
- when "RT" # Ruby Text
- if token.rtSize.width > token.rbSize.width
- @currentX += token.rtSize.width
- @font.set(@getRubyTextFont(token))
- else
- @currentX += token.rbSize.width
- when "LK" # Link
- if token.value == 'E' # End Link
- object = new ui.Object_Hotspot()
- object.enabled = yes
- object.setup()
- @addCustomObject(object)
- object.dstRect.x = @object.dstRect.x + @object.origin.x + @customData.linkData.cx
- object.dstRect.y = @object.dstRect.y + @object.origin.y + @customData.linkData.cy
- object.dstRect.width = @currentX - @customData.linkData.cx
- object.dstRect.height = @currentLineHeight
- object.events.on("click", gs.CallBack("onLinkClick", this), linkData: @customData.linkData, this)
- else # Begin Link
- @customData.linkData = { cx: @currentX, cy: @currentY, commonEventId: token.value, tokenIndex: @tokenIndex }
- when "SLK" # Styleable Link
- if token.value == 'E' # End Link
- linkData = @customData.linkData[@line].last()
- line = @lines[@line].content
- linkStart = @findToken(@tokenIndex-1, "SLK", -1, line)
- textTokens = @findTokensBetween(linkData.tokenIndex, @tokenIndex, null, line)
- linkData.cx = linkStart.customData.offsetX
- linkData.width = @currentX - linkData.cx + @padding
- linkData.height = @currentSprite.bitmap.height
- object = new ui.Object_Text()
- object.text = textTokens.select((x) => x.value).join("")
- #object.sizeToFit = yes
- object.formatting = no
- object.wordWrap = no
- object.ui = new ui.Component_UIBehavior()
- object.enabled = yes
- object.addComponent(object.ui)
- object.addComponent(new gs.Component_HotspotBehavior())
- object.behavior.padding.left = 0
- object.behavior.padding.right = 0
- object.dstRect.width = linkData.width
- object.dstRect.height = linkData.height
- if linkData.styleIndex == -1
- ui.UIManager.addControlStyles(object, ["hyperlink"])
- else
- ui.UIManager.addControlStyles(object, ["hyperlink-"+linkData.styleIndex])
- object.setup()
- @addCustomObject(object)
- object.dstRect.x = @currentSprite.x + linkData.cx
- object.dstRect.y = @object.dstRect.y + @object.origin.y + linkData.cy
- object.events.on("click", gs.CallBack("onLinkClick", this), linkData: linkData, this)
- else # Begin Link
- if !@customData.linkData
- @customData.linkData = []
- if !@customData.linkData[@line]
- @customData.linkData[@line] = []
- if token.value?.contains(",")
- values = token.value.split(",")
- @customData.linkData[@line].push({ cx: @currentX, cy: @currentY, commonEventId: values[0], styleIndex: parseInt(values[1]), tokenIndex: @tokenIndex })
- else
- @customData.linkData[@line].push({ cx: @currentY, cy: @currentY, commonEventId: token.value, tokenIndex: @tokenIndex, styleIndex: -1 })
- when "E" # Change Expression
- expression = RecordManager.characterExpressionsArray.first (c) -> (c.name.defaultText ? c.name) == token.value
- if !expression
- expression = RecordManager.characterExpressions[token.value]
- character = SceneManager.scene.currentCharacter
- if expression? and character?.index?
- duration = GameManager.defaults.character.expressionDuration
- easing = gs.Easings.fromObject(GameManager.defaults.character.changeEasing)
- animation = GameManager.defaults.character.changeAnimation
- object = SceneManager.scene.characters.first (c) -> c.rid == character.index
- object?.behavior.changeExpression(expression, animation, easing, duration)
- when "SP" # Play Sound
- sound = RecordManager.system.sounds[token.value-1]
- AudioManager.playSound(sound)
- when "S" # Change Speed
- GameManager.settings.messageSpeed = token.value
- when "W" # Wait
- @drawImmediately = no
- if !GameManager.tempSettings.skip
- if token.value == "A"
- @waitForKey = yes
- else
- @waitCounter = Math.round(token.value / 1000 * Graphics.frameRate)
- when "WE" # Wait at End
- @waitAtEnd = token.value == "Y"
- when "DI" # Draw Immedialty
- @drawImmediately = token.value == 1 or token.value == "Y" # Draw immediately
- else
- result = super(token)
- return result
- ###*
- * Clears/Resets the text-renderer.
- *
- * @method clear
- ###
- clear: ->
- @charIndex = 0
- @currentX = 0
- @currentY = 0
- @line = 0
- @lines = []
- @clearCustomObjects()
- @object.bitmap?.clear()
- for sprite in @allSprites
- sprite.dispose()
- sprite.bitmap?.dispose()
- @allSprites = []
- return null
- ###*
- * Clears/Disposes all sprites used to display the text-lines/parts.
- *
- * @method clearAllSprites
- ###
- clearAllSprites: ->
- for sprite in @allSprites
- sprite.dispose()
- sprite.bitmap?.dispose()
- return null
- ###*
- * Clears/Disposes the sprites used to display the text-lines/parts of the current/last message.
- *
- * @method clearSprites
- ###
- clearSprites: ->
- for sprite in @sprites
- sprite.dispose()
- sprite.bitmap?.dispose()
- return null
- ###*
- * Removes a game object from the message.
- *
- * @method removeCustomObject
- * @param object {gs.Object_Base} The game object to remove.
- ###
- removeCustomObject: (object) ->
- SceneManager.scene.removeObject(object)
- object.dispose()
- @customObjects.remove(object)
- ###*
- * Adds a game object to the message which is alive until the message is
- * erased. Can be used to display animationed-icons, etc. in a message.
- *
- * @method addCustomObject
- * @param object {gs.Object_Base} The game object to add.
- ###
- addCustomObject: (object) ->
- object.dstRect.x = @object.dstRect.x + @object.origin.x + @currentX
- object.dstRect.y = @object.dstRect.y + @object.origin.y + @currentY
- object.zIndex = @object.zIndex + 1
- object.update()
- SceneManager.scene.addObject(object)
- @customObjects.push(object)
- ###*
- * Clears the list of custom game objects. All game objects are disposed and removed
- * from the scene.
- *
- * @method clearCustomObjects
- * @param object {Object} The game object to add.
- ###
- clearCustomObjects: ->
- for object in @customObjects
- object.dispose()
- SceneManager.scene.removeObject(object)
- @customObjects = []
- ###*
- * Creates the bitmap for a specified line-object.
- *
- * @method createBitmap
- * @private
- * @param {Object} line - A line-object.
- * @return {Bitmap} A newly created bitmap containing the line-text.
- ###
- createBitmap: (line) ->
- @font = @object.font
- bitmap = new Bitmap(@object.dstRect.width, Math.max(@minLineHeight, line.height))
- bitmap.font = @font
- return bitmap
- ###*
- * Draws the line's content on the specified bitmap.
- *
- * @method drawLineContent
- * @protected
- * @param {Object} line - A line-object which should be drawn on the bitmap.
- * @param {gs.Bitmap} bitmap - The bitmap to draw the line's content on.
- * @param {number} length - Determines how many characters of the specified line should be drawn. You can
- * specify -1 to draw all characters.
- ###
- drawLineContent: (line, bitmap, length) ->
- bitmap.clear()
- currentX = @padding
- drawAll = length == -1
- for token, i in line.content
- break if i > @tokenIndex and !drawAll
- if token.code?
- size = @measureControlToken(token, bitmap)
- @drawControlToken(token, bitmap, currentX)
- if size then currentX += size.width
- @processControlToken(token, yes, line)
- else if token.value.length > 0
- token.applyFormat(@font)
- value = token.value
- if !drawAll and @tokenIndex == i and value.length > length
- value = value.substring(0, length)
- if value != "\n"
- size = @font.measureTextPlain(value)
- bitmap.drawText(currentX, line.height - (size.height - @font.descent) - line.descent, size.width, bitmap.height, value, 0, 0)
- currentX += size.width
- line.contentWidth = currentX + @font.measureTextPlain(" ").width
- ###*
- * Creates the sprite for a specified line-object.
- *
- * @method createSprite
- * @private
- * @param {Object} line - A line-object.
- * @return {Sprite} A newly created sprite object containing the line-text as bitmap.
- ###
- createSprite: (line) ->
- bitmap = @createBitmap(line)
- @currentX = 0
- @waitCounter = 0
- @waitForKey = no
- sprite = new Sprite(Graphics.viewport)
- sprite.bitmap = bitmap
- sprite.visible = yes
- sprite.z = @object.zIndex + 1
- sprite.srcRect = new Rect(0, 0, 0, bitmap.height)
- return sprite
- ###*
- * Creates the sprites for a specified array of line-objects.
- *
- * @method createSprites
- * @private
- * @see gs.Component_MessageTextRenderer.createSprite.
- * @param {Array} lines - An array of line-objects.
- * @return {Array} An array of sprites.
- ###
- createSprites: (lines) ->
- @fontSize = @object.font.size
- result = []
- for line, i in lines
- sprite = @createSprite(line)
- result.push(sprite)
- return result
- ###*
- * Starts a new line.
- *
- * @method newLine
- ###
- newLine: ->
- @currentX = 0
- @currentY += @currentLineHeight + @lineSpacing
- ###*
- * Displays a formatted text immediately without any delays or animations. The
- * Component_TextRenderer.drawFormattedText method from the base-class cannot
- * be used here because it would render to the game object's bitmap object while
- * this method is rendering to the sprites.
- *
- * @method drawFormattedTextImmediately
- * @param {number} x - The x-coordinate of the text's position.
- * @param {number} y - The y-coordinate of the text's position.
- * @param {number} width - Deprecated. Can be null.
- * @param {number} height - Deprecated. Can be null.
- * @param {string} text - The text to draw.
- * @param {boolean} wordWrap - If wordWrap is set to true, line-breaks are automatically created.
- ###
- drawFormattedTextImmediately: (x, y, width, height, text, wordWrap) ->
- @drawFormattedText(x, y, width, height, text, wordWrap)
- loop
- @nextChar()
- if @line >= @maxLines
- @isRunning = no
- else
- @drawNext()
- break unless @isRunning
- @currentY += @currentLineHeight + @lineSpacing
- return null
- ###*
- * Starts the rendering-process for the message.
- *
- * @method drawFormattedText
- * @param {number} x - The x-coordinate of the text's position.
- * @param {number} y - The y-coordinate of the text's position.
- * @param {number} width - Deprecated. Can be null.
- * @param {number} height - Deprecated. Can be null.
- * @param {string} text - The text to draw.
- * @param {boolean} wordWrap - If wordWrap is set to true, line-breaks are automatically created.
- ###
- drawFormattedText: (x, y, width, height, text, wordWrap) ->
- text = text || " " # Use a space character if no text is specified.
- @font.set(@object.font)
- @speed = 11 - Math.round(GameManager.settings.messageSpeed * 2.5)
- @isRunning = yes
- @drawImmediately = no
- @lineAnimationCount = @speed
- @currentLineHeight = 0
- @isWaiting = no
- @waitForKey = no
- @charIndex = 0
- @token = null
- @tokenIndex = 0
- @message = text
- @line = 0
- @currentLine = @line
- currentX = @currentX #Math.max(@currentX, @padding)
- @lines = @calculateLines(lcsm(@message), wordWrap, @currentX)
- @sprites = @createSprites(@lines)
- @allSprites = @allSprites.concat(@sprites)
- @currentX = currentX
- @currentSprite = @sprites[@line]
- @currentSprite.x = @currentX + @object.origin.x + @object.dstRect.x
- @maxLines = @calculateMaxLines(@lines)
- @token = @lines[@line]?.content[@tokenIndex] || new gs.RendererToken(null, "")
- @start()
- ###*
- * Starts the message-rendering process.
- *
- * @method start
- * @protected
- ###
- start: ->
- if GameManager.tempSettings.skip and GameManager.tempSettings.skipTime == 0
- @instantSkip()
- else if @maxLines == 0
- # If first line is empty then it doesn't fit into current line, so finish.
- if @lines[0]?.content == ""
- @finish()
- else
- @maxLines = 1
- @drawNext()
- else
- @drawNext()
- ###*
- * Skips the current message and finishes the message-processing immediately. The message
- * tokens are processed but not rendered.
- *
- * @method instantSkip
- ###
- instantSkip: ->
- loop
- if @line < @maxLines
- @nextChar()
- if @line >= @maxLines
- break
- else
- @processToken()
- break unless @isRunning and @line < @maxLines
- @object.events?.emit("messageWaiting", this)
- @continue()
- ###*
- * Processes the current token.
- *
- * @method processToken
- ###
- processToken: ->
- token = null
- if @token.code?
- token = @processControlToken(@token, no)
- if token?
- @token = token
- @token.onStart?()
- else
- token = @token
- return token
- gs.Component_MessageTextRenderer = Component_MessageTextRenderer
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement