Thread: Generating LOS via SVG from GIMP
-
October 25th, 2020, 03:58 #1
- Join Date
- Feb 2011
- Posts
- 6
Generating LOS via SVG from GIMP
Hi all,
I create a lot of my own maps, and wanted the ability to use GIMP to select the negative areas of the maps, and use that as the basis for my walls.
I know theres been some conversations about how to create LOS Walls, in the forums, but this is my own take on it.
The process is based around making a selection in GIMP.
Screenshot 2020-10-25 154041.png
Convert that to a PATH, (Menu: Select-> To Path)
Now Export it as a SVG File.
Screenshot 2020-10-25 154140.png
The SVG export from GIMP seems to be pretty specific SVG format, so I don't promise this works for all SVGs.
Screenshot 2020-10-25 155356.png
Then run the below powershell script that, for all SVG files in a directory:
1. Gets the image size. (This is needed to convert to FGU's Frame of Reference: 0,0 at the centre, and orientation: Y axis reversed)
2. Parse the path coords, and storing them in a List.
3. Parse the List, removing doubles, (I extended this to reduce the number of points, by distance.)
4. Output the list to the same filename as the svg, in the XML Occluder format that FGU's db.xml expects.
Then you take that xml, find your Image Layer in your dbxml and put it in there.
Screenshot 2020-10-25 155432.png
Done!!
Screenshot 2020-10-25 155537.png
Note it only handles walls. But of course, you could just make selection paths for all the different features in gimp, and just toggle their type in the db.xml.
Hope this helps someone!!
Muklin
Here is the powershell:
Code:param( [String]$filePath = $PWD, [Int]$SmoothDistance = 10 ) if(test-path -path $filePath){ $files = Get-ChildItem -name $filePath -Include *.svg } $files | %{ $file= $filePath+"\"+$_ $filename = $_ -replace ".svg",".occ" Write-Output "Processing $file..." if([System.IO.File]::Exists($file)){ $content = get-content $file }else{ Write-Error "Could not find file $file" exit 2 } $matchResult = [regex]::Match($content,"viewBox=\`"0 0 ([0-9]+) ([0-9]+)\`"") $xWide = $matchResult.Groups[1].Value $yHigh = $matchResult.Groups[2].Value Write-Host "Detected an image $xWide by $yHigh" $xWideMod = $xWide/2 $yHighMod = $yHigh/2 "<occluders>" | Out-file -Filepath $filename $occludercount = 0 $m = Select-String -InputObject $content -Pattern "C[0-9., `r`n]+Z" -AllMatches $array = [System.Collections.ArrayList]@() $m.Matches | %{ $line = $_.Value.trim("C").trim("Z") $matching = Select-String -InputObject $line -Pattern "([0-9\.,]+)" -AllMatches foreach($match in $matching.Matches){ $coord = $match.Value.split(",") $coord[0] = $coord[0] -as [int] $coord[1] = $coord[1] -as [int] if($array.Count -gt 0 -and [Math]::Pow($array[-1][0]-$coord[0],2)+[Math]::Pow($array[-1][1]-$coord[1],2) -lt [Math]::Pow($SmoothDistance,2) ) { #"discarded a point" }else{ $array.Add($coord) | Out-Null } } $out = "" $array | %{ $modX = $_[0]-$xWideMod -as [String] $modY = $yHighMod-$_[1] -as [String] $out = $out+$modX+","+$modY+"," } "`t<occluder>" | Out-file -append -Filepath $filename "`t`t<id>$occludercount</id>" | Out-file -append -Filepath $filename "`t`t<points>$($out.trim(","))</points>" | Out-file -append -Filepath $filename "`t`t<closedpolygon>true</closedpolygon>" | Out-file -append -Filepath $filename "`t</occluder>" | Out-file -append -Filepath $filename $occludercount++ $array.RemoveRange(0,$array.Count) } "</occluders>" | Out-file -append -Filepath $filename }
Last edited by muklin; October 26th, 2020 at 22:07.
-
October 25th, 2020, 14:47 #2
I would like to take some questions:
1 - Can I do this type of export only with GIMP?
2 - Are the colors defined by the Pen Tool that define the type of LoS or not?
3 - Where would that Script be used at the end?[FGU ULTIMATE LICENSE HOLDER][BRAZILIAN][GMT-3]
[RPG PLAYER]
[TWITCH] [YOUTUBE]
[Core RPG - Package] [Leather Theme Addition] [Rolemaster (Classic) - Shopping Stores] [Rolemaster (Classic) - XP Tab]
-
October 26th, 2020, 22:06 #3
- Join Date
- Feb 2011
- Posts
- 6
1. The workflow I described is only tested using Gimp to create an SVG. Potentially, some other SVGs would work, but probably not. Potentially even other versions of GIMP wouldn't work.
2. This is for FGU. See the LOS videos you can find linked in various places on this forum to see how LOS in FGU works.
3. The script converts the SVG to the occluder data, to be inserted into the db.xml file for your campaign. So you'd use it after you created the SVG. As mentioned in the post.
-
October 27th, 2020, 13:32 #4
- Join Date
- Aug 2020
- Posts
- 50
This is cool, thanks. Any chance of a brief step by step video explaining it further for those familiar with GIMP but not the dbxml files? (I don’t even know what those are).
-
October 27th, 2020, 23:07 #5
- Join Date
- Feb 2011
- Posts
- 6
db.xml is the main xml file that FG and FGU use to store the state of your campaign.
You can find the file by browsing to the Fantasy Grounds Data directory.
There are various links to this directory in the application, but also see:
https://www.fantasygrounds.com/wiki/...Files_Overview
Which says:
"The Fantasy Grounds data folder is specified in the FG Settings when installing FG.
The easiest way to access the data directory is to click the folder icon in the top right of the main FG startup screen. This will open a new file explorer window at the root of the data directory. "
Inside here, browse to campaigns/<your campaign name
db.xml will be in there, and is just a big ol xml file with the data in your campaign.
A few notes and disclaimers on working with db.xml
DISCLAIMER: All this information is what I've reverse engineered from using FG over the years. Take it with a grain of salt. It worked for me. I don't take responsibility for any loss of data.
1. Before anything else, BACKUP your current db.xml. If you make a mistake, then you might end up losing everything. Having a back up is always a good idea.
2. I recommend you only edit db.xml while your campaign is not loaded. This will save you heartache of making lots of edits in the file, only for FG to overwrite it when you make changes in the application.
2a. Alternatively, you can use the /reload and /save command lines in FG to force it to load changes.
3. Load the image you want to change into the campaign first, then close the campaign. this will create the image xml node in the db.xml.
4. Alter the image node to have, (or replace, or alter) the generated <occluders> sub node.
5. Save your file.
6. Reload your campaign.
7. Open the map and see if your occluders are set as you need them.
8. Rinse and repeat til you're happy.
-
September 8th, 2021, 19:31 #6
- Join Date
- May 2016
- Posts
- 522
A little of an old thread but still I had to say that this is an absolutely wonderful method of doing LoS. It works great.
A couple of additions I would add...
1. Use of a gaussian blur with the blending mode as color erase can help produce selections that inset the LoS into the wall slightly.
2. Use of the advanced selection to path can help with a little better granulation on the path.
I use this python-fu:
img = gimp.image_list()[0]
pdb.plug_in_sel2path_advanced(img,None,0.5,60.00,4 ,100.00,0.40,1,1.00,1,0.33,3,2,0,0.010,0.5,0.01,1, 0.1,4,0.09,3)
Hope this helps others with this method.
Jason
-
February 20th, 2022, 23:43 #7
- Join Date
- Jun 2020
- Posts
- 53
Bash version
I was inspired to try a bash (linux shell) version of this.
Code:#!/bin/bash if [ $# -lt 1 ] then echo "Usage:\n$ $0 <svg_file>..." exit 1 fi in_file="$1" out_file=${in_file%.svg}.occ vb_regex='viewBox="0 0 ([0-9]+) ([0-9]+)"' smooth_distance=10 readarray content < "${in_file}" if [[ "${content[@]}" =~ $vb_regex ]] then xWide=${BASH_REMATCH[1]} yHigh=${BASH_REMATCH[2]} echo "Detected an image $xWide by $yHigh" fi let xWideMod=$xWide/2 let yHighMod=$yHigh/2 echo "<occluders>" > "${out_file}" export occludercount=0 oc_regex='C[0-9\., \ ]+Z' coord_regex='([0-9\.,])+' close_to_last() { if [ ${#array[@]} -eq 0 ] then return 0 fi # echo "End of array: ${array[-1]}" local lastx=${array[-1]%,*} local lasty=${array[-1]/"$lastx,"/} return $(( ( ($lastx - ${coord[0]}) ** 2 + ($lasty - ${coord[1]}) ** 2 ) < ( $smooth_distance ** 2 ) )) } export OUT="" chunk="${content[@]}" while [[ "$chunk" =~ $oc_regex ]] do group="${BASH_REMATCH[0]}" # echo "$group" ( declare -a array declare -a coord while [[ "$group" =~ $coord_regex ]] do t=${BASH_REMATCH[0]%,*} coord[0]=${t%.*} t=${BASH_REMATCH[0]/"$t,"/} coord[1]=${t%.*} # echo "Found: (${coord[0]},${coord[1]})" close_to_last if [ $? -eq 0 ] then array+=("${coord[0]},${coord[1]}") # echo "Added: ${array[-1]}" fi group=${group/"${BASH_REMATCH[0]}"/} done if [ ${#array[@]} -gt 1 ] then for point in ${array[@]} do coord[0]=${point%,*} coord[1]=${point/"${coord[0]},"/} # echo -n "Processing (${coord[0]},${coord[1]})" let modX=${coord[0]}-$xWideMod let modY=$yHighMod-${coord[1]} # echo " = ($modX,$modY)" OUT="${OUT}${modX},${modY}," done out=${OUT%,} cat <<HERE >> "$out_file" <occluder> <id>$occludercount</id> <points>$out</points> <closedpolygon>true</closedpolygon> </occluder> HERE fi unset array ) occludercount=$((occludercount+1)) chunk=${chunk/"${BASH_REMATCH[0]}"/} # echo -n "Press enter to continue" # read enter done echo "</occluders>" >> "${out_file}"
Also on github: https://github.com/dimonic/fgu-scriptsLast edited by dimonic; February 21st, 2022 at 16:59. Reason: Added git link
Thread Information
Users Browsing this Thread
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks