Code Monkey home page Code Monkey logo

tiled-scripts's Introduction

Tiled Scripts

Assorted scripts for Tiled Map Editor, written by eishiya.

Usage instructions are in the comments at the top of each script. Feel free to use these scripts as you wish. Credit appreciated but not required.

If you're new to using Tiled scripts and don't know how to install them, please see the Tiled docs on scripting. Check out more scripts from the Tiled community in mapeditor/tiled-extensions.

Brief descriptions of the scripts in this repo:

Force Edge Terrain Tool

An alternative Terrain Brush that lets you paint with Mixed Terrains as if they were edge terrains, making it easier to draw thin paths, rivers, etc without making separate Edge Terrains for them.

Large Tile Stamp Tool

Draws large tiles spaced out so they don't overlap each other. Right-click to sample tiles.

Move Tiles Tool

Allows you to move selected tiles by dragging them instead of cut+pasting, similar to image editors' Move tools. Hold shift when starting to move to copy instead of cut. Also allows nudging with the keyboard. Click to commit the move.

Replace Tile Tool

Replaces a tile with your current brush tile, either in your selected layer(s) or everywhere in the map. Unlike Select Same Tile + Bucket Fill, it reconciles the existing flips with the new ones. If you need to replace a large number of tiles and/or replace tiles across many maps, see the Mass Replace Tiles script.

Terrain Rectangle Tool

Draws a rectangle using the currently selected terrain. Allows drawing large rectangles using Terrain sets that don't include concave corners and confuse the regular Terrain tools. Ctrl to ignore existing terrains in the map.

Apply Action to Open Documents

Lets you choose any action in Tiled and run it on every open document. Useful for mass-applying scripted actions without making a separate "apply to all" action for all of them.

Automap Helper

A collection of several actions to make automapping less tedious.

Add/Remove UIDs to/from Selected Layers

Useful to temporarily give layers unique names even when Automapping requires them to be the same, to aid copypasting in multiple layers at once.

Generate Automap Layers

Creates multiple input or output layers at once, optionally filling them with tiles from your brush.

Convert Brush to Layers

Takes your brush and prepares it for pasting to the Selected Layers, either by renaming the layers of a multi-layer brush to match the selected layers, or (for single-layer brushes) by moving each tile to its own layer, named to match the selected layers. This action makes it possible to multi-layer paste to different layers.

Toggle //

Adds or removes // to/from selected layers' names, either individually or based on the comment state of the bottom layer. Hotkey this to quickly mark layers as ignored for Automapping in Tiled 1.8+.

Center View on Map

Centres the current map view on the map, useful to quickly go back to a map after panning around a large World.

Copy+Paste Animations

Copies/pastes tile animations. It can copy the frames exactly, or adjust the frames relative to the destination tile(s).

Copy+Paste Collisions

Copies/pastes tile collisions in the Tileset Editor, makes it easier to copy complex collisions across groups of tiles.

Copy+Paste Layers

Copies/pastes entire layers, including their properties along with the content. Can copy/paste multiple layers at once, regardless of layer type.

Copy+Paste Objects in Layers

Copies/pastes objects, but remembers the names of the layers they came from and pastes them and pastes them to layers of those names, enabling multi-layer copy+paste similar to that for tiles.

Copy+Paste Terrains

Copies/pastes terrains from/to selected tiles. Includes actions to copy/paste terrains exactly, as well as to copy/paste the arrangement of a particular terrain, so you can paste it as a different terrain.

Count Tiles

Counts the tiles used in a map, useful for e.g. GB Studio where the unique tiles allowed per map are limited, but tilesets may be large. Counts both by ID and by flips.

Delete Collisions

Deletes collision shapes from selected tiles in a Tileset.

Find Tiles in Project

Finds instances of specific tiles across all the maps in your Project.

Flip Tiles in Brush

Flips the tiles in your current brush stamp without flipping the stamp itself.

Image to Map

Generates a TileMap based on a source image by matching colours from the image to tiles, using user-defined color: tileID pairs. Useful for turning schematic map sketches into TileMaps.

Import Metatile Terrains

Builds Terrain data for a metatileset by using the Terrain data from the source Tileset. Useful for speeding up Terrain creation for metatilesets, as the source tiles are usually fewer in number and easier to label. Only tested with orthographic tiles.

Mass Replace Tiles

Replaces tiles en masse, according to a guide map that specifies the tile to replace in an "old" layer and the replacements in a "new" layer. Includes actions to run the replacer on all open maps, or on all maps in a Project. Useful for when you need to rearrange the tiles in a tileset, replace an old tileset with a new one that's arranged differently, or create multiple sets of similarly structured Automapping rules.

Modify Selection

Expands and contracts (erodes) selections in maps.

Random Automap

Enables additional syntax in Automapping rules.txt to apply random rules and apply rules conditionally based on earlier selections. Can be useful for procedural generation.

Replace in Layer Name

Renames selected layers by doing a search and replace in their name. Supports regular expressions.

Select Child Layers

Recursively selects the child layers of all selected groups.

Select Layer Tiles

Selects all the non-empty cells in a layer, letting you use a layer as a selection.

Spreadsheet Actions

Inserts and deletes rows and columns in your map, making it easier to expand and contract your map. Can also shift Objects over to match.

Tileset Heatmap

Generates a heatmap of your tileset, making it easy to find over- and under-used tiles.

tiled-scripts's People

Contributors

eishiya avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

tiled-scripts's Issues

Question about how to use Find All Tiles and Tile Heatmap

Hello! Firstly, thank you for your incredibly helpful plugins! I have been using them since yesterday and they have already saved me a ton of hassle!

I want to use the two plugins in the title, I have them installed in the extensions directory, not in folders. I'm not sure whether they need to be, but I don't see any way to use them in the program. I am completely new to this, so if you could point me in the direction of which menu they're in, I'd be very grateful! Thank you for your time. :)

LargeTileStampTool2

I tried do something like this:
LargeTileStampTool2/LargeTileStampTool2.js
To resolve this:
mapeditor/tiled#4036 (comment)

  • Painting GIDs small tiles by bigger tile from sprite
var tool = tiled.registerTool("LargeTileStampTool2", {
	alignToTopLeft: true, // Should large tiles be offset such that they behave as if they have top left alignment?
	
	name: "Large Tile Stamp Tool 2",
	icon: "LargeTileStamp2.png",
	usesSelectedTiles: true,
	targetLayerType: Layer.TileLayerType,
	mouseDown: false,
	
	lineMode: false, // Controlled via Shift modifier
	lineStart: {x: -1, y: -1},
	
	tileStep: {x: 1, y: 1}, // How many cells does each large tile occupy?
	stampSize: {width: 0, height: 0}, // How many cells does the stamp cover?

	activated: function() {
		this.isActive = true;
		console.log("Tool activated.");
	},
	
	deactivated: function() {
		this.isActive = false;
		console.log("Tool deactivated.");
	},
	
	mouseReleased: function (button, x, y, modifiers) {
		if(button == 1) { // left-click
			this.mouseDown = false;
			if(this.lineMode) { // Commit line mode on release
				if(!this.map || !this.preview) return;
				this.map.merge(this.preview);
			}
		}
	},

	mousePressed: function (button, x, y, modifiers) {
		if(this.isActive) {
			if(button == 1) { // left-click, commit the preview
				if(!this.map || !this.preview) return;
				this.map.merge(this.preview);
				this.mouseDown = true;
				if(this.lineMode) {
					this.lineStart.x = this.tilePosition.x;
					this.lineStart.y = this.tilePosition.y;
				}
			} else if(button == 2) { // right-click, sample the tile on the selected layer
				if(!this.map || this.map.selectedLayers.length < 1) return;
				let selectedLayer = this.map.selectedLayers[0];
				if(!selectedLayer || !selectedLayer.isTileLayer) return;
				let newTile = selectedLayer.tileAt(this.tilePosition.x, this.tilePosition.y);
				let newBrush = new TileMap();
				newBrush.width = 1;
				newBrush.height = 1;
				let newLayer = new TileLayer();
				newBrush.addLayer(newLayer);
				let layerEdit = newLayer.edit();
				if(newTile) {
					layerEdit.setTile(0, 0, newTile, selectedLayer.flagsAt(this.tilePosition.x, this.tilePosition.y));
				} else {
					// Try sampling the nearest tile based on the last measured stamp dimensions:
					let sampleX = Math.floor(this.tilePosition.x / this.tileStep.x) * this.tileStep.x;
					let sampleY = Math.floor(this.tilePosition.y / this.tileStep.y) * this.tileStep.y;
					if(this.alignToTopLeft)
						sampleY += (this.tileStep.y - 1);
					newTile = selectedLayer.tileAt(sampleX, sampleY);
					layerEdit.setTile(0, 0, newTile, selectedLayer.flagsAt(sampleX, sampleY));
				}
				layerEdit.apply();
				tiled.mapEditor.currentBrush = newBrush;
				this.showPreview();
			}
		}
	},
	
	tilePositionChanged: function () {
		if(this.isActive) {
			this.showPreview();
			if(this.mouseDown && !this.lineMode) { // Don't commit immediately in line mode
				if(!this.map || !this.preview) return;
				this.map.merge(this.preview, true);
			}
		}
	},
	
	modifiersChanged: function(modifiers) {
		if(this.isActive) {
			if(modifiers & Qt.ShiftModifier)
				this.lineMode = true;
			else
				this.lineMode = false;
		}
	},

	measureStamp: function(stamp) {
		if (!stamp || !this.map) {
			console.log("Error: Missing stamp or map.");
			return;
		}

		let cellSize = { x: this.map.tileWidth, y: this.map.tileHeight };
		let tileSize = { x: cellSize.x, y: cellSize.y }; // Default to cell size

		// Iterate through layers in the stamp and find the maximum tile size
		function checkLayer(layer) {
			if (!layer) return;
			if (layer.isTileLayer) {
				for (rect of layer.region().rects) {
					for (x = rect.x; x < rect.x + rect.width; x++) {
						for (y = rect.y; y < rect.y + rect.height; y++) {
							let tile = layer.tileAt(x, y);
							// Check if the tile exists before reading its properties
							if (tile) {
								if (tile.width > tileSize.x)
									tileSize.x = tile.width;
								if (tile.height > tileSize.y)
									tileSize.y = tile.height;
							}
						}
					}
				}
			} else if (layer.isGroupLayer || layer.isTileMap) {
				for (let gi = 0; gi < layer.layerCount; ++gi) {
					checkLayer(layer.layerAt(gi));
				}
			}
		}
		checkLayer(stamp);

		// Calculate tileStep based on the size of the large tile compared to the cell size
		this.tileStep.x = Math.ceil(tileSize.x / cellSize.x);
		this.tileStep.y = Math.ceil(tileSize.y / cellSize.y);
		this.stampSize.width = this.tileStep.x * stamp.width;
		this.stampSize.height = this.tileStep.y * stamp.height;
	},

	drawStamp: function(x, y, stamp, map) {
		if (!stamp || !map) {
			console.log("Error: Missing stamp or map.");
			return;
		}
		
		let cellSize = { x: this.map.tileWidth, y: this.map.tileHeight };
		let stampSize = { width: stamp.width * cellSize.x, height: stamp.height * cellSize.y };

		let offset = {
			x: x - Math.floor(stampSize.width / 2),
			y: y - Math.floor(stampSize.height / 2)
		};
		
		if (this.alignToTopLeft) {
			offset.y += (stampSize.height - cellSize.y);
		}

		for (let sy = 0; sy < stampSize.height; sy += cellSize.y) {
			for (let sx = 0; sx < stampSize.width; sx += cellSize.x) {
				let tile = stamp.tileAt(sx / cellSize.x, sy / cellSize.y);
				if (tile) {
					map.setTile(
						offset.x + sx,
						offset.y + sy,
						tile
					);
				}
			}
		}
	},

	showPreview: function() {
		if(!this.map || this.map.selectedLayers.length < 1) return;
		
		let stamp = tiled.mapEditor.currentBrush;
		if (!stamp) {
			console.log("No stamp (currentBrush) available.");
			return;
		}
		
		console.log("Creating stamp preview...");
		this.preparePreview();
		this.measureStamp(stamp); // Set the step and stamp size
		
		let destinationMap = this.preview;
		if(this.lineMode) {
			// Implement line mode if necessary
		} else {
			this.drawStamp(this.tilePosition.x, this.tilePosition.y, stamp, destinationMap);
		}
		this.preview = destinationMap;
	},

	preparePreview: function() {
		var preview = new TileMap();
		preview.setSize(this.map.width, this.map.height);
		preview.setTileSize(this.map.tileWidth, this.map.tileHeight);
		preview.infinite = this.map.infinite;
		// Prepare layers:
		function addLayer(layer) {
			if(!layer) return;
			if(layer.isTileLayer) {
				let newLayer = new TileLayer(layer.name);
				preview.addLayer(newLayer);
			} else if(layer.isGroupLayer || layer.isTileMap) {
				// Process its child layers recursively:
				for(let gi = 0; gi < layer.layerCount; ++gi) {
					addLayer(layer.layerAt(gi));
				}
			}
		}
		addLayer(tiled.mapEditor.currentBrush);
		this.preview = preview;
	}
});

/* Large Tile Stamp Tool by eishiya, last updated 28 Feb 2023

LargeTileStamp2

scripting "print" function doesn't log to the console anymore

hey. With Tiled 1.7.something I could use print to output strings to the console when working on scripts, it helped quite a lot with debugging things.
I updated to tiled 1.8.3 and it doesn't see to print anything to the console anymore.

Maybe I'm missing something?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.