Tiled API scripting: extras

I have implemented a custom tile inserter, but I was wondering if the script had access to the floating, transparent image of the currently selected tile.

image

I am also attempting to change an object’s name based on a somewhat static property.

For example. When I select my item’s name, I want to somehow change the name of the object. Is this possible?

It did seem like Interface Signal would be my answer, but there is nothing I see that shows Property Changed, etc. :frowning:

Do you mean tiled.mapEditor.currentBrush? When you mean how to control it for a custom tool, see Tool.preview.

Unfortunately there is currently no signal being emitted to the script when you change the property. There is also no way yet for the script to set a different text on the object’s label, the only way to change it is to actually assign to object.name.

What you could do is to register a custom action that you manually trigger, which will update the object names as appropriate. You could also attach such an update to tiled.assetAboutToBeSaved.

I can’t seem to get this to work. I am sure I am doing something wrong as its use is not too clear to me.

This is actually what I ended up doing last night. Funny you should post this option. Thanks. :slightly_smiling_face:

Which part? Are you writing a Tool, or something else? Perhaps you should share your code, or explain exactly what you’re doing, since it’s hard to help with no idea of what you’re doing.

Hello, I am actually reviewing some of your tool sources now to better understand how Tool.preview works. I thought it was much simpler and straight forward to show a preview of the currently selected object, but looking at your tool sources, it seems much more involved.

All I want to do is show a preview of the currently selected tile as a preview.

What do you mean by “your tool sources”? If you mean the scripts I’ve written: Mine are more complicated than they strictly need to be.

You need to assign a TileMap to preview, this map containing the modified tile at the correct location. The easiest way to do this consistently is to, any time you want to replace the preview (e.g. on tilePositionChanged):

//Create a new TileMap. You could reuse the old one if it exists, but then you'll need to clear any existing preview.
let preview = new TileMap();
preview.width = this.map.width; //"this" being the Tool
preview.height = this.map.height;
let layer = new TileLayer();
preview.addLayer(layer);

//Set up the actual tile(s) you want to preview
let layerEdit = layer.edit();
layerEdit.setTile(x, y, newTile, newFlags); //the tile you want to display. flags are optional.
layerEdit.apply();

this.preview = preview; //the preview is only actually updated when you assign to Tool.preview
}
1 Like

Ah, go it. Yes, your scripts were doing more than I needed. Thanks for the help. My tool is strictly for ObjectGroups so I made the necessary adjustments.

AFAIK objects cannot be displayed in previews currently, Object layers are ignored. So you’d still have to use a tile layer to preview Tile Objects if you want to preview at all. There’s an issue open about this: Scripting: Allow MapObjects in Tool previews · Issue #3383 · mapeditor/tiled · GitHub

Lol. Yes, I just realized this when all errors popped up in my console. Going to switch it back to TileLayer and try it again.

Object layers are ignored silently, they don’t create errors. The errors you saw were probably because there’s no edit() for Object layers, you can add objects directly. Only Tile Layers have TileLayerEdit, this is required by the API to enable it to group together edits and thus make modifying tile layers more performant.

I notice that you create a new instance of TileMap() each time the mouse moves to a new cell and showpreview is called. Is that necessary?

I assumed you still required preparepreview / showpreview though your above example did not indicate it as much.

As I wrote in the comment at the top of the example, no, this is not necessary. But you would need to either clear or delete and recreate the existing layer to keep the preview from showing a trail of tiles. Creating a new one each time is simpler (no need to check for an existing preview map, layer, adjust size when the current document changes, etc), and at least in my experience hasn’t caused performance issues.

All I had to do was scroll over a bit to see that. Lol.
Cool. Working on implementation now. Will let you know how it turns out. Thanks again.

Hey again.

Okay, something is still wrong. :frowning:
The tile is not showing and I have no errors. I commented out some things and tried to display all in preparepreview but still nothing. Maybe you can help me figure it out? Thanks.

// X, Y = this.tilePosition.x/y
preparePreview(x, y) {
		let preview = new TileMap();
		preview.width = this.map.width; //"this" being the Tool
		preview.height = this.map.height;
		let layer = new TileLayer();
		preview.addLayer(layer);

		const brush = tiled.mapEditor.currentBrush.layerAt(0);
		const tile = brush.tileAt(0, 0);
		tiled.log("TILE: " + tile );

		let layerEdit = layer.edit();
		layerEdit.setTile(x, y, tile, 0); //the tile you want to display. flags are optional.
		layerEdit.apply();

		// if (this.map) {
		// 	preview.setSize(this.map.width, this.map.height);
		// 	preview.setTileSize(this.map.tileWidth, this.map.tileHeight);
		// }
		this.preview = preview;
	},

	showPreview(x, y) {
		this.preparePreview(x, y);

		// if (!this.map || !this.map.currentLayer) return;

		// let currentLayer = this.map.currentLayer;
		// if (!currentLayer.isObjectLayer) return;
		
		// const brush = tiled.mapEditor.currentBrush.layerAt(0);
		// const tile = brush.tileAt(0, 0);
		// tiled.log("TILE: " + tile );

		// let layer = this.preview.layerAt(0);
		// let layerEdit = layer.edit();
		// layerEdit.setTile(x, y, tile, 0); //the tile you want to display. flags are optional.
		// layerEdit.apply();

		// this.preview = preview;
	}

Are you calling showPreview() anywhere?

Calling it here:

mouseMoved(x, y, /*, modifiers */) {
		let positionChanged = (this.lastModifiedTile.x != this.tilePosition.x || this.lastModifiedTile.y != this.tilePosition.y);

		if (positionChanged){
//			tiled.log("MOVED: " + this.tilePosition.x + ", " + this.tilePosition.y)
			this.showPreview(this.tilePosition.x, this.tilePosition.y);
			this.lastModifiedTile.x = this.tilePosition.x;
			this.lastModifiedTile.y = this.tilePosition.y;
		}
	},

Do any of your tiled.logs run, or are these methods just not getting to run at all? Nothing jumps out at me.

If the methods are running but the preview’s not working, try setting the tile size. I don’t remember whether that’s required or not. It might be, and in my code I do set it, e.g.

let preview = new TileMap();
preview.setSize(this.map.width, this.map.height);
preview.setTileSize(this.map.tileWidth, this.map.tileHeight);
preview.infinite = this.map.infinite;

By the way, you shouldn’t be using mouseMoved if you only want to do things when the mouse changes tile location. There’s tilePositionChanged for that instead, and that should also remove the need to store/check against the tile position. mouseMoved is for when you actually care about changing position within a cell.

1 Like

All logs run, and tile does contain an item. Nothing is being displayed though.

Okay, I think I got it now. I had to use this.selectedTile in order to see what I needed.

It seems to not work with ObjectGroups. TileLayers are working fine, but I only need it for ObjectGroups. Oh well. Thanks again.

@bjorn @eishiya Hey folks. My apologies for tagging you, but I have a custom tools question and did not want to start a new thread.

When adding custom tools, is it possible to get access to the flipping tools or not?

image