Files
GDevelop/Extensions/TextObject/textruntimeobject.ts
T
Harsimran Singh Virk 599ccb677f Add support for visual effects ("shaders") on objects. (#2901)
* This allows to generate interesting visual effects, which can be controlled by events. For example, you can use an outline on an object to highlight, make the player glow when launching a spell, blur objects, etc...
* A new "effects" tab is now present in the objects editor. From there, you can add visual effects, that were already available for layers, customize them from this editor.
* Actions and conditions are available to manipulate effects and change their parameters during the game.
* Learn more on the wiki: http://wiki.compilgames.net/doku.php/gdevelop5/objects/effects

Co-authored-by: Florian Rival <Florian.Rival@gmail.com>
2021-08-20 15:01:06 +02:00

563 lines
14 KiB
TypeScript

/*
* GDevelop JS Platform
* 2013-2016 Florian Rival (Florian.Rival@gmail.com)
*/
namespace gdjs {
/** Base parameters for gdjs.TextRuntimeObject */
export type TextObjectDataType = {
/** The size of the characters */
characterSize: number;
/** The font name */
font: string;
/** Is Bold? */
bold: boolean;
/** Is Italic? */
italic: boolean;
/** Is Underlined? */
underlined: boolean;
/** The text color in an RGB representation */
color: {
/** The Red level from 0 to 255 */
r: number;
/** The Green level from 0 to 255 */
g: number;
/** The Blue level from 0 to 255 */
b: number;
};
/** The text of the object */
string: string;
};
export type TextObjectData = ObjectData & TextObjectDataType;
/**
* Displays a text.
*/
export class TextRuntimeObject extends gdjs.RuntimeObject {
_characterSize: number;
_fontName: string;
_bold: boolean;
_italic: boolean;
_underlined: boolean;
_color: integer[];
_useGradient: boolean = false;
_gradient: Array<Array<integer>> = [];
_gradientType: string = '';
opacity: float = 255;
_textAlign: string = 'left';
_wrapping: boolean = false;
_wrappingWidth: float = 1;
_outlineThickness: number = 0;
_outlineColor: integer[] = [255, 255, 255];
_shadow: boolean = false;
_shadowColor: integer[] = [0, 0, 0];
_shadowDistance: number = 1;
_shadowBlur: integer = 1;
_shadowAngle: float = 0;
_padding: integer = 5;
_str: string;
_renderer: gdjs.TextRuntimeObjectRenderer;
// We can store the scale as nothing else can change it.
_scaleX: number = 1;
_scaleY: number = 1;
/**
* @param runtimeScene The scene the object belongs to.
* @param textObjectData The initial properties of the object
*/
constructor(
runtimeScene: gdjs.RuntimeScene,
textObjectData: TextObjectData
) {
super(runtimeScene, textObjectData);
this._characterSize = Math.max(1, textObjectData.characterSize);
this._fontName = textObjectData.font;
this._bold = textObjectData.bold;
this._italic = textObjectData.italic;
this._underlined = textObjectData.underlined;
this._color = [
textObjectData.color.r,
textObjectData.color.g,
textObjectData.color.b,
];
this._str = textObjectData.string;
this._renderer = new gdjs.TextRuntimeObjectRenderer(this, runtimeScene);
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
}
updateFromObjectData(
oldObjectData: TextObjectData,
newObjectData: TextObjectData
): boolean {
if (oldObjectData.characterSize !== newObjectData.characterSize) {
this.setCharacterSize(newObjectData.characterSize);
}
if (oldObjectData.font !== newObjectData.font) {
this.setFontName(newObjectData.font);
}
if (oldObjectData.bold !== newObjectData.bold) {
this.setBold(newObjectData.bold);
}
if (oldObjectData.italic !== newObjectData.italic) {
this.setItalic(newObjectData.italic);
}
if (
oldObjectData.color.r !== newObjectData.color.r ||
oldObjectData.color.g !== newObjectData.color.g ||
oldObjectData.color.b !== newObjectData.color.b
) {
this.setColor(
'' +
newObjectData.color.r +
';' +
newObjectData.color.g +
';' +
newObjectData.color.b
);
}
if (oldObjectData.string !== newObjectData.string) {
this.setString(newObjectData.string);
}
if (oldObjectData.underlined !== newObjectData.underlined) {
return false;
}
return true;
}
getRendererObject() {
return this._renderer.getRendererObject();
}
update(runtimeScene: gdjs.RuntimeScene): void {
this._renderer.ensureUpToDate();
}
/**
* Initialize the extra parameters that could be set for an instance.
*/
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
if (initialInstanceData.customSize) {
this.setWrapping(true);
this.setWrappingWidth(initialInstanceData.width);
} else {
this.setWrapping(false);
}
}
/**
* Update the rendered object position.
*/
private _updateTextPosition() {
this.hitBoxesDirty = true;
this._renderer.updatePosition();
}
/**
* Set object position on X axis.
*/
setX(x): void {
super.setX(x);
this._updateTextPosition();
}
/**
* Set object position on Y axis.
*/
setY(y): void {
super.setY(y);
this._updateTextPosition();
}
/**
* Set the angle of the object.
* @param angle The new angle of the object
*/
setAngle(angle: float): void {
super.setAngle(angle);
this._renderer.updateAngle();
}
/**
* Set object opacity.
*/
setOpacity(opacity): void {
if (opacity < 0) {
opacity = 0;
}
if (opacity > 255) {
opacity = 255;
}
this.opacity = opacity;
this._renderer.updateOpacity();
}
/**
* Get object opacity.
*/
getOpacity() {
return this.opacity;
}
/**
* Get the string displayed by the object.
*/
getString(): string {
return this._str;
}
/**
* Set the string displayed by the object.
* @param str The new text
*/
setString(str: string): void {
if (str === this._str) {
return;
}
this._str = str;
this._renderer.updateString();
this._updateTextPosition();
}
/**
* Get the font size of the characters of the object.
*/
getCharacterSize() {
return this._characterSize;
}
/**
* Set the font size for characters of the object.
* @param newSize The new font size for the text.
*/
setCharacterSize(newSize: number): void {
if (newSize <= 1) {
newSize = 1;
}
this._characterSize = newSize;
this._renderer.updateStyle();
}
/**
* Set the name of the resource to use for the font.
* @param fontResourceName The name of the font resource.
*/
setFontName(fontResourceName: string): void {
this._fontName = fontResourceName;
this._renderer.updateStyle();
}
/**
* Return true if the text is bold.
*/
isBold(): boolean {
return this._bold;
}
/**
* Set bold for the object text.
* @param enable {boolean} true to have a bold text, false otherwise.
*/
setBold(enable): void {
this._bold = enable;
this._renderer.updateStyle();
}
/**
* Return true if the text is italic.
*/
isItalic(): boolean {
return this._italic;
}
/**
* Set italic for the object text.
* @param enable {boolean} true to have an italic text, false otherwise.
*/
setItalic(enable): void {
this._italic = enable;
this._renderer.updateStyle();
}
/**
* Get width of the text.
*/
getWidth(): float {
return this._renderer.getWidth();
}
/**
* Get height of the text.
*/
getHeight(): float {
return this._renderer.getHeight();
}
/**
* Get scale of the text.
*/
getScale(): float {
return (Math.abs(this._scaleX) + Math.abs(this._scaleY)) / 2.0;
}
/**
* Get x-scale of the text.
*/
getScaleX(): float {
return this._scaleX;
}
/**
* Get y-scale of the text.
*/
getScaleY(): float {
return this._scaleY;
}
/**
* Set the text object scale.
* @param newScale The new scale for the text object.
*/
setScale(newScale: float): void {
if (this._scaleX === newScale && this._scaleY === newScale) return;
this._scaleX = newScale;
this._scaleY = newScale;
this._renderer.setScale(newScale);
this.hitBoxesDirty = true;
}
/**
* Set the text object x-scale.
* @param newScale The new x-scale for the text object.
*/
setScaleX(newScale: float): void {
if (this._scaleX === newScale) return;
this._scaleX = newScale;
this._renderer.setScaleX(newScale);
this.hitBoxesDirty = true;
}
/**
* Set the text object y-scale.
* @param newScale The new y-scale for the text object.
*/
setScaleY(newScale: float): void {
if (this._scaleY === newScale) return;
this._scaleY = newScale;
this._renderer.setScaleY(newScale);
this.hitBoxesDirty = true;
}
/**
* Change the text color.
* @param color color as a "R;G;B" string, for example: "255;0;0"
*/
setColor(str: string): void {
const color = str.split(';');
if (color.length < 3) {
return;
}
this._color[0] = parseInt(color[0], 10);
this._color[1] = parseInt(color[1], 10);
this._color[2] = parseInt(color[2], 10);
this._useGradient = false;
this._renderer.updateStyle();
}
/**
* Get the text color.
* @return The color as a "R;G;B" string, for example: "255;0;0"
*/
getColor(): string {
return this._color[0] + ';' + this._color[1] + ';' + this._color[2];
}
/**
* Set the text alignment for multiline text objects.
* @param alignment The text alignment.
*/
setTextAlignment(alignment: string): void {
this._textAlign = alignment;
this._renderer.updateStyle();
}
/**
* Get the text alignment of text object.
* @return The text alignment.
*/
getTextAlignment(): string {
return this._textAlign;
}
/**
* Return true if word wrapping is enabled for the text.
*/
isWrapping(): boolean {
return this._wrapping;
}
/**
* Set word wrapping for the object text.
* @param enable true to enable word wrapping, false to disable it.
*/
setWrapping(enable: boolean): void {
if (this._wrapping === enable) return;
this._wrapping = enable;
this._renderer.updateStyle();
this.hitBoxesDirty = true;
}
/**
* Get the word wrapping width for the text object.
*/
getWrappingWidth(): float {
return this._wrappingWidth;
}
/**
* Set the word wrapping width for the text object.
* @param width The new width to set.
*/
setWrappingWidth(width: float): void {
if (width <= 1) {
width = 1;
}
if (this._wrappingWidth === width) return;
this._wrappingWidth = width;
this._renderer.updateStyle();
this.hitBoxesDirty = true;
}
/**
* Set the outline for the text object.
* @param str color as a "R;G;B" string, for example: "255;0;0"
* @param thickness thickness of the outline (0 = disabled)
*/
setOutline(str: string, thickness: number): void {
const color = str.split(';');
if (color.length < 3) {
return;
}
this._outlineColor[0] = parseInt(color[0], 10);
this._outlineColor[1] = parseInt(color[1], 10);
this._outlineColor[2] = parseInt(color[2], 10);
this._outlineThickness = thickness;
this._renderer.updateStyle();
}
/**
* Set the shadow for the text object.
* @param str color as a "R;G;B" string, for example: "255;0;0"
* @param distance distance between the shadow and the text, in pixels.
* @param blur amout of shadow blur, in pixels.
* @param angle shadow offset direction, in degrees.
*/
setShadow(
str: string,
distance: number,
blur: integer,
angle: float
): void {
const color = str.split(';');
if (color.length < 3) {
return;
}
this._shadowColor[0] = parseInt(color[0], 10);
this._shadowColor[1] = parseInt(color[1], 10);
this._shadowColor[2] = parseInt(color[2], 10);
this._shadowDistance = distance;
this._shadowBlur = blur;
this._shadowAngle = angle;
this._shadow = true;
this._renderer.updateStyle();
}
/**
* Set the gradient for the text object.
* @param strFirstColor color as a "R;G;B" string, for example: "255;0;0"
* @param strSecondColor color as a "R;G;B" string, for example: "255;0;0"
* @param strThirdColor color as a "R;G;B" string, for example: "255;0;0"
* @param strFourthColor color as a "R;G;B" string, for example: "255;0;0"
* @param strGradientType gradient type
*/
setGradient(
strGradientType: string,
strFirstColor: string,
strSecondColor: string,
strThirdColor: string,
strFourthColor: string
): void {
const colorFirst = strFirstColor.split(';');
const colorSecond = strSecondColor.split(';');
const colorThird = strThirdColor.split(';');
const colorFourth = strFourthColor.split(';');
this._gradient = [];
if (colorFirst.length == 3) {
this._gradient.push([
parseInt(colorFirst[0], 10),
parseInt(colorFirst[1], 10),
parseInt(colorFirst[2], 10),
]);
}
if (colorSecond.length == 3) {
this._gradient.push([
parseInt(colorSecond[0], 10),
parseInt(colorSecond[1], 10),
parseInt(colorSecond[2], 10),
]);
}
if (colorThird.length == 3) {
this._gradient.push([
parseInt(colorThird[0], 10),
parseInt(colorThird[1], 10),
parseInt(colorThird[2], 10),
]);
}
if (colorFourth.length == 3) {
this._gradient.push([
parseInt(colorFourth[0], 10),
parseInt(colorFourth[1], 10),
parseInt(colorFourth[2], 10),
]);
}
this._gradientType = strGradientType;
this._useGradient = this._gradient.length > 1 ? true : false;
this._renderer.updateStyle();
}
/**
* Show the shadow of the text object.
* @param enable true to show the shadow, false to hide it
*/
showShadow(enable: boolean): void {
this._shadow = enable;
this._renderer.updateStyle();
}
/**
* Get padding of the text object.
* @return number of pixels around the text before it gets cropped
*/
getPadding(): number {
return this._padding;
}
/**
* Set padding of the text object.
* @param value number of pixels around the text before it gets cropped
*/
setPadding(value: float): void {
this._padding = value;
this._renderer.updateStyle();
}
}
gdjs.registerObject('TextObject::Text', gdjs.TextRuntimeObject);
}