Page 1 of 4

svg-placer

Posted: Mon 27 Aug 2012, 19:02
by seaside
Here's a GUI tool for technosaurus' svgame and 13x10 grid where you can try out images and text on each square. Just click in the upper left corner of any square where you want an image or text to start and then close the window. A dialog follows asking if you want an image, press enter and a fileselect dialog for the directory "/usr/share/pixmaps" opens. Press cancel and a text entry box opens. The program then rerenders the new svg. Repeat until done (sounds like a recipe :D )

Kind of a kludge because commands don't run inside the case statements until the window is closed. Best run in a terminal, since the program calls itself, you have to kill it to stop.

Cheers,
s

Code: Select all

 #!/bin/sh
# requires technosaurus' svgame
# svg-placer -click on location & close window
# run in terminal to kill

 if ! [ -f /tmp/svgame.svg ]; then 
echo '
<svg  width="640" height="480">
  <defs> 
    <pattern id="grid" width="48" height="48" patternUnits="userSpaceOnUse">
      <rect fill="white" stroke="black" x="0" y="0" width="48" height="48"/>
    </pattern>
  </defs>
  <rect fill="url(#grid)" stroke="black" x="0" y="0" width="640" height="480"/>
</svg>'  >/tmp/svgame.svg

fi

svgame  /tmp/svgame.svg  2>/dev/null  | \
while read LINE; do
case "$LINE" in
BUTTON*) 
LINE="${LINE//BUTTON=/}"
 x="${LINE%,*}" 
 y="${LINE##*,}" ;;
 *) exit 
;;
esac

Xdialog --title "Image or Text dialog" --stdout  --yesno "Is this an image file?" 0 0

case $? in
  0)
    FILE="`Xdialog --backtitle "Please choose Image." --title "Image selector" --stdout --no-buttons --fselect  /usr/share/pixmaps 0 0`"
	sed -i 's|</svg>||' /tmp/svgame.svg 
	
	echo '
	<image x="'$x'" y="'$y'" width="48" height="48"
	     xlink:href="'$FILE'" />
	</svg>' >>/tmp/svgame.svg ;;

  1)
	 TEXT="`Xdialog --backtitle "Please type text below" --title "Text Select" --stdout --no-wrap --inputbox "short text no wrap" 0 0`" 
	 sed -i 's|</svg>||' /tmp/svgame.svg 
	
	  echo ' 
	 <text x="'$x'" y="'$y'" 
	     style="font-size:20" fill="black"
	>'"$TEXT"'</text>
	</svg>' >>/tmp/svgame.svg ;;
   
  255)
       exit ;;
esac
done
$0 

Case statements

Posted: Tue 28 Aug 2012, 23:25
by seaside
technosaurus,

I just noticed that everything runs fine for the case statements in the 2nd version of the source code that included key and mouse events (but not /path/to/image) when I compiled it under Racy.

The other posting of svgame.tar.gz which was a compiled version, allowing a file to be passed on the command line, is the one that Racy is not handling the same way.

Would you be kind enough to post the source code for that compiled version
Description Here is a precompiled version.that takes an input filename as 1st arg.
usage:
svgame /path/to/image.svg | your_controls
I'd like to compile that in Racy and see if that cures the "case statements not being run problem"

Thanks,
s
(Can this be a gtk version level problem?)

Posted: Wed 29 Aug 2012, 01:18
by technosaurus
formatting is scrunched, but here it is:

Code: Select all

#include <sys/inotify.h>
#include <gtk/gtk.h>
#include <string.h>
typedef struct _variable { char Name[ 512 ]; GtkWidget *Widget; } variable;
void key_press_event(GtkWidget *widget, GdkEventKey *event){printf("KEY=%s\n",gdk_keyval_name(event->keyval));}
void button_press_event(GtkWidget *widget, GdkEventButton *event){printf("BUTTON=%f,%f\n",event->x ,event->y);}
void refresh(gpointer data, gint fd, GdkInputCondition c){
char buffer[sizeof (struct inotify_event)];	variable *var; var = (variable *)data;
read( fd, buffer, sizeof(buffer) ); gtk_image_set_from_file(GTK_IMAGE(var->Widget),var->Name);}
int main(int argc, char **argv){ int watch, fd;	GtkWidget *window, *image, *eventbox; variable *var; var = g_malloc(sizeof(variable));
gtk_init (&argc, &argv); fd = inotify_init();
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); eventbox = gtk_event_box_new (); image = gtk_image_new_from_file(argv[1]);
gtk_container_add(GTK_CONTAINER(window), eventbox); gtk_container_add(GTK_CONTAINER(eventbox), image);
watch = inotify_add_watch( fd, argv[1], IN_MODIFY ); var->Widget=image; strncpy(var->Name, argv[1], 512);
gdk_input_add( fd, GDK_INPUT_READ, refresh, (gpointer) var );
g_signal_connect((gpointer)window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect((gpointer) window, "button_press_event", G_CALLBACK(button_press_event), NULL);
g_signal_connect ((gpointer) window, "key_press_event", G_CALLBACK (key_press_event), NULL);
gtk_widget_show_all(window); gtk_main ();}
Note: need to replace printf with g_print and remove string.h

Racy5.3

Posted: Wed 29 Aug 2012, 20:45
by seaside
technosaurus,

Thank you very much for posting the source code. I compiled it in Racy5.3 and it works.

In case anyone else wants the Racy5.3 compiled version, I've attached it below.

Regards,
s

svg-placer

Posted: Thu 30 Aug 2012, 14:36
by seaside
Here's a handier version of svg-placer that doesn't call itself, with the added ability to change text font size and color. Also, F3 brings up Inkscape.

Code: Select all

 #!/bin/sh
# requires technosaurus' svgame
# svg-placer -click on location 
# choose image or text
#F3 brings up inkscape

 if ! [ -f /tmp/svgame.svg ]; then 
echo '
<svg  width="640" height="480">
  <defs> 
    <pattern id="grid" width="48" height="48" patternUnits="userSpaceOnUse">
      <rect fill="white" stroke="black" x="0" y="0" width="48" height="48"/>
    </pattern>
  </defs>
  <rect fill="url(#grid)" stroke="black" x="0" y="0" width="640" height="480"/>
</svg>'  >/tmp/svgame.svg

fi

svgame  /tmp/svgame.svg  2>/dev/null  | \
while read LINE; do
case "$LINE" in
BUTTON*) 
	LINE="${LINE//BUTTON=/}"
	 x="${LINE%,*}" 
	 y="${LINE##*,}"
	 
	Xdialog --title "Image or Text dialog" --stdout  --yesno "Is this an image file?" 0 0
	
	case $? in
	  0)
	    FILE="`Xdialog --backtitle "Please choose Image." --title "Image selector" --stdout --no-buttons --fselect  /usr/share/pixmaps 0 0`"
		cp /tmp/svgame.svg /tmp/svgameNEW # need to copy else works once only
		
		sed -i 's|</svg>||' /tmp/svgameNEW 
	
		echo '
		<image x="'$x'" y="'$y'" width="48" height="48"
		     xlink:href="'$FILE'" />
		</svg>' >>/tmp/svgameNEW
		
		cp /tmp/svgameNEW /tmp/svgame.svg ;;
	
	
	  1)
		SEL=`Xdialog \
		        --title "Text Select" \
		         --stdout \
		        --3inputsbox  "Text Selector" 0 0 \
		            "Text to place" "" \
		            "Font Size" "20" \
		            "Color Name" "black"`
	
		cp /tmp/svgame.svg /tmp/svgameNEW # need to copy else works once only
		
		sed -i 's|</svg>||' /tmp/svgameNEW 
		 
		TEXT="${SEL%%/*}"
		n="${SEL#*/}"
		FONT="${n%/*}"
		COLOR="'"${SEL##*/}"'"
		
		  echo ' 
		 <text x="'$x'" y="'$y'" 
		     style="font-size:'"$FONT"'"  fill='"$COLOR"'
		>'"$TEXT"'</text>
		</svg>' >>/tmp/svgameNEW 
		
		cp /tmp/svgameNEW /tmp/svgame.svg ;;
	   
	  255)
	       exit ;;
	esac ;;
	
 KEY=F3) inkscapelite /tmp/svgame.svg ;;

*)  ;;

esac
done
Cheers,
s

Posted: Fri 31 Aug 2012, 03:41
by technosaurus
Here is some portable collision detection code:

Code: Select all

#!/bin/ash
ALPHAS=" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
#alphas can represent tiles, sprites etc...
WIDTH=3
HEIGHT=3
GRID="   bbb   "
#so the grid looks like:
#   #
#bbb#
#   #
no_collision(){
	#x=$1 y=$2
	pos=${GRID:$(($1+$2*$HEIGHT)):1}
	retval=${ALPHAS%${pos}*}
	return ${#retval}
}
no_collision 1 1 || echo ${ALPHAS:$?:1}
basically collision detection would tell you if you are trying to place something where something else already exists... moving a character, placing a game piece etc...

Posted: Thu 06 Dec 2012, 03:28
by jamesbond
The code on the first post doesn't work for me (and thus by extension all the other newer revisions because the part that doesn't work is the same for all revisions).

This part:

Code: Select all

void refresh(gpointer si, gint fd, GdkInputCondition c){
   char buffer[sizeof (struct inotify_event)];
   read( fd, buffer, sizeof(buffer) ); /* just clearing, don't care the type */
   gtk_image_set_from_file(si,IMAGE);} /* force redraw of image*/
only works once because if the file is deleted and re-created, the watch is lost after the first trigger.

The fix that works for me:

Code: Select all

void refresh(gpointer si, gint fd, GdkInputCondition c) {
	char buffer[sizeof (struct inotify_event)];
	gtk_image_set_from_file(si,IMAGE);  /* force redraw of image*/
		
	read( fd, buffer, sizeof(buffer) ); /* just clearing, don't care the type */
	inotify_rm_watch(fd, watch);
	watch = inotify_add_watch( fd, IMAGE, IN_MODIFY ); /* re-trigger watch in case file is deleted / recreated */
} 

Posted: Thu 06 Dec 2012, 05:32
by technosaurus
That's why none of my examples deleted the file, only modified them by ln/cp/mv -f or echo > my.svg

I had tried something similar, but gtk would sometimes hiccup on remove/replace (depending on timing) ... there are events for delete (and create in watched directory) too. Watching the directory may be a better idea anyhow - would allow you to redraw the svg if one of the include images changes (for instance a character uses a weapon while standing still)

I may try testing it with the file watch mechanism that I started using in sit (basically so it works on win32 and mac as well)

Posted: Thu 06 Dec 2012, 10:56
by jamesbond
technosaurus wrote:That's why none of my examples deleted the file, only modified them by ln/cp/mv -f or echo > my.svg
I wasn't trying to do anything fancy. I was doing a rox-clock http://murga-linux.com/puppy/viewtopic.php?t=82734 and it dawned upon me that svgame would be an excellent platform for it. I used sed -i to update the svg, and it only worked the first time. Only upon strace-ing sed -i, I realised that it worked by creating a new file, and moving that file over the old one ... As it happens geany also works this way.
I had tried something similar, but gtk would sometimes hiccup on remove/replace (depending on timing) ... there are events for delete (and create in watched directory) too. Watching the directory may be a better idea anyhow - would allow you to redraw the svg if one of the include images changes (for instance a character uses a weapon while standing still)
Yes, but the problem with watching a directory is that you'll get notified for anything that happens in the directory. If you only need to watch a specific file then you will have to filter these events.
I may try testing it with the file watch mechanism that I started using in sit (basically so it works on win32 and mac as well)
I thought you're using the same mechanism there?

Posted: Thu 06 Dec 2012, 19:59
by technosaurus
lets say your svg file is mygame/mygame.svg and you are watching the directory mygame. if a file is modified or created in that directory you simply redraw mygame.svg (not caring what file it is - it could be an included sub-image)

for sit I made a win32 version, meaning I couldn't use the linux specific inotify, so I used a glib/gio wrapper pseudo-equivalent

rather than using sed, you could probably just store the strings in variables and echo > them for redraws (it will be faster anyways)

Posted: Fri 07 Dec 2012, 00:44
by seaside
technosaurus wrote:
rather than using sed, you could probably just store the strings in variables and echo > them for redraws (it will be faster anyways)
jamesbond,

Not only works with svgame but on your very nicely done rox-clock as well -

Code: Select all

j#!/bin/sh
# Copyright (C) jamesbond 2012
# License: GNU GPL Version 3 or later
#
# called by AppRun
#exec 2> /tmp/log-clock
APPDIR=${0%/*}

update_clock() {
	# date
	sed -i -e "s/ary>.*</ary>$(date +"%A %e %B %Y")</" \
${APPDIR}/AppInfo.xml
	
	# time
	time=$(date +%I-%M)
	hour=${time%-*} 
	minute=${time#*-}
	hour=${hour#0}	
	minute=${minute#0}

	HROTATE=$(( $hour*30 + $minute/2 ))
	MROTATE=$(( $minute*6 ))
	#echo $hour_rot $min_rot
	
	echo '<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     viewBox="-1024 -1024 2048 2048" width="600" height="600">
  <title>Swiss Railway Clock</title>
  <style type="text/css">
    .bg {stroke: none; fill: white;}
    .fc {stroke: none; fill: black;}
    .h1 {stroke: none; fill: black;}
    .h2 {stroke: none; fill: #aa0000;}
  </style>
  <defs>
    <path id="mark1" d="M -20,-1000 l 40,0 0,100 -40,0 z" />
    <path id="mark2" d="M -40,-1000 l 80,0 0,240 -80,0 z" />
    <path id="mark3" d="M -40,-1000 l 80,0 0,300 -80,0 z" />
    <path id="handh" d="M -50,-600  l 50,-50 50,50 0,800  -100,0 z" />
    <path id="handm" d="M -40,-900  l 40,-40 40,40 0,1180 -80,0  z" />
    <g    id="hands">
      <path d="M -10,-910 l  10,-10 10,10 2,300 -24,0 z
               M -13,-390 l  26,0         7,690 -40,0 z" />
      <path d="M   0,-620 a 120,120 0 0 1 0,240
                          a 120,120 0 0 1 0,-240 z
               M   0,-560 a  60,60  0 0 0 0,120
                          a  60,60  0 0 0 0,-120 z" />
    </g>
    <g id="face1">
      <use xlink:href="#mark1" transform="rotate(06)" />
      <use xlink:href="#mark1" transform="rotate(12)" />
      <use xlink:href="#mark1" transform="rotate(18)" />
      <use xlink:href="#mark1" transform="rotate(24)" />
    </g>
    <g id="face2">
      <use xlink:href="#face1" />
      <use xlink:href="#face1" transform="rotate(30)" />
      <use xlink:href="#face1" transform="rotate(60)" />
      <use xlink:href="#mark3" />
      <use xlink:href="#mark2" transform="rotate(30)" />
      <use xlink:href="#mark2" transform="rotate(60)" />
    </g>
    <g id="face">
      <use xlink:href="#face2" />
      <use xlink:href="#face2" transform="rotate(90)"  />
      <use xlink:href="#face2" transform="rotate(180)" />
      <use xlink:href="#face2" transform="rotate(270)" />
    </g>
  </defs>
  <circle class="bg" r="1024" />
  <use xlink:href="#face"  class="fc" />
  <use xlink:href="#handh" class="h1" transform="rotate('"$HROTATE"')" />
  <use xlink:href="#handm" class="h1" transform="rotate('"$MROTATE"')" />
  <!-- <use xlink:href="#hands" class="h2" transform="rotate(168)" /> -->
</svg> ' > ${APPDIR}/clock.svg	
	
	#sed -i -e "
#/\#handh/ s/rotate(.*)/rotate($hour_rot)/
#/\#handm/ s/rotate(.*)/rotate($min_rot)/
#" ${APPDIR}/clock.svg
	rox -x ${APPDIR}	
}

# 1. initial update
update_clock

# 2. sync to the start of the minute
while [ $(date +"%S") -ne 0 ]; do sleep 1; done 

# 3. run the clock proper
while true; do
	update_clock
	sleep 60
done 
Cheers,
s

Posted: Fri 07 Dec 2012, 23:25
by jamesbond
technosaurus, seaside,

Thanks for the info :)

cheers!

Posted: Sun 23 Dec 2012, 21:36
by technosaurus
Todo: example of output mouse position on click

Maybe a dialog button.

Posted: Mon 24 Dec 2012, 03:37
by linuph
I call this script 'control':
<svg width="640" height="480">
<image x="1" y="1" width="640" height="480"
xlink:href="/usr/share/backgrounds/default.jpg" />
<image x="1" y="1" width="64" height="48"
xlink:href="/usr/share/pixmaps/buddy.png" />
</svg>
With 'svgame | control' I get an error:
./control: line 1: syntax error near unexpected token 'newline'
./control: line 1: '<svg width="300" height="300">'

The web is full with questions about this but I can't find a solution. Has it to to with line endings? Geany shows 'LF'. What should this script be? Just a script, or .xml or with #!/bin/sh in the top line.

A lot to learn here...

Posted: Mon 24 Dec 2012, 04:04
by linuph
Double post

Posted: Mon 24 Dec 2012, 05:38
by technosaurus
It's an svg image. Scripts begin with #!/bin/something and need to have the executable bit set.

Posted: Mon 24 Dec 2012, 06:53
by linuph
Using #!/bin/sh now, but the 'newline' error remains. Same in #!/bin/ash, if that means anything. I understand that '<' has special meaning in Bash, reason for the error. What could be the problem?

Posted: Mon 24 Dec 2012, 14:01
by Keef
I'm just guessing here, but after looking at other examples on the page, is your code sequence quoted properly?
eg

Code: Select all

 echo ' < blah blah> '

Posted: Tue 25 Dec 2012, 00:39
by linuph
Thanks Keef. Being not quoted was the problem. I had a thorough misunderstanding of how the svgame program works. Solved.

Posted: Mon 31 Dec 2012, 19:43
by technosaurus
to further confuse everyone new to this topic, here is my latest research results for svg and "sprites"... I found it easier to include a second svg rather than the more complicated method of filling a rectangle with a pattern from an image (it may be slower to render but I couldn't figure out a good way to slice the png sprites for fill patterns)

Code: Select all

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="354" viewBox="0 176 256 176">

<image xlink:href="zelda-map.png" height="1408" width="4096" />

<svg x="32" y="240" width="16" height="16" viewBox="0 0 16 16">
<image xlink:href="link.png" width="432" height="303" />
</svg>

</svg>
Note: the <image> width and height are the total width and height of the image whereas the <svg> width and height are the displayed width and height
Note2: the viewbox is xoffset yoffset width height of the image "slice"
Note3: the link.png image has an x and y attribute that are relative to the actual image size from the parent viewbox (0 and 176 in this case) ... thus the image will be scaled to 32x32 since the parent is scaled 2x2 (width='512' height='354' with viewport width of 256 and 176 ... such that the main width and height can be set to 100% for full scale rendering without having to calculate the values for all of the sprites)