[GDI+][Class] Particle System 2.0

Post your working scripts, libraries and tools for AHK v1.1 and older
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [GDI+][Class] Particle System 2.0

17 Jan 2017, 18:16

SpecialG wrote:then the gui-show with an empty/faulty gui-name..

Code: Select all

MsgBox, % A_AHKVersion ; ?
SpecialG

Re: [GDI+][Class] Particle System 2.0

17 Jan 2017, 18:51

Helgef wrote:

Code: Select all

MsgBox, % A_AHKVersion ; ?
v1.1.24.00

My bad, I must have been half asleep (I lack some at the moment) ..
When I re-added the includes and did a gdip startup at the top it shows :shh:

Now on the other hand, with this code I get no effects :

lol :think:
User avatar
tidbit
Posts: 1273
Joined: 29 Sep 2013, 17:15
Location: USA

Re: [GDI+][Class] Particle System 2.0

17 Jan 2017, 19:32

"and I get an error on Helgef's script"
Helgef forgot to add the includes :P (s)he also didn't copy "pToken:=Gdip_Startup()" into the sample :D
but fixing that stuff fixes it.

"Also, over here a 2-screen canvas didn't even work for some reason :monkeysee: "
I'll test, haven't tried. I rarely use 2 monitors.

"My prediction ..."
:blush:
rawr. fear me.
*poke*
Is it December 21, 2012 yet?
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [GDI+][Class] Particle System 2.0

17 Jan 2017, 19:53

tidbit wrote: Helgef forgot to add the includes:
:oops:
tidbit wrote: something like this: https://www.openprocessing.org/sketch/105516
Cool, I'll ponder it.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [GDI+][Class] Particle System 2.0

18 Jan 2017, 06:41

It's quite smooth, but the gif seems a little more flickery than I percieved it, but it still flickers some.
To look more like the original, I'll need to displace every other row of the image. I'll provide the code later, it still needs some tweaking I think.
2017-01-18_12-31-34.gif
2017-01-18_12-31-34.gif (1.09 MiB) Viewed 4994 times
SpecialG

Re: [GDI+][Class] Particle System 2.0

18 Jan 2017, 07:35

Nice one again Helgef ! It already looks almost identical to the original.

The flickering is something I sadly haven't managed to get rid off with GDI+ ...
I made fullscreen visualizations but they flicker if I make them too complex.
Gotta keep 'm real simple even to be easy on the eyes.

It would be a world of difference if this could be addressed somehow.
It seems the time between the deletion of the canvas and the redraw causes this.
At least that's how it is with my code.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [GDI+][Class] Particle System 2.0

19 Jan 2017, 07:06

SpecialG wrote:Nice one again Helgef ! It already looks almost identical to the original.
Thanks.
SpecialG wrote: The flickering is something I sadly haven't managed to get rid off with GDI+ ...
That is disappointing. I wonder if... :think:
Iris
As promised, a script for the Iris-effect, inspired by this.
You need this image,
white.png
white.png (229 Bytes) Viewed 4942 times

Code: Select all

; Inspired by https://www.openprocessing.org/sketch/105516 
SetWorkingDir, % A_ScriptDir
#include Gdip.ahk
#include particles_class.ahk
SetBatchLines,-1
ListLines,off
SetWinDelay,-1
SetControlDelay,-1

pToken:=Gdip_Startup()
if !pToken
{
	MsgBox, Fail!
	ExitApp
}

owl:=false

if !owl
{
	sFile:="white.png"					; This script is made for this case. 64-by-64 all white.
	I:=particliseImage(sFile,10,8,4)
	prepareIris(I)						; This function is only for this case
	irisParticleImage(I,32)				; 32 is the "radius" of the effect
}
else
{
	; Owl
	
	sFile:="57.jpg"						; But you can use it for any image.
	I2:=particliseImage(sFile,12,4,4)
	setParticleImageAlpha(I2,240)
	showParticleIm(I2,,0xDFDFDF)
	irisParticleImage(I2,24,3)
	/*
	; Or:
	sFile:="57.jpg"	
	I2:=particliseImage(sFile,8,3,3)
	setParticleImageAlpha(I2,240)
	showParticleIm(I2,,0xDFDFDF)
	irisParticleImage(I2,32,2)
	*/
}
return

prepareIris(pIm)
{
	setParticleImageAlpha(pIm,125)
	rows:=[]
	loop, % round(pIm.w/2)
		rows.push(A_Index*2)
	displaceRows(pIm,rows,(pIm.size*pIm.res)/2)
	showParticleIm(pIm,0,0x000000)
	return
}

irisParticleImage(pIm,r:=3,size:="",freq:=50,init:=1)
{
	static pmx, pmy, pInd
	if init
	{
		if (size="")
			size:=pIm.size
		tf:=Func("irisParticleImage").Bind(pIm,r,size,freq,0)
		pmx:="",pmy:="",pInd:=""
		SetTimer, % tf, % freq
		return
	}
	CoordMode, mouse, client
	MouseGetPos, mx, my, wum
	if (mx=pmx && my=pmy) ; || (wum!=pIm.guiId) ; Uncomment to omit effect when mouse is outside of the window
		return
	pmx:=mx,pmy:=my
	X:=(mx)//(pIm.space*pIm.res)+1
	Y:=(my)//(pIm.space*pIm.res)+1
	coords:=circleCoords(X,Y,r,pIm.w,pIm.h)	; Coords are relative to the upper left particle
	ind:=indFromCoords(coords,pIm)			; Coords are converted to indices in the particles array, i.e, psys.particles[1, ind ]
	mousePos:={x:mx,y:my}
	for k, i in pInd
		pIm.psys.Particles[1,i].radius:=pIm.size
	for k, i in ind
	{
		p:=pIm.psys.Particles[1,i]
		d:=dist({x:p.x1,y:p.y1},mousePos)
		if (d>r*(size))
			continue
		term:=1-d/(r*pIm.size)
		p.radius:=size*(1+term*9*exp(-1+term**4))
	}
	pIm.psys.clear()
	pIm.psys.draw(pIm.hPic)
	pInd:=ind ; For restoring previous particles
}

dist(q1,q2)
{
	return sqrt((q1.x-q2.x)**2+(q1.y-q2.y)**2)
}

displaceRows(pIm, rows, dx)
{
	for k, row in rows
		for l, i in indFromRow(pIm,row)
			pIm.psys.Particles[1,i].x1+=dx
	return		
}

indFromRow(pIm,row)
{
	coords:=[]
	Loop, % pIm.w
		coords.Push({x:A_Index,y:row})
	return indFromCoords(coords,pIm)
}

setParticleImageAlpha(pIm,alpha)
{
	if !IsObject(alpha)
		for k, p in pIm.psys.Particles[1]
			p.alpha:=alpha
	else
		for k, p in pIm.psys.Particles[1]
			p.alpha:=alpha[k]
	return
}

indFromCoords(coords,pIm)
{
	ind:=[]
	for k, pair in coords
		ind.Push((pIm.w-pair.x)*pIm.h+(pIm.h-(pair.y-1)))
	return ind
}

circleCoords(x,y,r,w,h)
{
	; "Circle", its a square
	coords:=[]
	x:= x-r//2<1 ? 1 : x-r//2
	y:= y-r//2<1 ? 1 : y-r//2
	xCap:= x+r>w ? x+r-w : 0
	yCap:= y+r>h ? y+r-h : 0
	Loop, % r+1-xCap
	{
		i:=A_Index-1
		Loop, % r+1-yCap
		{
			j:=A_Index-1
			coords.push({x:x+i,y:y+j})
		}
	}
	return coords
}

particliseImage(file,size:="",space:=2,res:=4)
{	
	if !size
		size:=space*res*2
	psys:=new particles(30)
	pBitmap:=Gdip_CreateBitmapFromFile(file)
	if !pBitmap
	{
		MsgBox, Fail
		return -1
	}
	Gdip_GetDimensions(pBitmap,w,h)

	gui, new, +hwndguiId +ToolWindow
	gui, % guiId ":margin", 0,0
	gui, % guiId ":add", picture, % "x0 y0 " "w" w*space " h" h*space " 0xE hwndhPic"
	psys.setCanvas(0, 0, w*space, h*space, 4, hPic)
	ctr:=0
	e:=psys.addEmitter()
	e.color:=[]
	e.circleSize:=[size]
	e.coords:=[]
	e.alpha:=[255]
	
	Loop, % w//res
	{
		i:=A_Index
		x:=(i-1)*res
		Loop, % h//res
		{
			j:=A_Index
			y:=(j-1)*res
			argb := Gdip_GetPixel(pBitmap, x, y)
			rgb:=argb & 0x00FFFFFF
			e.color.Push(format("{:06x}", rgb))
			e.coords.Push({x:x*space,y:y*space})
		}
	}
	e:=psys.emitters[1]
	for k, tuple in e.coords
		psys.addParticle(tuple.x,tuple.y)
		
	Gdip_DisposeImage(pBitmap) ; !!! in this code it gets redrawn. get rid of the old
	return {psys:psys, w:w//res, h:h//res, guiId:guiId, hPic:hPic, res:res, space:space, size:size}
}


showParticleIm(pIm,clear:=1,color:="")
{
	if !WinExist("ahk_id " pIm.guiId)
		Gui, % pIm.guiId ":show"
	if (color!="")
		Gui, % pIm.guiId ": color", % color
	if clear
		pIm.psys.clear()
	pIm.psys.draw(pIm.hPic)
	return
}

Esc::
guiclose:
	Gdip_Shutdown(pToken)
	exitapp
return
Edit: Removed some noise, and made some minor improvments to the code.
Last edited by Helgef on 20 Jan 2017, 19:08, edited 1 time in total.
User avatar
tidbit
Posts: 1273
Joined: 29 Sep 2013, 17:15
Location: USA

Re: [GDI+][Class] Particle System 2.0

19 Jan 2017, 11:45

That works awesomely :D
Helgef, the king of fun
rawr. fear me.
*poke*
Is it December 21, 2012 yet?
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [GDI+][Class] Particle System 2.0

07 Apr 2017, 16:19

I was just trying to interact with a government website, when I was greeted by an infinite please wait while loading animation, in the frustration that followed, I made this,
loading.gif
loading.gif (102.44 KiB) Viewed 4727 times
With example, and brief instructions, a function to show an annoying loading animation, until some condition is met,

Code: Select all

; PRESS a to run notepad, then the loading quits.
;ESC to exit script
SetWorkingDir, % A_ScriptDir
#include Gdip.ahk
#include particles_class.ahk

gosub, startup

loading(func("winexist").bind("ahk_exe  notepad.exe"),100,75,35) ; Load until notpad exists, press the keyboard button "a", to run notepad
fire:=["FFE600","FFD100","FFBC00","FFA800","FF9300","FF7E00","FF6900","FF5500"] ; from the gui example
loading(4000,75,25,12,fire) ; Load 4 seconds. Quicker and smaller
exitapp
a::Run,notepad.exe

loading(funcOrTime:="",speed:=100,radius:=75, size:=25, color:="00ff00",trans:=240)
{	
	; funcOrTime, pass a func or bound func object which returns true when the load graphic should terminate.
	; or pass a duration in ms.
	; speed, higher values means slower.
	; radius is the raidus of the ring,
	; size, is the radius of the circles which makes the ring.
	; color, hex
	; trans, 0-255, transparency value.
	
	static pi_ish:=3.1416
	IsObject(funcOrTime) ? func:=funcOrTime : time:=funcOrTime
	t1:=A_TickCount
	psys:=new particles(30)
	w:=radius*2, h:=radius*2
	gui, new, +hwndguiId +ToolWindow -caption +alwaysontop
	gui, % guiId ":margin", 0,0
	gui, % guiId ":color", ffffff
	gui, % guiId ":add", picture, % "x0 y0 " "w" w " h" h " 0xE hwndhPic"
	psys.setCanvas(0, 0, w, h, 4, hPic)
	e:=psys.addEmitter()
	e.alpha:=[trans]
	e.circleSize:=[size]
	e.color:=IsObject(color)?color:[color]
	n:=8 ; 8-12 is nice. 
	oX:=radius
	oY:=radius
	; Make the particles
	Loop, % n {
		t:=A_Index-1
		phi:=-pi_ish/2+t*2*pi_ish/n
		x:=oX+(radius-size)*cos(phi)
		y:=oY+(radius-size)*sin(phi)
		psys.addParticle(x,y)
	}
	sizes:=[.35,.55, .85, 1, .85, .55,.35,0], scale:=2 ; You can modify this array, scale and n to get a lot of different looks.
	; Some slight variations to try.
	;sizes:=[0.25,.35, .45, .25, .45, .65,.85,1], scale:=3
	;sizes:=[0.25,.35, .45, .55, .45, .35,.25,0,25], scale:=3
	
	Gui, % guiId ":show"
	WinSet, Transcolor, ffffff, % "ahk_id " guiId
	Loop { ; Inf loop
		i:=A_Index
		for k, p in psys.Particles[1]
			j:=(Mod(k+i,n)+1), p.radius:=scale*size*sizes[j]/j
		psys.clear()
		psys.draw(hPic)
		sleep, % speed
		
	} Until IsObject(func) ? func.call() : A_TickCount-t1>=time
	Gui, % guiId ":destroy"
	return
}

esc::
guiclose:
	Gdip_Shutdown(pToken)
	exitapp
return
startup:		
	pToken:=Gdip_Startup()
	if !pToken
	{
		MsgBox, Fail!
		ExitApp
	}
return
Cheers.
User avatar
tidbit
Posts: 1273
Joined: 29 Sep 2013, 17:15
Location: USA

Re: [GDI+][Class] Particle System 2.0

08 Apr 2017, 10:48

Nice!
I'm actually surprised people still use this :P
rawr. fear me.
*poke*
Is it December 21, 2012 yet?
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [GDI+][Class] Particle System 2.0

08 Apr 2017, 11:11

I'm surprised more people aren't :shock:
Because it is funny, and coooool :ugeek:

Cheers.
Edit:
sGuest wrote:Same here, you should see the stuff I'm making with this 8-)
:superhappy:
Last edited by Helgef on 08 Apr 2017, 16:01, edited 1 time in total.
sGuest

Re: [GDI+][Class] Particle System 2.0

08 Apr 2017, 14:33

Same here, you should see the stuff I'm making with this 8-)
When I have some more free time and get around to cleaning up the leftover stuff I'll post it here as well as that little addition I made to the GUI :)
Thanks again for the awesome class you shared with us Tidbit !
And you too Helgef :thumbup:
User avatar
tidbit
Posts: 1273
Joined: 29 Sep 2013, 17:15
Location: USA

Re: [GDI+][Class] Particle System 2.0

08 Apr 2017, 18:02

someone sent me a PM to a modded gui version that has saving/loading and code generating (generate the emitters settings for your own scripts). it could be improved but I'm not doing that. I intended to add those features aswell, but kinda lost motivation as this was just a tech demo/preview/example, not meant for anything serious.
rawr. fear me.
*poke*
Is it December 21, 2012 yet?
User ahk new

Re: [GDI+][Class] Particle System 2.0

09 Apr 2017, 10:21

Hi Tibit


Very nice GUI , could you please share the code "modded gui version that has saving/loading and code generating".
I think is useful for a new user.


Thanks in advance
elbitjusticiero
Posts: 78
Joined: 06 May 2017, 11:07

Re: [GDI+][Class] Particle System 2.0

03 Feb 2019, 01:49

hi! I asked this question in a different thread making use of this system but it's more appropriate here, I think:

I would really like to put one of these in a box inside a GUI. Can it be done? I see they work inside an AHK Gui but I'm not sure what kind of control is hosting them because it's created through DllCall. What I would like is to place a box with one of these beautiful thingies alongside other "normal" controls, where a logo would normally be.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 122 guests