Text Plugin
The Clay Text plugin provides advanced text processing capabilities for Clayground applications, including CSV file handling, text highlighting with regular expressions, and JSON data transformation using JSONata query language. It’s ideal for data-driven games, configuration management, and text-based game features.
Getting Started
To use the Clay Text plugin in your QML files:
import Clayground.Text
Core Components
- CsvModel - High-level component combining CSV reading/writing with a TableModel for UI display and data binding.
- CsvReader - Low-level CSV file reader that emits signals for column headers and each row.
- CsvWriter - Low-level CSV file writer for creating CSV files programmatically.
- HighlightedText - TextArea with regular expression highlighting support for search and emphasis.
- TextHighlighter - Low-level syntax highlighter for QML text documents.
- JsonataTransform - JSONata query processor for powerful JSON data transformation and querying.
Usage Examples
Game Configuration from CSV
import Clayground.Text
Item {
CsvModel {
id: enemyConfig
source: "enemies.csv"
Component.onCompleted: load()
}
function spawnEnemies() {
for (let i = 0; i < enemyConfig.tableModel.rowCount; i++) {
let enemy = enemyConfig.tableModel.rows[i]
createEnemy({
type: enemy.type,
health: parseInt(enemy.health),
damage: parseInt(enemy.damage),
speed: parseFloat(enemy.speed)
})
}
}
}
Filtering Game Data
CsvModel {
id: itemDatabase
source: "items.csv"
// Only load weapons
colFilter: (colName) => {
return ["id", "name", "type", "damage", "rarity"].includes(colName)
}
// Only rare or legendary items
rowFilter: (vals) => {
let rarity = vals[colNames.indexOf("rarity")]
return rarity === "rare" || rarity === "legendary"
}
// Transform damage values
rowTransform: (vals) => {
let damageIdx = colNames.indexOf("damage")
vals[damageIdx] = (parseInt(vals[damageIdx]) * 1.5).toString()
return vals
}
}
Saving High Scores
CsvWriter {
id: scoreWriter
destination: "highscores.csv"
function saveHighScores(scores) {
begin(["rank", "player", "score", "date"])
for (let i = 0; i < scores.length; i++) {
appendRow([
(i + 1).toString(),
scores[i].player,
scores[i].score.toString(),
scores[i].date
])
}
finish()
}
}
Text Search in Game
HighlightedText {
id: questLog
width: parent.width
height: 200
// Highlight quest objectives
searchRegEx: "\\b(kill|collect|find|talk to)\\b"
text: `
Current Quest: The Lost Artifact
Objectives:
- Talk to the village elder
- Find the ancient map
- Collect 5 mystic gems
- Kill the dragon boss
`
}
Dynamic Data Transformation
JsonataTransform {
id: inventoryTransform
inputObject: {
"inventory": [
{"item": "sword", "quantity": 1, "value": 100},
{"item": "potion", "quantity": 5, "value": 20},
{"item": "armor", "quantity": 1, "value": 150}
]
}
// Calculate total inventory value
jsonataString: "$sum(inventory.(quantity * value))"
Text {
text: "Total inventory value: " + inventoryTransform.jsonOutput
}
}
Complex Game Statistics
JsonataTransform {
id: gameStats
inputObject: playerData
// Find best performing weapon
jsonataString: `
weapons[damage = $max(weapons.damage)] {
"name": name,
"damage": damage,
"efficiency": damage / weight
}
`
onJsonOutputChanged: {
console.log("Best weapon:", JSON.stringify(jsonOutput))
}
}
Localization System
Item {
property string language: "en"
CsvModel {
id: translations
source: "translations.csv"
rowFilter: (vals) => {
return vals[0] === language
}
Component.onCompleted: load()
}
function translate(key) {
for (let i = 0; i < translations.tableModel.rowCount; i++) {
let row = translations.tableModel.rows[i]
if (row.key === key) {
return row.text
}
}
return key
}
}
Quest Dialog System
HighlightedText {
id: dialogText
// Highlight character names
searchRegEx: "^\\[([^\\]]+)\\]:"
property var dialogData: []
property int currentLine: 0
CsvReader {
source: "dialog_quest_01.csv"
onRow: (values) => {
dialogData.push({
character: values[0],
text: values[1],
choices: values[2]
})
}
Component.onCompleted: load()
}
function showCurrentDialog() {
if (currentLine < dialogData.length) {
text = `[${dialogData[currentLine].character}]: ${dialogData[currentLine].text}`
}
}
}
Best Practices
-
CSV Format: Use consistent delimiters and quote characters across your data files.
-
Data Validation: Always validate data types when reading from CSV (use parseInt, parseFloat).
-
Performance: For large CSV files, use filters to reduce memory usage.
-
JSONata Queries: Test complex queries incrementally to ensure correctness.
-
File Paths: Use appropriate paths for different platforms (consider using StandardPaths).
-
Encoding: Ensure CSV files use UTF-8 encoding for international characters.
Technical Implementation
The Clay Text plugin provides:
- CSV Processing: Built on the robust csv-parser library
- Table Model Integration: Automatic TableModel generation for Qt Quick views
- Regex Highlighting: QSyntaxHighlighter implementation for text marking
- JSONata Engine: Full JSONata query language support for JSON transformation
- Streaming Support: Efficient handling of large CSV files
- Unicode Support: Proper handling of international characters
The plugin handles various text processing needs from simple CSV configuration files to complex data transformations, making it versatile for data-driven game development.