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

  1. CSV Format: Use consistent delimiters and quote characters across your data files.

  2. Data Validation: Always validate data types when reading from CSV (use parseInt, parseFloat).

  3. Performance: For large CSV files, use filters to reduce memory usage.

  4. JSONata Queries: Test complex queries incrementally to ensure correctness.

  5. File Paths: Use appropriate paths for different platforms (consider using StandardPaths).

  6. 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.