mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Add BBText object (#1247)
* Uses `pixi-multistyle-text` * Add standalone example * Update the Yarn Dialogue example
This commit is contained in:

committed by
Florian Rival

parent
0c045d6e79
commit
2809f53af8
611
Extensions/BBText/JsExtension.js
Normal file
611
Extensions/BBText/JsExtension.js
Normal file
@@ -0,0 +1,611 @@
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change
|
||||
* to this extension file or to any other *.js file that you reference inside.
|
||||
*
|
||||
* The file must be named "JsExtension.js", otherwise GDevelop won't load it.
|
||||
* ⚠️ If you make a change and the extension is not loaded, open the developer console
|
||||
* and search for any errors.
|
||||
*
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
createExtension: function(_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
'BBText',
|
||||
_('BBCode Text Object'),
|
||||
_(
|
||||
'Displays a rich text label using BBCode markup (allowing to set parts of the text as bold, italic, use different colors and shadows).'
|
||||
),
|
||||
'Todor Imreorov',
|
||||
'Open source (MIT License)'
|
||||
)
|
||||
.setExtensionHelpPath('/objects/bbtext_object');
|
||||
|
||||
var objectBBText = new gd.ObjectJsImplementation();
|
||||
objectBBText.updateProperty = function(
|
||||
objectContent,
|
||||
propertyName,
|
||||
newValue
|
||||
) {
|
||||
if (propertyName in objectContent) {
|
||||
if (typeof objectContent[propertyName] === 'boolean')
|
||||
objectContent[propertyName] = newValue === '1';
|
||||
else objectContent[propertyName] = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
objectBBText.getProperties = function(objectContent) {
|
||||
var objectProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
objectProperties.set(
|
||||
'text',
|
||||
new gd.PropertyDescriptor(objectContent.text)
|
||||
.setType('textarea')
|
||||
.setLabel(_('BBCode text'))
|
||||
);
|
||||
|
||||
objectProperties.set(
|
||||
'color',
|
||||
new gd.PropertyDescriptor(objectContent.color)
|
||||
.setType('color')
|
||||
.setLabel(_('Base color'))
|
||||
);
|
||||
|
||||
objectProperties.set(
|
||||
'opacity',
|
||||
new gd.PropertyDescriptor(objectContent.opacity.toString())
|
||||
.setType('number')
|
||||
.setLabel(_('Opacity (0-255)'))
|
||||
);
|
||||
|
||||
objectProperties.set(
|
||||
'fontSize',
|
||||
new gd.PropertyDescriptor(objectContent.fontSize)
|
||||
.setType('number')
|
||||
.setLabel(_('Base size'))
|
||||
);
|
||||
|
||||
objectProperties.set(
|
||||
'align',
|
||||
new gd.PropertyDescriptor(objectContent.align)
|
||||
.setType('choice')
|
||||
.addExtraInfo('left')
|
||||
.addExtraInfo('center')
|
||||
.addExtraInfo('right')
|
||||
.setLabel(_('Base alignment'))
|
||||
);
|
||||
|
||||
objectProperties.set(
|
||||
'fontFamily',
|
||||
new gd.PropertyDescriptor(objectContent.fontFamily)
|
||||
.setType('string')
|
||||
.setLabel(_('Base font family'))
|
||||
);
|
||||
|
||||
objectProperties.set(
|
||||
'wordWrap',
|
||||
new gd.PropertyDescriptor(objectContent.wordWrap ? 'true' : 'false')
|
||||
.setType('boolean')
|
||||
.setLabel(_('Word wrapping'))
|
||||
);
|
||||
|
||||
objectProperties.set(
|
||||
'visible',
|
||||
new gd.PropertyDescriptor(objectContent.visible ? 'true' : 'false')
|
||||
.setType('boolean')
|
||||
.setLabel(_('Visible on start'))
|
||||
);
|
||||
|
||||
return objectProperties;
|
||||
};
|
||||
objectBBText.setRawJSONContent(
|
||||
JSON.stringify({
|
||||
text:
|
||||
'[b]bold[/b] [i]italic[/i] [size=15]smaller[/size] [font=times]times[/font] font\n[spacing=12]spaced out[/spacing]\n[outline=yellow]outlined[/outline] [shadow=red]DropShadow[/shadow] ',
|
||||
opacity: 255,
|
||||
fontSize: '20',
|
||||
visible: true,
|
||||
color: '#000000',
|
||||
fontFamily: 'Arial',
|
||||
align: 'left',
|
||||
wordWrap: true,
|
||||
})
|
||||
);
|
||||
|
||||
objectBBText.updateInitialInstanceProperty = function(
|
||||
objectContent,
|
||||
instance,
|
||||
propertyName,
|
||||
newValue,
|
||||
project,
|
||||
layout
|
||||
) {
|
||||
return false;
|
||||
};
|
||||
objectBBText.getInitialInstanceProperties = function(
|
||||
content,
|
||||
instance,
|
||||
project,
|
||||
layout
|
||||
) {
|
||||
var instanceProperties = new gd.MapStringPropertyDescriptor();
|
||||
return instanceProperties;
|
||||
};
|
||||
|
||||
const object = extension
|
||||
.addObject(
|
||||
'BBText',
|
||||
_('BBText'),
|
||||
_(
|
||||
'Displays a rich text label using BBCode markup (allowing to set parts of the text as bold, italic, use different colors and shadows).'
|
||||
),
|
||||
'JsPlatform/Extensions/bbcode32.png',
|
||||
objectBBText
|
||||
)
|
||||
.setIncludeFile('Extensions/BBText/bbtextruntimeobject.js')
|
||||
.addIncludeFile('Extensions/BBText/bbtextruntimeobject-pixi-renderer.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/BBText/pixi-multistyle-text/dist/pixi-multistyle-text.umd.js'
|
||||
);
|
||||
|
||||
/**
|
||||
* Utility function to add both a setter and a getter to a property from a list.
|
||||
* Useful for setting multiple generic properties.
|
||||
*/
|
||||
const addSettersAndGettersToObject = (gdObject, properties, objectName) => {
|
||||
properties.forEach(property => {
|
||||
const parameterType =
|
||||
property.type === 'boolean' ? 'yesorno' : property.type;
|
||||
|
||||
// Add the expression
|
||||
if (parameterType === 'number') {
|
||||
gdObject
|
||||
.addExpression(
|
||||
`Get${property.functionName}`,
|
||||
property.expressionDescription,
|
||||
property.expressionSentence,
|
||||
'',
|
||||
'',
|
||||
property.iconPath,
|
||||
property.iconPath
|
||||
)
|
||||
.addParameter('object', objectName, objectName, false)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName(`get${property.functionName}`);
|
||||
} else if (parameterType === 'string') {
|
||||
gdObject
|
||||
.addStrExpression(
|
||||
`Get${property.functionName}`,
|
||||
property.expressionDescription,
|
||||
property.expressionSentence,
|
||||
'',
|
||||
'',
|
||||
property.iconPath,
|
||||
property.iconPath
|
||||
)
|
||||
.addParameter('object', objectName, objectName, false)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName(`get${property.functionName}`);
|
||||
}
|
||||
|
||||
// Add the action
|
||||
if (parameterType === 'number' || parameterType === 'string') {
|
||||
const expressionType =
|
||||
parameterType === 'number' ? 'expression' : 'string';
|
||||
gdObject
|
||||
.addAction(
|
||||
`Set${property.functionName}`,
|
||||
property.paramLabel,
|
||||
property.actionDescription,
|
||||
property.actionSentence,
|
||||
'',
|
||||
property.iconPath,
|
||||
property.iconPath
|
||||
)
|
||||
.addParameter('object', objectName, objectName, false)
|
||||
.addParameter('operator', _("Modification's sign"), '', false)
|
||||
.addParameter(expressionType, property.paramLabel, '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName(`set${property.functionName}`)
|
||||
.setManipulatedType(parameterType)
|
||||
.setGetter(`get${property.functionName}`);
|
||||
} else {
|
||||
gdObject
|
||||
.addAction(
|
||||
`Set${property.functionName}`,
|
||||
property.paramLabel,
|
||||
property.actionDescription,
|
||||
property.actionSentence,
|
||||
'',
|
||||
property.iconPath,
|
||||
property.iconPath
|
||||
)
|
||||
.addParameter('object', objectName, objectName, false)
|
||||
.addParameter(
|
||||
parameterType,
|
||||
property.paramLabel,
|
||||
property.options
|
||||
? '["' + property.options.join('", "') + '"]'
|
||||
: '',
|
||||
false
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName(`set${property.functionName}`)
|
||||
.setGetter(`get${property.functionName}`);
|
||||
}
|
||||
|
||||
// Add condition
|
||||
if (parameterType === 'string' || parameterType === 'number') {
|
||||
const propExpressionType =
|
||||
parameterType === 'string' ? 'string' : 'expression';
|
||||
gdObject
|
||||
.addCondition(
|
||||
`Is${property.functionName}`,
|
||||
property.paramLabel,
|
||||
property.conditionDescription,
|
||||
property.conditionSentence,
|
||||
'',
|
||||
property.iconPath,
|
||||
property.iconPath
|
||||
)
|
||||
.addParameter('object', objectName, objectName, false)
|
||||
.addParameter(
|
||||
'relationalOperator',
|
||||
_('Sign of the test'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.addParameter(
|
||||
propExpressionType,
|
||||
parameterType + _(' value'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName(`get${property.functionName}`)
|
||||
.setManipulatedType(parameterType);
|
||||
} else if (parameterType === 'yesorno') {
|
||||
gdObject
|
||||
.addCondition(
|
||||
`Is${property.functionName}`,
|
||||
property.paramLabel,
|
||||
property.conditionDescription,
|
||||
property.conditionSentence,
|
||||
'',
|
||||
property.iconPath,
|
||||
property.iconPath
|
||||
)
|
||||
.addParameter('object', objectName, objectName, false)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName(`get${property.functionName}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const setterAndGetterProperties = [
|
||||
{
|
||||
functionName: 'BBText',
|
||||
iconPath: 'res/actions/text24.png',
|
||||
type: 'string',
|
||||
paramLabel: _('BBCode text'),
|
||||
conditionDescription: _('Compare the value of the BBCode text.'),
|
||||
conditionSentence: _('The BBCode text of _PARAM0_ is _PARAM1__PARAM2_'),
|
||||
actionDescription: _('Set BBCode text'),
|
||||
actionSentence: _('Do _PARAM1__PARAM2_ to the BBCode text of _PARAM0_'),
|
||||
expressionDescription: _('Get BBCode text'),
|
||||
expressionSentence: _('Get BBCode text'),
|
||||
},
|
||||
{
|
||||
functionName: 'Color',
|
||||
iconPath: 'res/actions/color24.png',
|
||||
type: 'color',
|
||||
paramLabel: _('Color'),
|
||||
conditionDescription: '', // No conditions for a "color" property
|
||||
conditionSentence: '', // No conditions for a "color" property
|
||||
actionDescription: _('Set base color'),
|
||||
actionSentence: _('Set base color of _PARAM0_ to _PARAM1_'),
|
||||
expressionDescription: '', // No expression for a "color" property
|
||||
expressionSentence: '', // No expression for a "color" property
|
||||
},
|
||||
{
|
||||
functionName: 'Opacity',
|
||||
iconPath: 'res/actions/opacity24.png',
|
||||
type: 'number',
|
||||
paramLabel: _('Opacity'),
|
||||
conditionDescription: _(
|
||||
'Compare the value of the base opacity of the text.'
|
||||
),
|
||||
conditionSentence: _(
|
||||
'The base opacity of _PARAM0_ is _PARAM1__PARAM2_'
|
||||
),
|
||||
actionDescription: _('Set base opacity'),
|
||||
actionSentence: _(
|
||||
'Do _PARAM1__PARAM2_ to the base opacity of _PARAM0_'
|
||||
),
|
||||
expressionDescription: _('Get the base opacity'),
|
||||
expressionSentence: _('Get the base opacity'),
|
||||
},
|
||||
{
|
||||
functionName: 'FontSize',
|
||||
iconPath: 'res/actions/characterSize24.png',
|
||||
type: 'number',
|
||||
paramLabel: _('Font size'),
|
||||
conditionDescription: _('Compare the base font size of the text.'),
|
||||
conditionSentence: _(
|
||||
'The base font size of _PARAM0_ is _PARAM1__PARAM2_'
|
||||
),
|
||||
actionDescription: _('Set base font size'),
|
||||
actionSentence: _(
|
||||
'Do _PARAM1__PARAM2_ to the base font size of _PARAM0_'
|
||||
),
|
||||
expressionDescription: _('Get the base font size'),
|
||||
expressionSentence: _('Get the base font size'),
|
||||
},
|
||||
{
|
||||
functionName: 'FontFamily',
|
||||
iconPath: 'res/actions/font24.png',
|
||||
type: 'string',
|
||||
paramLabel: _('Font family'),
|
||||
conditionDescription: _('Compare the value of font family'),
|
||||
conditionSentence: _(
|
||||
'The base font family of _PARAM0_ is _PARAM1__PARAM2_'
|
||||
),
|
||||
actionDescription: _('Set font family'),
|
||||
actionSentence: _(
|
||||
'Do _PARAM1__PARAM2_ to the base font family of _PARAM0_'
|
||||
),
|
||||
expressionDescription: _('Get the base font family'),
|
||||
expressionSentence: _('Get the base font family'),
|
||||
},
|
||||
{
|
||||
functionName: 'Alignment',
|
||||
iconPath: 'res/actions/textAlign24.png',
|
||||
type: 'stringWithSelector',
|
||||
paramLabel: _('Alignment'),
|
||||
options: ['left', 'right', 'center'],
|
||||
conditionDescription: _('Check the current text alignment'),
|
||||
conditionSentence: _('The text alignment of _PARAM0_ is _PARAM1_'),
|
||||
actionDescription: _('Change the alignment of the text.'),
|
||||
actionSentence: _('Set text alignment of _PARAM0_ to _PARAM1_'),
|
||||
expressionDescription: _('Get the text alignment'),
|
||||
expressionSentence: _('Get the text alignment'),
|
||||
},
|
||||
{
|
||||
functionName: 'WordWrap',
|
||||
iconPath: 'res/actions/scaleWidth24.png',
|
||||
type: 'boolean',
|
||||
paramLabel: _('Word wrap'),
|
||||
conditionDescription: _('Check if word wrap is enabled'),
|
||||
conditionSentence: _('Word wrap is enabled'),
|
||||
actionDescription: _('Set word wrap'),
|
||||
actionSentence: _('Activate word wrap for _PARAM0_: _PARAM1_'),
|
||||
expressionDescription: '',
|
||||
expressionSentence: '',
|
||||
},
|
||||
{
|
||||
functionName: 'WrappingWidth',
|
||||
iconPath: 'res/actions/scaleWidth24.png',
|
||||
type: 'number',
|
||||
paramLabel: _('Wrapping width'),
|
||||
conditionDescription: _(
|
||||
'Compare the width, in pixels, after which the text is wrapped on next line.'
|
||||
),
|
||||
conditionSentence: _(
|
||||
'The wrapping width of _PARAM0_ is _PARAM1__PARAM2_'
|
||||
),
|
||||
actionDescription: _(
|
||||
'Change the width, in pixels, after which the text is wrapped on next line.'
|
||||
),
|
||||
actionSentence: _(
|
||||
'Do _PARAM1__PARAM2_ to the wrapping width of _PARAM0_'
|
||||
),
|
||||
expressionDescription: _('Get the wrapping width'),
|
||||
expressionSentence: _('Get the wrapping width'),
|
||||
},
|
||||
];
|
||||
|
||||
addSettersAndGettersToObject(object, setterAndGetterProperties, 'BBText');
|
||||
|
||||
return extension;
|
||||
},
|
||||
|
||||
/**
|
||||
* You can optionally add sanity tests that will check the basic working
|
||||
* of your extension behaviors/objects by instanciating behaviors/objects
|
||||
* and setting the property to a given value.
|
||||
*
|
||||
* If you don't have any tests, you can simply return an empty array like this:
|
||||
* `runExtensionSanityTests: function(gd, extension) { return []; }`
|
||||
*
|
||||
* But it is recommended to create tests for the behaviors/objects properties you created
|
||||
* to avoid mistakes.
|
||||
*/
|
||||
runExtensionSanityTests: function(gd, extension) {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* Register editors for objects.
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerEditorConfigurations: function(objectsEditorService) {
|
||||
objectsEditorService.registerEditorConfiguration(
|
||||
'BBText::BBText',
|
||||
objectsEditorService.getDefaultObjectJsImplementationPropertiesEditor({
|
||||
helpPagePath: '/objects/bbtext_object',
|
||||
})
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Register renderers for instance of objects on the scene editor.
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers: function(objectsRenderingService) {
|
||||
const RenderedInstance = objectsRenderingService.RenderedInstance;
|
||||
const PIXI = objectsRenderingService.PIXI;
|
||||
const MultiStyleText = objectsRenderingService.requireModule(
|
||||
__dirname,
|
||||
'pixi-multistyle-text/dist/pixi-multistyle-text.umd'
|
||||
);
|
||||
|
||||
/**
|
||||
* Renderer for instances of BBText inside the IDE.
|
||||
*
|
||||
* @extends RenderedBBTextInstance
|
||||
* @class RenderedBBTextInstance
|
||||
* @constructor
|
||||
*/
|
||||
function RenderedBBTextInstance(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObject,
|
||||
pixiContainer,
|
||||
pixiResourcesLoader
|
||||
) {
|
||||
RenderedInstance.call(
|
||||
this,
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObject,
|
||||
pixiContainer,
|
||||
pixiResourcesLoader
|
||||
);
|
||||
|
||||
const bbTextStyles = {
|
||||
default: {
|
||||
fontFamily: 'Arial',
|
||||
fontSize: '24px',
|
||||
fill: '#cccccc',
|
||||
tagStyle: 'bbcode',
|
||||
wordWrap: true,
|
||||
wordWrapWidth: 250, // This value is the default wrapping width of the runtime object.
|
||||
align: 'left',
|
||||
},
|
||||
};
|
||||
|
||||
this._pixiObject = new MultiStyleText('', bbTextStyles);
|
||||
|
||||
this._pixiObject.anchor.x = 0.5;
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
this._pixiContainer.addChild(this._pixiObject);
|
||||
this.update();
|
||||
}
|
||||
RenderedBBTextInstance.prototype = Object.create(
|
||||
RenderedInstance.prototype
|
||||
);
|
||||
|
||||
/**
|
||||
* Return the path to the thumbnail of the specified object.
|
||||
*/
|
||||
RenderedBBTextInstance.getThumbnail = function(
|
||||
project,
|
||||
resourcesLoader,
|
||||
object
|
||||
) {
|
||||
return 'JsPlatform/Extensions/bbcode24.png';
|
||||
};
|
||||
|
||||
/**
|
||||
* This is called to update the PIXI object on the scene editor
|
||||
*/
|
||||
RenderedBBTextInstance.prototype.update = function() {
|
||||
const rawText = this._associatedObject
|
||||
.getProperties(this.project)
|
||||
.get('text')
|
||||
.getValue();
|
||||
if (rawText !== this._pixiObject.text) {
|
||||
this._pixiObject.setText(rawText);
|
||||
}
|
||||
|
||||
const opacity = this._associatedObject
|
||||
.getProperties(this.project)
|
||||
.get('opacity')
|
||||
.getValue();
|
||||
this._pixiObject.alpha = opacity / 255;
|
||||
|
||||
const color = this._associatedObject
|
||||
.getProperties(this.project)
|
||||
.get('color')
|
||||
.getValue();
|
||||
this._pixiObject.textStyles.default.fill = color;
|
||||
|
||||
const fontSize = this._associatedObject
|
||||
.getProperties(this.project)
|
||||
.get('fontSize')
|
||||
.getValue();
|
||||
this._pixiObject.textStyles.default.fontSize = `${fontSize}px`;
|
||||
|
||||
const fontFamily = this._associatedObject
|
||||
.getProperties(this.project)
|
||||
.get('fontFamily')
|
||||
.getValue();
|
||||
this._pixiObject.textStyles.default.fontFamily = fontFamily;
|
||||
|
||||
const wordWrap = this._associatedObject
|
||||
.getProperties(this.project)
|
||||
.get('wordWrap')
|
||||
.getValue();
|
||||
if (wordWrap !== this._pixiObject._style.wordWrap) {
|
||||
this._pixiObject._style.wordWrap = wordWrap === 'true';
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
|
||||
const align = this._associatedObject
|
||||
.getProperties(this.project)
|
||||
.get('align')
|
||||
.getValue();
|
||||
if (align !== this._pixiObject._style.align) {
|
||||
this._pixiObject._style.align = align;
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
|
||||
this._pixiObject.position.x =
|
||||
this._instance.getX() + this._pixiObject.width / 2;
|
||||
this._pixiObject.position.y =
|
||||
this._instance.getY() + this._pixiObject.height / 2;
|
||||
this._pixiObject.rotation = RenderedInstance.toRad(
|
||||
this._instance.getAngle()
|
||||
);
|
||||
|
||||
if (this._instance.hasCustomSize() && this._pixiObject) {
|
||||
const customWidth = this._instance.getCustomWidth();
|
||||
if (
|
||||
this._pixiObject &&
|
||||
this._pixiObject.textStyles.default.wordWrapWidth !== customWidth
|
||||
) {
|
||||
this._pixiObject._style.wordWrapWidth = customWidth;
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the width of the instance, when it's not resized.
|
||||
*/
|
||||
RenderedBBTextInstance.prototype.getDefaultWidth = function() {
|
||||
return this._pixiObject.width;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the height of the instance, when it's not resized.
|
||||
*/
|
||||
RenderedBBTextInstance.prototype.getDefaultHeight = function() {
|
||||
return this._pixiObject.height;
|
||||
};
|
||||
|
||||
objectsRenderingService.registerInstanceRenderer(
|
||||
'BBText::BBText',
|
||||
RenderedBBTextInstance
|
||||
);
|
||||
},
|
||||
};
|
112
Extensions/BBText/bbtextruntimeobject-pixi-renderer.js
Normal file
112
Extensions/BBText/bbtextruntimeobject-pixi-renderer.js
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* The PIXI.js renderer for the BBCode Text runtime object.
|
||||
*
|
||||
* @class BBTextRuntimeObjectPixiRenderer
|
||||
* @constructor
|
||||
* @param {gdjs.BBTextRuntimeObject} runtimeObject The object to render
|
||||
* @param {gdjs.RuntimeScene} runtimeScene The gdjs.RuntimeScene in which the object is
|
||||
*/
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer = function(runtimeObject, runtimeScene) {
|
||||
this._object = runtimeObject;
|
||||
|
||||
// Load (or reset) the text
|
||||
if (this._pixiObject === undefined) {
|
||||
this._pixiObject = new MultiStyleText(runtimeObject._text, {
|
||||
default: {
|
||||
fontFamily: runtimeObject._fontFamily,
|
||||
fontSize: runtimeObject._fontSize + 'px',
|
||||
fill: runtimeObject._color,
|
||||
tagStyle: 'bbcode',
|
||||
wordWrap: runtimeObject._wordWrap,
|
||||
wordWrapWidth: runtimeObject._wrappingWidth,
|
||||
align: runtimeObject._align,
|
||||
},
|
||||
});
|
||||
|
||||
this._object.hidden = !runtimeObject._visible;
|
||||
} else {
|
||||
this.updateColor();
|
||||
this.updateAlignment();
|
||||
this.updateFontFamily();
|
||||
this.updateFontSize();
|
||||
}
|
||||
|
||||
runtimeScene
|
||||
.getLayer('')
|
||||
.getRenderer()
|
||||
.addRendererObject(this._pixiObject, runtimeObject.getZOrder());
|
||||
|
||||
// Set the anchor in the center, so that the object rotates around
|
||||
// its center
|
||||
this._pixiObject.anchor.x = 0.5;
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
|
||||
this.updateText();
|
||||
this.updatePosition();
|
||||
this.updateAngle();
|
||||
this.updateOpacity();
|
||||
this.updateVisible();
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectRenderer = gdjs.BBTextRuntimeObjectPixiRenderer;
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.getRendererObject = function() {
|
||||
return this._pixiObject;
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.updateWordWrap = function() {
|
||||
this._pixiObject._style.wordWrap = this._object._wordWrap;
|
||||
this._pixiObject.dirty = true;
|
||||
this.updatePosition();
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.updateWrappingWidth = function() {
|
||||
this._pixiObject._style.wordWrapWidth = this._object._wrappingWidth;
|
||||
this._pixiObject.dirty = true;
|
||||
this.updatePosition();
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.updateText = function() {
|
||||
this._pixiObject.setText(this._object._text);
|
||||
this.updatePosition();
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.updateColor = function() {
|
||||
this._pixiObject.textStyles.default.fill = this._object._color;
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.updateAlignment = function() {
|
||||
this._pixiObject._style.align = this._object._align;
|
||||
this._pixiObject.dirty = true;
|
||||
};
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.updateFontFamily = function() {
|
||||
this._pixiObject.textStyles.default.fontFamily = this._object._fontFamily;
|
||||
};
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.updateFontSize = function() {
|
||||
this._pixiObject.textStyles.default.fontSize = this._object._fontSize + 'px';
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.updatePosition = function() {
|
||||
this._pixiObject.position.x = this._object.x + this._pixiObject.width / 2;
|
||||
this._pixiObject.position.y = this._object.y + this._pixiObject.height / 2;
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.updateVisible = function() {
|
||||
this._pixiObject.hidden = !this._object._visible;
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.updateAngle = function() {
|
||||
this._pixiObject.rotation = gdjs.toRad(this._object.angle);
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.updateOpacity = function() {
|
||||
this._pixiObject.alpha = this._object._opacity / 255;
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.getWidth = function() {
|
||||
return this._pixiObject.width;
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObjectPixiRenderer.prototype.getHeight = function() {
|
||||
return this._pixiObject.height;
|
||||
};
|
200
Extensions/BBText/bbtextruntimeobject.js
Normal file
200
Extensions/BBText/bbtextruntimeobject.js
Normal file
@@ -0,0 +1,200 @@
|
||||
/**
|
||||
* Displays a rich text using BBCode markup (allowing to set parts of the text as bold, italic, use different colors and shadows).
|
||||
* @memberof gdjs
|
||||
* @class BBTextRuntimeObject
|
||||
* @extends RuntimeObject
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject = function(runtimeScene, objectData) {
|
||||
gdjs.RuntimeObject.call(this, runtimeScene, objectData);
|
||||
|
||||
/** @type number */
|
||||
this._opacity = objectData.content.opacity;
|
||||
/** @type boolean */
|
||||
this._visible = objectData.content.visible;
|
||||
/** @type string */
|
||||
this._text = objectData.content.text;
|
||||
/** @type string */
|
||||
this._color = objectData.content.color;
|
||||
/** @type string */
|
||||
this._fontFamily = objectData.content.fontFamily;
|
||||
/** @type number */
|
||||
this._fontSize = objectData.content.fontSize;
|
||||
/** @type boolean */
|
||||
this._wordWrap = objectData.content.wordWrap;
|
||||
/** @type number */
|
||||
this._wrappingWidth = 250; // This value is the default wrapping width of the runtime object.
|
||||
/** @type string */
|
||||
this._align = objectData.content.align;
|
||||
|
||||
if (this._renderer)
|
||||
gdjs.BBTextRuntimeObjectRenderer.call(this._renderer, this, runtimeScene);
|
||||
else
|
||||
this._renderer = new gdjs.BBTextRuntimeObjectRenderer(this, runtimeScene);
|
||||
|
||||
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
|
||||
this.onCreated();
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype = Object.create(
|
||||
gdjs.RuntimeObject.prototype
|
||||
);
|
||||
gdjs.BBTextRuntimeObject.thisIsARuntimeObjectConstructor = 'BBText::BBText';
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.getRendererObject = function() {
|
||||
return this._renderer.getRendererObject();
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the extra parameters that could be set for an instance.
|
||||
* @private
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject.prototype.extraInitializationFromInitialInstance = function(
|
||||
initialInstanceData
|
||||
) {
|
||||
// The wrapping width value (this._wrappingWidth) is using the object's width as an innitial value
|
||||
if (initialInstanceData.customSize)
|
||||
this.setWrappingWidth(initialInstanceData.width);
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.onDestroyFromScene = function(runtimeScene) {
|
||||
gdjs.RuntimeObject.prototype.onDestroyFromScene.call(this, runtimeScene);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set/Get BBText base style properties
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject.prototype.setBBText = function(text) {
|
||||
this._text = text;
|
||||
this._renderer.updateText();
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.getBBText = function() {
|
||||
return this._text;
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.setColor = function(rgbColorString) {
|
||||
const splitValue = rgbColorString.split(';');
|
||||
if (splitValue.length !== 3) return;
|
||||
const hexColor =
|
||||
'#' +
|
||||
gdjs.rgbToHex(
|
||||
parseInt(splitValue[0], 0),
|
||||
parseInt(splitValue[1], 0),
|
||||
parseInt(splitValue[2], 0)
|
||||
);
|
||||
this._color = hexColor;
|
||||
this._renderer.updateColor();
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.getColor = function() {
|
||||
return this._color;
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.setFontSize = function(fontSize) {
|
||||
this._fontSize = fontSize;
|
||||
this._renderer.updateFontSize();
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.getFontSize = function() {
|
||||
return this._fontSize;
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.setFontFamily = function(fontFamily) {
|
||||
this._fontFamily = fontFamily;
|
||||
this._renderer.updateFontFamily();
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.getFontFamily = function() {
|
||||
return this._fontFamily;
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.setAlignment = function(align) {
|
||||
this._align = align;
|
||||
this._renderer.updateAlignment();
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.getAlignment = function() {
|
||||
return this._align;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set object position on X axis.
|
||||
* @param {number} x The new position X of the object.
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject.prototype.setX = function(x) {
|
||||
gdjs.RuntimeObject.prototype.setX.call(this, x);
|
||||
this._renderer.updatePosition();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set object position on Y axis.
|
||||
* @param {number} y The new position Y of the object.
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject.prototype.setY = function(y) {
|
||||
gdjs.RuntimeObject.prototype.setY.call(this, y);
|
||||
this._renderer.updatePosition();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the angle of the object.
|
||||
* @param {number} angle The new angle of the object.
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject.prototype.setAngle = function(angle) {
|
||||
gdjs.RuntimeObject.prototype.setAngle.call(this, angle);
|
||||
this._renderer.updateAngle();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set object opacity.
|
||||
* @param {number} opacity The new opacity of the object (0-255).
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject.prototype.setOpacity = function(opacity) {
|
||||
this._opacity = opacity;
|
||||
this._renderer.updateOpacity();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get object opacity.
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject.prototype.getOpacity = function() {
|
||||
return this._opacity;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the width.
|
||||
* @param {number} width The new width in pixels.
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject.prototype.setWrappingWidth = function(width) {
|
||||
this._wrappingWidth = width;
|
||||
this._renderer.updateWrappingWidth();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the wrapping width of the object.
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject.prototype.getWrappingWidth = function() {
|
||||
return this._wrappingWidth;
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.setWordWrap = function(wordWrap) {
|
||||
this._wordWrap = wordWrap;
|
||||
this._renderer.updateWordWrap();
|
||||
};
|
||||
|
||||
gdjs.BBTextRuntimeObject.prototype.getWordWrap = function(wordWrap) {
|
||||
return this._wordWrap;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the width of the object.
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject.prototype.getWidth = function() {
|
||||
return this._renderer.getWidth();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the height of the object.
|
||||
*/
|
||||
gdjs.BBTextRuntimeObject.prototype.getHeight = function() {
|
||||
return this._renderer.getHeight();
|
||||
};
|
9
Extensions/BBText/pixi-multistyle-text/README.md
Normal file
9
Extensions/BBText/pixi-multistyle-text/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
This extension is using release version 0.8.0 (commit 336bed0b206043e2c3e81c373b7ca02094ecabe7) of the pixi-multistyle-text library:
|
||||
https://github.com/tleunen/pixi-multistyle-text
|
||||
|
||||
The BBcode tag feature was especially added for Gdevelop and this extension (commit 2a7be2084598933502c76419d7a86c0e6cd11719)
|
||||
|
||||
README:
|
||||
Add a MultiStyleText object inside pixi.js to easily create text using different styles.
|
||||
|
||||
License: MIT
|
2
Extensions/BBText/pixi-multistyle-text/dist/pixi-multistyle-text.umd.js
vendored
Normal file
2
Extensions/BBText/pixi-multistyle-text/dist/pixi-multistyle-text.umd.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
Extensions/BBText/pixi-multistyle-text/dist/pixi-multistyle-text.umd.js.map
vendored
Normal file
1
Extensions/BBText/pixi-multistyle-text/dist/pixi-multistyle-text.umd.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
newIDE/app/public/JsPlatform/Extensions/bbcode16.png
Normal file
BIN
newIDE/app/public/JsPlatform/Extensions/bbcode16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 548 B |
BIN
newIDE/app/public/JsPlatform/Extensions/bbcode24.png
Normal file
BIN
newIDE/app/public/JsPlatform/Extensions/bbcode24.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 748 B |
BIN
newIDE/app/public/JsPlatform/Extensions/bbcode32.png
Normal file
BIN
newIDE/app/public/JsPlatform/Extensions/bbcode32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 950 B |
19
newIDE/app/public/external/utils/path-editor.js
vendored
19
newIDE/app/public/external/utils/path-editor.js
vendored
@@ -120,7 +120,7 @@ export const createPathEditorHeader = ({
|
||||
headerObject.saveFolderLabel.title =
|
||||
'Changing the path is disabled on imported GD animations!';
|
||||
headerObject.setFolderButton.removeEventListener('click', selectFolderPath);
|
||||
headerObject.setFolderButton.style.visibility = 'hidden';
|
||||
headerObject.setFolderButton.style.display = 'none';
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -151,19 +151,26 @@ export const createPathEditorHeader = ({
|
||||
|
||||
const render = headerObject => {
|
||||
const pathEditorVisibility = headerObject.state.visible
|
||||
? 'visibility:visible'
|
||||
: 'visibility:hidden;';
|
||||
? 'display:visible'
|
||||
: 'display:none;';
|
||||
headerObject.rightButtons.style = pathEditorVisibility;
|
||||
headerObject.root.style = pathEditorVisibility;
|
||||
|
||||
headerObject.hideButton.textContent = headerObject.state.visible ? '>' : '<';
|
||||
headerObject.hideButton.textContent = headerObject.state.visible
|
||||
? '>'
|
||||
: '...';
|
||||
|
||||
headerObject.hideButton.title = headerObject.state.visible
|
||||
? 'Hide save path options'
|
||||
: 'Open save path options';
|
||||
|
||||
headerObject.hideButton.style = headerObject.state.visible
|
||||
? 'opacity: 1'
|
||||
? 'opacity: 1; margin-right: 3px;'
|
||||
: 'opacity:0.5';
|
||||
|
||||
headerObject.root.parentElement.style = headerObject.state.visible
|
||||
? 'position: relative; display:flex; width:100%'
|
||||
: 'position: absolute; display:flex; width:100%';
|
||||
: 'position: absolute; display:flex; width:40px; height:40px; right:0';
|
||||
|
||||
headerObject.nameInput.value = headerObject.nameInput.value.replace(
|
||||
/[^a-zA-Z0-9_-]/g,
|
||||
|
@@ -0,0 +1 @@
|
||||
This shows how to change the bbcode text of a BBText object displayed on the screen.
|
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@
|
||||
"macExecutableFilename": "",
|
||||
"orientation": "landscape",
|
||||
"packageName": "com.example.platformer",
|
||||
"projectFile": "/home/fox/DEV/GDevelop/newIDE/app/resources/examples/yarn-dialogue/yarn-dialogue.json",
|
||||
"projectFile": "/home/fox/DEV/GDevelop/newIDE/app/resources/examples/dialogue-tree-with-yarn/dialogue-tree-with-yarn.json",
|
||||
"scaleMode": "linear",
|
||||
"sizeOnStartupMode": "adaptWidth",
|
||||
"useExternalSourceFiles": false,
|
||||
@@ -796,13 +796,6 @@
|
||||
"smoothed": true,
|
||||
"userAdded": true
|
||||
},
|
||||
{
|
||||
"file": "dialogueData/npcs.json",
|
||||
"kind": "json",
|
||||
"metadata": "",
|
||||
"name": "dialogueData/npcs.json",
|
||||
"userAdded": true
|
||||
},
|
||||
{
|
||||
"alwaysLoaded": false,
|
||||
"file": "NewObject2-1.png",
|
||||
@@ -811,6 +804,14 @@
|
||||
"name": "NewObject2-1.png",
|
||||
"smoothed": true,
|
||||
"userAdded": false
|
||||
},
|
||||
{
|
||||
"disablePreload": false,
|
||||
"file": "dialogueData/npcs.json",
|
||||
"kind": "json",
|
||||
"metadata": "",
|
||||
"name": "dialogueData/npcs.json",
|
||||
"userAdded": false
|
||||
}
|
||||
],
|
||||
"resourceFolders": []
|
||||
@@ -921,10 +922,10 @@
|
||||
"name": "avatars"
|
||||
},
|
||||
{
|
||||
"name": "dialogueTextObject"
|
||||
"name": "questionChoicesText"
|
||||
},
|
||||
{
|
||||
"name": "questionChoicesText"
|
||||
"name": "DialogueTreeBBtextObject"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1596,21 +1597,6 @@
|
||||
"stringProperties": [],
|
||||
"initialVariables": []
|
||||
},
|
||||
{
|
||||
"angle": 0,
|
||||
"customSize": true,
|
||||
"height": 81,
|
||||
"layer": "GUI",
|
||||
"locked": false,
|
||||
"name": "dialogueTextObject",
|
||||
"width": 533,
|
||||
"x": 110,
|
||||
"y": 115,
|
||||
"zOrder": 43,
|
||||
"numberProperties": [],
|
||||
"stringProperties": [],
|
||||
"initialVariables": []
|
||||
},
|
||||
{
|
||||
"angle": 0,
|
||||
"customSize": false,
|
||||
@@ -1975,6 +1961,21 @@
|
||||
"numberProperties": [],
|
||||
"stringProperties": [],
|
||||
"initialVariables": []
|
||||
},
|
||||
{
|
||||
"angle": 0,
|
||||
"customSize": true,
|
||||
"height": 79,
|
||||
"layer": "GUI",
|
||||
"locked": false,
|
||||
"name": "DialogueTreeBBtextObject",
|
||||
"width": 543,
|
||||
"x": 108,
|
||||
"y": 98,
|
||||
"zOrder": 47,
|
||||
"numberProperties": [],
|
||||
"stringProperties": [],
|
||||
"initialVariables": []
|
||||
}
|
||||
],
|
||||
"objects": [
|
||||
@@ -5120,25 +5121,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"name": "dialogueTextObject",
|
||||
"smoothed": true,
|
||||
"tags": "",
|
||||
"type": "TextObject::Text",
|
||||
"underlined": false,
|
||||
"variables": [],
|
||||
"behaviors": [],
|
||||
"string": "Text",
|
||||
"font": "",
|
||||
"characterSize": 20,
|
||||
"color": {
|
||||
"b": 61,
|
||||
"g": 44,
|
||||
"r": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"bold": false,
|
||||
"italic": true,
|
||||
@@ -5375,6 +5357,23 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DialogueTreeBBtextObject",
|
||||
"tags": "",
|
||||
"type": "BBText::BBText",
|
||||
"variables": [],
|
||||
"behaviors": [],
|
||||
"content": {
|
||||
"text": "[b]bold[/b] [i]italic[/i] [size=15]smaller[/size] [font=times]times[/font] font\n[spacing=12]spaced out[/spacing]\n[outline=yellow]outlined[/outline] [shadow=red]DropShadow[/shadow] ",
|
||||
"opacity": 255,
|
||||
"fontSize": "20",
|
||||
"visible": true,
|
||||
"color": "#000000",
|
||||
"fontFamily": "Arial",
|
||||
"align": "left",
|
||||
"wordWrap": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
@@ -5540,7 +5539,7 @@
|
||||
"colorR": 74,
|
||||
"creationTime": 0,
|
||||
"disabled": false,
|
||||
"folded": true,
|
||||
"folded": false,
|
||||
"name": "Other gameplay mechanics",
|
||||
"source": "",
|
||||
"type": "BuiltinCommonInstructions::Group",
|
||||
@@ -5618,16 +5617,6 @@
|
||||
"textBg"
|
||||
],
|
||||
"subInstructions": []
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"inverted": false,
|
||||
"value": "Cache"
|
||||
},
|
||||
"parameters": [
|
||||
"dialogueTextObject"
|
||||
],
|
||||
"subInstructions": []
|
||||
}
|
||||
],
|
||||
"events": []
|
||||
@@ -6559,6 +6548,16 @@
|
||||
"dialogueData/npcs.json"
|
||||
],
|
||||
"subInstructions": []
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"inverted": false,
|
||||
"value": "Cache"
|
||||
},
|
||||
"parameters": [
|
||||
"textHud"
|
||||
],
|
||||
"subInstructions": []
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
@@ -6938,10 +6937,10 @@
|
||||
{
|
||||
"type": {
|
||||
"inverted": false,
|
||||
"value": "TextObject::String"
|
||||
"value": "BBText::SetBBText"
|
||||
},
|
||||
"parameters": [
|
||||
"dialogueTextObject",
|
||||
"DialogueTreeBBtextObject",
|
||||
"=",
|
||||
"DialogueTree::ClippedLineText()"
|
||||
],
|
||||
|
@@ -2,20 +2,20 @@
|
||||
{
|
||||
"title": "Start",
|
||||
"tags": "",
|
||||
"body": "<<avatar sign>> Press Z to interact with the tree critters 🐜🐛🐞 Spacebar to jump. \nAnd welcome to yarn's example GD project! ",
|
||||
"body": "<<avatar sign>> [color=#e90b0b]Press Z[/color] to interact with the tree critters 🐜🐛🐞 [color=#07a9b0]Spacebar[/color] to jump.\nAnd welcome to yarn's example GD project!",
|
||||
"position": {
|
||||
"x": -2074,
|
||||
"y": 220
|
||||
"x": -2144,
|
||||
"y": 468
|
||||
},
|
||||
"colorID": 0
|
||||
},
|
||||
{
|
||||
"title": "ant",
|
||||
"tags": "",
|
||||
"body": "<<avatar ant>>Please don't bug me now... <<wait 1000>> I am quite busy at the moment.\nHave you seen my crumb?\n[[ yes |antcrumbyes ]] [[ no |antcrumbno ]] ",
|
||||
"body": "<<avatar ant>>[b]Please don't bug me now[/b]... <<wait 1000>> I am [i]quite[/i] busy at the moment.\nHave you seen my crumb?\n[[ yes |antcrumbyes ]] [[ no |antcrumbno ]] ",
|
||||
"position": {
|
||||
"x": -1808,
|
||||
"y": 222
|
||||
"x": -1878,
|
||||
"y": 470
|
||||
},
|
||||
"colorID": 0
|
||||
},
|
||||
@@ -24,18 +24,18 @@
|
||||
"tags": "",
|
||||
"body": "<<if $seenCrumb == true>>\nOh yeah? You saw it on a branch?\nDid you taste it?...\n<<else>>\nOh ha-ha! I can see that you are lying.\n<<endif>>",
|
||||
"position": {
|
||||
"x": -2016,
|
||||
"y": 504
|
||||
"x": -2086,
|
||||
"y": 752
|
||||
},
|
||||
"colorID": 3
|
||||
},
|
||||
{
|
||||
"title": "antcrumbno",
|
||||
"tags": "",
|
||||
"body": "Then scram!\nI don't have time for you...",
|
||||
"body": "Then [b]scram[/b]!\nI don't have time for you...",
|
||||
"position": {
|
||||
"x": -1624,
|
||||
"y": 496
|
||||
"x": -1694,
|
||||
"y": 744
|
||||
},
|
||||
"colorID": 0
|
||||
},
|
||||
@@ -44,8 +44,8 @@
|
||||
"tags": "",
|
||||
"body": "<<avatar crumb>> <<set $seenCrumb to true >> You stumbled on a giant crumb.\nWhat would you like to do with it?\n[[ taste it | eatCrumb]] [[ take it| takeCrumb]] [[ nothing |null ]] ",
|
||||
"position": {
|
||||
"x": -1821,
|
||||
"y": 726
|
||||
"x": -1891,
|
||||
"y": 974
|
||||
},
|
||||
"colorID": 6
|
||||
},
|
||||
@@ -54,8 +54,8 @@
|
||||
"tags": "",
|
||||
"body": "Let see <<wait 1000>>.<<wait 200>>.<<wait 200>> .<<wait 200>>these 🥨 are making you thirsty...",
|
||||
"position": {
|
||||
"x": -2035,
|
||||
"y": 977
|
||||
"x": -2105,
|
||||
"y": 1225
|
||||
},
|
||||
"colorID": 0
|
||||
},
|
||||
@@ -64,8 +64,8 @@
|
||||
"tags": "",
|
||||
"body": "The thing is way too heavy 😬 ....",
|
||||
"position": {
|
||||
"x": -1600,
|
||||
"y": 964
|
||||
"x": -1670,
|
||||
"y": 1212
|
||||
},
|
||||
"colorID": 0
|
||||
},
|
||||
@@ -74,8 +74,8 @@
|
||||
"tags": "",
|
||||
"body": "<<wait 100>> ",
|
||||
"position": {
|
||||
"x": -1520,
|
||||
"y": 727
|
||||
"x": -1590,
|
||||
"y": 975
|
||||
},
|
||||
"colorID": 0
|
||||
}
|
||||
|
@@ -61,6 +61,13 @@ const jsExtensions = [
|
||||
extensionModule: require('GDJS-for-web-app-only/Runtime/Extensions/DialogueTree/JsExtension.js'),
|
||||
objectsRenderingServiceModules: {},
|
||||
},
|
||||
{
|
||||
name: 'BBText',
|
||||
extensionModule: require('GDJS-for-web-app-only/Runtime/Extensions/BBText/JsExtension.js'),
|
||||
objectsRenderingServiceModules: {
|
||||
'pixi-multistyle-text/dist/pixi-multistyle-text.umd': require('GDJS-for-web-app-only/Runtime/Extensions/BBText/pixi-multistyle-text/dist/pixi-multistyle-text.umd'),
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
type MakeExtensionsLoaderArguments = {|
|
||||
|
@@ -122,6 +122,34 @@ export default (
|
||||
},
|
||||
getLabel,
|
||||
};
|
||||
} else if (valueType === 'color') {
|
||||
return {
|
||||
name,
|
||||
valueType: 'color',
|
||||
getValue: (instance: Instance): string => {
|
||||
return getProperties(instance)
|
||||
.get(name)
|
||||
.getValue();
|
||||
},
|
||||
setValue: (instance: Instance, newValue: string) => {
|
||||
onUpdateProperty(instance, name, newValue);
|
||||
},
|
||||
getLabel,
|
||||
};
|
||||
} else if (valueType === 'textarea') {
|
||||
return {
|
||||
name,
|
||||
valueType: 'textarea',
|
||||
getValue: (instance: Instance): string => {
|
||||
return getProperties(instance)
|
||||
.get(name)
|
||||
.getValue();
|
||||
},
|
||||
setValue: (instance: Instance, newValue: string) => {
|
||||
onUpdateProperty(instance, name, newValue);
|
||||
},
|
||||
getLabel,
|
||||
};
|
||||
} else {
|
||||
console.error(
|
||||
`A property with type=${valueType} could not be mapped to a field. Ensure that this type is correct and understood by the IDE.`
|
||||
|
@@ -10,6 +10,9 @@ import FlatButton from '../UI/FlatButton';
|
||||
import SelectField from '../UI/SelectField';
|
||||
import SelectOption from '../UI/SelectOption';
|
||||
import Edit from '@material-ui/icons/Edit';
|
||||
import ColorField from '../UI/ColorField';
|
||||
import { hexToRGBColor } from '../Utils/ColorTransformer';
|
||||
|
||||
import {
|
||||
type ResourceKind,
|
||||
type ResourceSource,
|
||||
@@ -56,6 +59,18 @@ export type PrimitiveValueField =
|
||||
getValue: Instance => boolean,
|
||||
setValue: (instance: Instance, newValue: boolean) => void,
|
||||
...ValueFieldCommonProperties,
|
||||
|}
|
||||
| {|
|
||||
valueType: 'color',
|
||||
getValue: Instance => string,
|
||||
setValue: (instance: Instance, newValue: string) => void,
|
||||
...ValueFieldCommonProperties,
|
||||
|}
|
||||
| {|
|
||||
valueType: 'textarea',
|
||||
getValue: Instance => string,
|
||||
setValue: (instance: Instance, newValue: string) => void,
|
||||
...ValueFieldCommonProperties,
|
||||
|};
|
||||
|
||||
// "Resource" fields are showing a resource selector.
|
||||
@@ -209,6 +224,41 @@ export default class PropertiesEditor extends React.Component<Props, {||}> {
|
||||
disabled={field.disabled}
|
||||
/>
|
||||
);
|
||||
} else if (field.valueType === 'color') {
|
||||
const { setValue } = field;
|
||||
return (
|
||||
<ColorField
|
||||
key={field.name}
|
||||
id={field.name}
|
||||
floatingLabelText={getFieldLabel(this.props.instances, field)}
|
||||
disableAlpha
|
||||
fullWidth
|
||||
color={hexToRGBColor(getFieldValue(this.props.instances, field))}
|
||||
onChangeComplete={color => {
|
||||
this.props.instances.forEach(i =>
|
||||
setValue(i, color.hex || '#000000')
|
||||
);
|
||||
this._onInstancesModified(this.props.instances);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else if (field.valueType === 'textarea') {
|
||||
const { setValue } = field;
|
||||
return (
|
||||
<SemiControlledTextField
|
||||
key={field.name}
|
||||
id={field.name}
|
||||
onChange={text => {
|
||||
this.props.instances.forEach(i => setValue(i, text || ''));
|
||||
this._onInstancesModified(this.props.instances);
|
||||
}}
|
||||
value={getFieldValue(this.props.instances, field)}
|
||||
floatingLabelText={getFieldLabel(this.props.instances, field)}
|
||||
floatingLabelFixed
|
||||
multiLine
|
||||
style={styles.field}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
const { onEditButtonClick, setValue } = field;
|
||||
return (
|
||||
|
@@ -11,3 +11,16 @@ export const rgbToHex = (r: number, g: number, b: number) =>
|
||||
*/
|
||||
export const rgbToHexNumber = (r: number, g: number, b: number) =>
|
||||
(r << 16) + (g << 8) + b;
|
||||
|
||||
/**
|
||||
* Convert a hex color value to an rgb object value.
|
||||
*/
|
||||
export const hexToRGBColor = (hex: string) => {
|
||||
const hexNumber = parseInt(hex.replace('#', ''), 16);
|
||||
return {
|
||||
r: (hexNumber >> 16) & 0xff,
|
||||
g: (hexNumber >> 8) & 0xff,
|
||||
b: hexNumber & 0xff,
|
||||
a: 255,
|
||||
};
|
||||
};
|
||||
|
Reference in New Issue
Block a user