Compare commits

...

5 Commits

Author SHA1 Message Date
Florian Rival
3ef2e4167e Move line height in text editor dialog 2025-08-07 18:45:50 +02:00
Florian Rival
71ea1995dd Fix flow 2025-08-07 18:43:31 +02:00
Florian Rival
d7248cb48e Revert BBText 2025-08-07 18:41:00 +02:00
Florian Rival
a08441eb9f Add missing types 2025-08-07 18:21:06 +02:00
Florian Rival
8014a59ea3 feat: add line height property to text objects 2025-08-07 18:09:35 +02:00
11 changed files with 94 additions and 0 deletions

View File

@@ -449,6 +449,16 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "Text")
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions());
obj.AddExpressionAndConditionAndAction("number",
"LineHeight",
_("Line height"),
_("the line height of a text object"),
_("the line height"),
"",
"res/actions/font24.png")
.AddParameter("object", _("Object"), "Text")
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions());
// Support for deprecated "Size" actions/conditions:
obj.AddDuplicatedAction("Size", "Text::SetFontSize").SetHidden();
obj.AddDuplicatedCondition("Size", "Text::FontSize").SetHidden();

View File

@@ -96,6 +96,14 @@ class TextObjectJsExtension : public gd::PlatformExtension {
.SetFunctionName("setOutlineThickness")
.SetGetter("getOutlineThickness");
GetAllExpressionsForObject("TextObject::Text")["LineHeight"]
.SetFunctionName("getLineHeight");
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::LineHeight"]
.SetFunctionName("getLineHeight");
GetAllActionsForObject("TextObject::Text")["TextObject::Text::SetLineHeight"]
.SetFunctionName("setLineHeight")
.SetGetter("getLineHeight");
GetAllActionsForObject("TextObject::Text")["TextObject::ShowShadow"]
.SetFunctionName("showShadow");
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::IsShadowEnabled"]

View File

@@ -20,6 +20,7 @@ using namespace std;
TextObject::TextObject()
: text("Text"),
characterSize(20),
lineHeight(0),
fontName(""),
smoothed(true),
bold(false),
@@ -50,6 +51,10 @@ bool TextObject::UpdateProperty(const gd::String& propertyName,
characterSize = newValue.To<double>();
return true;
}
if (propertyName == "lineHeight") {
lineHeight = newValue.To<double>();
return true;
}
if (propertyName == "font") {
fontName = newValue;
return true;
@@ -129,6 +134,13 @@ std::map<gd::String, gd::PropertyDescriptor> TextObject::GetProperties() const {
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetGroup(_("Font"));
objectProperties["lineHeight"]
.SetValue(gd::String::From(lineHeight))
.SetType("number")
.SetLabel(_("Line height"))
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetGroup(_("Font"));
objectProperties["font"]
.SetValue(fontName)
.SetType("resource")
@@ -271,6 +283,7 @@ void TextObject::DoUnserializeFrom(gd::Project& project,
SetCharacterSize(content.GetChild("characterSize", 0, "CharacterSize")
.GetValue()
.GetInt());
SetLineHeight(content.GetDoubleAttribute("lineHeight", 0));
smoothed = content.GetBoolAttribute("smoothed");
bold = content.GetBoolAttribute("bold");
italic = content.GetBoolAttribute("italic");
@@ -339,6 +352,7 @@ void TextObject::DoSerializeTo(gd::SerializerElement& element) const {
content.AddChild("textAlignment").SetValue(GetTextAlignment());
content.AddChild("verticalTextAlignment").SetValue(GetVerticalTextAlignment());
content.AddChild("characterSize").SetValue(GetCharacterSize());
content.AddChild("lineHeight").SetValue(GetLineHeight());
content.AddChild("color").SetValue(GetColor());
content.SetAttribute("smoothed", smoothed);

View File

@@ -49,6 +49,12 @@ class GD_EXTENSION_API TextObject : public gd::ObjectConfiguration {
*/
inline double GetCharacterSize() const { return characterSize; };
/** \brief Change the line height. */
inline void SetLineHeight(double value) { lineHeight = value; };
/** \brief Get the line height. */
inline double GetLineHeight() const { return lineHeight; };
/** \brief Return the name of the font resource used for the text.
*/
inline const gd::String& GetFontName() const { return fontName; };
@@ -120,6 +126,7 @@ class GD_EXTENSION_API TextObject : public gd::ObjectConfiguration {
gd::String text;
double characterSize;
double lineHeight;
gd::String fontName;
bool smoothed;
bool bold, italic, underlined;

View File

@@ -86,6 +86,7 @@ namespace gdjs {
? style.dropShadowDistance + style.dropShadowBlur
: 0;
style.padding = Math.ceil(this._object._padding + extraPaddingForShadow);
style.lineHeight = this._object._lineHeight;
// Prevent spikey outlines by adding a miter limit
style.miterLimit = 3;

View File

@@ -22,6 +22,8 @@ namespace gdjs {
text: string;
textAlignment: string;
verticalTextAlignment: string;
/** The line height */
lineHeight: float;
isOutlineEnabled: boolean;
outlineThickness: float;
@@ -62,6 +64,7 @@ namespace gdjs {
sha: float;
shb: float;
pad: integer;
lh: float;
};
export type TextObjectNetworkSyncData = ObjectNetworkSyncData &
@@ -101,6 +104,8 @@ namespace gdjs {
_shadowAngle: float;
_shadowBlur: float;
_lineHeight: float;
_padding: integer = 5;
_str: string;
_renderer: gdjs.TextRuntimeObjectRenderer;
@@ -139,6 +144,7 @@ namespace gdjs {
this._shadowDistance = content.shadowDistance;
this._shadowBlur = content.shadowBlurRadius;
this._shadowAngle = content.shadowAngle;
this._lineHeight = content.lineHeight || 0;
this._renderer = new gdjs.TextRuntimeObjectRenderer(
this,
@@ -211,6 +217,9 @@ namespace gdjs {
if (oldContent.shadowBlurRadius !== newContent.shadowBlurRadius) {
this.setShadowBlurRadius(newContent.shadowBlurRadius);
}
if ((oldContent.lineHeight || 0) !== (newContent.lineHeight || 0)) {
this.setLineHeight(newContent.lineHeight || 0);
}
return true;
}
@@ -238,6 +247,7 @@ namespace gdjs {
shd: this._shadowDistance,
sha: this._shadowAngle,
shb: this._shadowBlur,
lh: this._lineHeight,
pad: this._padding,
};
}
@@ -312,6 +322,9 @@ namespace gdjs {
if (networkSyncData.shb !== undefined) {
this.setShadowBlurRadius(networkSyncData.shb);
}
if (networkSyncData.lh !== undefined) {
this.setLineHeight(networkSyncData.lh);
}
if (networkSyncData.pad !== undefined) {
this.setPadding(networkSyncData.pad);
}
@@ -444,6 +457,22 @@ namespace gdjs {
this._renderer.updateStyle();
}
/**
* Get the line height of the text.
*/
getLineHeight(): float {
return this._lineHeight;
}
/**
* Set the line height of the text.
* @param value The new line height for the text.
*/
setLineHeight(value: float): void {
this._lineHeight = value;
this._renderer.updateStyle();
}
/**
* Set the name of the resource to use for the font.
* @param fontResourceName The name of the font resource.

View File

@@ -3728,6 +3728,8 @@ interface TextObject {
[Const, Ref] DOMString GetText();
void SetCharacterSize(double size);
double GetCharacterSize();
void SetLineHeight(double value);
double GetLineHeight();
void SetFontName([Const] DOMString string);
[Const, Ref] DOMString GetFontName();
boolean IsBold();

View File

@@ -2758,6 +2758,8 @@ export class TextObject extends ObjectConfiguration {
getText(): string;
setCharacterSize(size: number): void;
getCharacterSize(): number;
setLineHeight(value: number): void;
getLineHeight(): number;
setFontName(string: string): void;
getFontName(): string;
isBold(): boolean;

View File

@@ -5,6 +5,8 @@ declare class gdTextObject extends gdObjectConfiguration {
getText(): string;
setCharacterSize(size: number): void;
getCharacterSize(): number;
setLineHeight(value: number): void;
getLineHeight(): number;
setFontName(string: string): void;
getFontName(): string;
isBold(): boolean;

View File

@@ -371,6 +371,21 @@ export default class TextEditor extends React.Component<EditorProps, void> {
}}
/>
</Column>
<Text size="block-title" noMargin>
<Trans>Multiline</Trans>
</Text>
<Line noMargin>
<SemiControlledTextField
floatingLabelText={<Trans>Line height</Trans>}
type="number"
fullWidth
value={textObjectConfiguration.getLineHeight()}
onChange={value => {
textObjectConfiguration.setLineHeight(parseFloat(value) || 0);
this.forceUpdate();
}}
/>
</Line>
</ColumnStackLayout>
);
}

View File

@@ -32,6 +32,7 @@ export default class RenderedTextInstance extends RenderedInstance {
_shadowColor = '0;0;0';
_shadowOpacity = 127;
_shadowBlurRadius = 2;
_lineHeight = 0;
constructor(
project: gdProject,
@@ -97,6 +98,7 @@ export default class RenderedTextInstance extends RenderedInstance {
textObjectConfiguration.isItalic() !== this._isItalic ||
textObjectConfiguration.isBold() !== this._isBold ||
textObjectConfiguration.getCharacterSize() !== this._characterSize ||
textObjectConfiguration.getLineHeight() !== this._lineHeight ||
textObjectConfiguration.getTextAlignment() !== this._textAlignment ||
textObjectConfiguration.getVerticalTextAlignment() !==
this._verticalTextAlignment ||
@@ -118,6 +120,7 @@ export default class RenderedTextInstance extends RenderedInstance {
this._isItalic = textObjectConfiguration.isItalic();
this._isBold = textObjectConfiguration.isBold();
this._characterSize = textObjectConfiguration.getCharacterSize();
this._lineHeight = textObjectConfiguration.getLineHeight();
this._textAlignment = textObjectConfiguration.getTextAlignment();
this._verticalTextAlignment = textObjectConfiguration.getVerticalTextAlignment();
this._color = textObjectConfiguration.getColor();
@@ -167,6 +170,7 @@ export default class RenderedTextInstance extends RenderedInstance {
style.fontSize = Math.max(1, this._characterSize);
style.fontStyle = this._isItalic ? 'italic' : 'normal';
style.fontWeight = this._isBold ? 'bold' : 'normal';
style.lineHeight = this._lineHeight !== 0 ? this._lineHeight : undefined;
style.fill = rgbStringToHexNumber(this._color);
style.wordWrap = this._wrapping;
style.wordWrapWidth = this._wrappingWidth <= 1 ? 1 : this._wrappingWidth;