├── examples
├── stickMan.png
├── Polygons.ahk
├── MouseDots.ahk
├── CrosshairOverlay.ahk
├── GeneralExample.ahk
└── EverythingExample.ahk
├── AHK V2
├── Examples V2
│ ├── crosshair.ini
│ ├── stickMan.png
│ ├── Polygons_V2.ahk
│ ├── MouseDots_V2.ahk
│ ├── CrosshairOverlay_V2.ahk
│ ├── GeneralExample_V2.ahk
│ └── EverythingExample_V2.ahk
├── game_example_by_dmtr99
│ └── Raptor_V2.ahk
└── ShinsOverlayClass.ahk
├── LICENSE
├── README.md
└── ShinsOverlayClass.ahk
/examples/stickMan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Spawnova/ShinsOverlayClass/HEAD/examples/stickMan.png
--------------------------------------------------------------------------------
/AHK V2/Examples V2/crosshair.ini:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Spawnova/ShinsOverlayClass/HEAD/AHK V2/Examples V2/crosshair.ini
--------------------------------------------------------------------------------
/AHK V2/Examples V2/stickMan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Spawnova/ShinsOverlayClass/HEAD/AHK V2/Examples V2/stickMan.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Spawnova
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/examples/Polygons.ahk:
--------------------------------------------------------------------------------
1 | #singleinstance,force
2 | #include ..\shinsoverlayclass.ahk
3 |
4 | x := floor(a_screenwidth * 0.2)
5 | y := floor(a_screenheight * 0.2)
6 | width := floor(a_screenwidth * 0.6)
7 | height := floor(a_screenheight * 0.6)
8 | if (width < height) {
9 | height := width
10 | } else {
11 | width := height
12 | }
13 | ;create a octagon window
14 | oRad := 0.25 ;octagon corner radius
15 | windowPolygon := [ [2,height*oRad], [width*oRad,2], [width*(1-oRad),2], [width-2,height*oRad], [width-2,height*(1-oRad)], [width*(1-oRad),height-2], [width*oRad,height-2], [2,height*(1-oRad)] ]
16 |
17 | drawPoints := [] ;set example polygons to be empty, user will define these
18 | fillPoints := []
19 | bothPoints := []
20 |
21 | overlay := new ShinsOverlayClass(x,y,width,height,0,0,0)
22 | opacity := 0xBB
23 |
24 | onmessage(0x201,"WindowMove")
25 | moving := false
26 | settimer,draw,10
27 | return
28 |
29 |
30 | draw:
31 | if (moving) {
32 | postmessage,0xA1,2,,,% "ahk_id " overlay.hwnd
33 | while(GetKeyState("lbutton","p")) {
34 | sleep 100
35 | }
36 | moving := false
37 | }
38 | if (overlay.BeginDraw()) {
39 |
40 | ;draw background window
41 | overlay.FillPolygon(windowPolygon,(opacity<<24))
42 | overlay.DrawPolygon(windowPolygon,0xFF000000,2)
43 |
44 |
45 | overlay.FillPolygon(fillPoints,0x6600FF00)
46 | overlay.DrawPolygon(drawPoints,0xFF0000)
47 |
48 | overlay.FillPolygon(bothPoints,0x6622908A)
49 | overlay.DrawPolygon(bothPoints,0x00FFF1)
50 |
51 | overlay.DrawText("Press ESC to close",0,2,32,0xFFFF0000,"Arial","dsFF000000 aCenter w" width " h" height)
52 |
53 | overlay.DrawText("Press F1 to add points for DrawPolygon`nPress F2 to add points for FillPolygon`nPress F3 for both`nYou would only see it form after adding 3+ points!",0,height*0.1,24,0xFFFFFFFF,"Arial","dsFF000000 aCenter w" width " h" height)
54 |
55 | overlay.EndDraw()
56 | }
57 | return
58 |
59 |
60 | #if WinActive("ahk_id " overlay.hwnd)
61 |
62 | f1::
63 | if (overlay.GetMousePos(x,y))
64 | drawPoints.push([x,y])
65 | return
66 |
67 | f2::
68 | if (overlay.GetMousePos(x,y))
69 | fillPoints.push([x,y])
70 | return
71 |
72 | f3::
73 | if (overlay.GetMousePos(x,y))
74 | bothPoints.push([x,y])
75 | return
76 |
77 | wheeldown::
78 | opacity := (opacity-10 < 1 ? 1 : opacity-10)
79 | return
80 |
81 | wheelup::
82 | opacity := (opacity+10 > 255 ? 255 : opacity+10)
83 | return
84 |
85 | #if
86 |
87 |
88 | WindowMove() {
89 | global moving
90 | moving := 1
91 | }
92 |
93 |
94 | f9::Reload
95 | esc::exitapp
96 |
97 |
--------------------------------------------------------------------------------
/examples/MouseDots.ahk:
--------------------------------------------------------------------------------
1 | #singleinstance,force
2 | setbatchlines,-1
3 | settitlematchmode,2
4 |
5 |
6 | #include ..\shinsoverlayclass.ahk
7 |
8 | if (!WinExist("Untitled - Notepad")) {
9 | msgbox % "Please open a notepad window and press OK to reload"
10 | reload
11 | }
12 | WinActivate, Notepad
13 |
14 | overlay := new ShinsOverlayClass("Untitled - Notepad")
15 |
16 | dots := []
17 | dotRate := 0
18 | dotIndex := 0
19 |
20 | lastX := 0
21 | lastY := 0
22 | toggle := 1 ;start on
23 | settimer,main,10
24 | return
25 |
26 | f2::
27 | toggle := !toggle
28 | if (toggle) {
29 | settimer,main,10
30 | } else {
31 | settimer,main,off
32 | overlay.BeginDraw()
33 | overlay.EndDraw()
34 | }
35 | return
36 |
37 | main:
38 | if (overlay.BeginDraw()) { ;must always call BeginDraw() to start, it returns true if window is valid
39 |
40 | overlay.FillRectangle(overlay.realX,overlay.realY,300,100,0xAA000000)
41 | overlay.DrawText("Press ESC to exit`nPress F2 to toggle overlay",10,10,24,0xFFFFFFFF)
42 |
43 | if (overlay.GetMousePos(mx,my)) { ;if mouse is within overlay area
44 | if (lastX != mx or lastY != my) { ;only draw when moving the mouse
45 | strength := 1.0 + ((abs(lastX-mx) + abs(lasty-my)) / 20)
46 | dotIndex := dotRate
47 | loop 3
48 | dots.push(new _dot(mx,my,random(3,15),random(0xFF505050,0xFFFFFFFF),random(0,360),random(0.50,1.00)*strength,random(0.92,0.99),random(-0.32,-0.13),random(-5.0,-1.7)))
49 | lastX := mx
50 | lastY := my
51 | }
52 | }
53 |
54 | ;draw the dots and remove the ones that expired
55 | i := 1
56 | while(i < dots.length()) {
57 | if (!dots[i].draw(overlay)) {
58 | dots.removeat(i)
59 | } else {
60 | i++
61 | }
62 | }
63 |
64 | overlay.EndDraw() ;must always call EndDraw() to finish drawing
65 | }
66 | return
67 |
68 | random(min,max) {
69 | random,result,min,max
70 | return result
71 | }
72 |
73 | esc::exitapp
74 |
75 | ;simple class to handle dot behaviours
76 | class _dot {
77 |
78 | __New(x,y,size,col,dir,speed,friction,growDir,growCol) {
79 | this.x := x
80 | this.y := y
81 | this.size := size
82 | this.speed := speed
83 | this.friction := friction
84 | this.rgb := (col & 0xFFFFFF)
85 | this.alpha := (col&0xFF000000)>>24
86 | this.dir := dir
87 | this.growDir := growDir
88 | this.growCol := growCol
89 | }
90 |
91 | Draw(overlay) {
92 | this.size += this.growDir
93 | if (this.size < 0.1)
94 | return 0
95 |
96 | this.x += cos(this.dir) * this.speed
97 | this.y += sin(this.dir) * this.speed
98 |
99 | this.speed *= this.friction
100 |
101 | this.alpha += this.growCol
102 |
103 | if (this.alpha < 1)
104 | return 0
105 |
106 | overlay.fillellipse(this.x,this.y,this.size,this.size,(floor(this.alpha)<<24)+this.rgb)
107 | return 1
108 | }
109 | }
110 |
111 |
112 |
--------------------------------------------------------------------------------
/AHK V2/Examples V2/Polygons_V2.ahk:
--------------------------------------------------------------------------------
1 | #Requires AutoHotkey v2.0
2 |
3 | #SingleInstance force
4 | #Include "..\shinsoverlayclass.ahk"
5 |
6 | x := floor(a_screenwidth * 0.2)
7 | y := floor(a_screenheight * 0.2)
8 | width := floor(a_screenwidth * 0.6)
9 | height := floor(a_screenheight * 0.6)
10 | if (width < height) {
11 | height := width
12 | } else {
13 | width := height
14 | }
15 | ;create a octagon window
16 | oRad := 0.25 ;octagon corner radius
17 | windowPolygon := [ [2,height*oRad], [width*oRad,2], [width*(1-oRad),2], [width-2,height*oRad], [width-2,height*(1-oRad)], [width*(1-oRad),height-2], [width*oRad,height-2], [2,height*(1-oRad)] ]
18 |
19 | drawPoints := [] ;set example polygons to be empty, user will define these
20 | fillPoints := []
21 | bothPoints := []
22 |
23 | overlay := ShinsOverlayClass(x,y,width,height,0,0,0)
24 | opacity := 0xBB
25 |
26 | OnMessage(0x201, WindowMove)
27 | moving := false
28 | SetTimer(draw,10)
29 | return
30 |
31 | draw(){
32 | global moving
33 | if (moving) {
34 | PostMessage(0xA1, 2, , , "ahk_id " overlay.hwnd)
35 | while(GetKeyState("lbutton","p")) {
36 | Sleep(100)
37 | }
38 | moving := false
39 | }
40 | if (overlay.BeginDraw()) {
41 |
42 | ;draw background window
43 | overlay.FillPolygon(windowPolygon,(opacity<<24))
44 | overlay.DrawPolygon(windowPolygon,0xFF000000,2)
45 |
46 | overlay.FillPolygon(fillPoints,0x6600FF00)
47 | overlay.DrawPolygon(drawPoints,0xFF0000)
48 |
49 | overlay.FillPolygon(bothPoints,0x6622908A)
50 | overlay.DrawPolygon(bothPoints,0x00FFF1)
51 |
52 | overlay.DrawText("Press ESC to close",0,2,32,0xFFFF0000,"Arial","dsFF000000 aCenter w" width " h" height)
53 |
54 | overlay.DrawText("Press F1 to add points for DrawPolygon`nPress F2 to add points for FillPolygon`nPress F3 for both`nYou would only see it form after adding 3+ points!",0,height*0.1,24,0xFFFFFFFF,"Arial","dsFF000000 aCenter w" width " h" height)
55 |
56 | overlay.EndDraw()
57 | }
58 | return
59 | }
60 |
61 | #HotIf WinActive("ahk_id " overlay.hwnd)
62 | f1::
63 | {
64 | if (overlay.GetMousePos(&x,&y))
65 | drawPoints.push([x,y])
66 | return
67 | }
68 |
69 | f2::
70 | {
71 | if (overlay.GetMousePos(&x,&y))
72 | fillPoints.push([x,y])
73 | return
74 | }
75 |
76 | f3::
77 | {
78 | if (overlay.GetMousePos(&x,&y))
79 | bothPoints.push([x,y])
80 | return
81 | }
82 |
83 | wheeldown::
84 | {
85 | opacity := (opacity-10 < 1 ? 1 : opacity-10)
86 | return
87 | }
88 |
89 | wheelup::
90 | {
91 | opacity := (opacity+10 > 255 ? 255 : opacity+10)
92 | return
93 | }
94 |
95 | #HotIf
96 |
97 | WindowMove(*) {
98 | global moving
99 | moving := 1
100 | }
101 |
102 |
103 | f9::Reload()
104 | esc::ExitApp()
--------------------------------------------------------------------------------
/examples/CrosshairOverlay.ahk:
--------------------------------------------------------------------------------
1 | #singleinstance,force
2 | #include ..\ShinsOverlayClass.ahk
3 |
4 |
5 | iniread,cx,crosshair.ini,pos,x,600
6 | iniread,cy,crosshair.ini,pos,y,600
7 | iniread,cs,crosshair.ini,pos,s,8
8 |
9 | ;some variables for setting the position
10 | setPos := 0
11 | setPosBlink := 0
12 | setPosColor := 0
13 |
14 | ;crosshair settings
15 | crossHairSize := cs
16 | crossHairColor := 0xFF00FF00
17 | crossHairBorderColor := 0xFF000000
18 | crossHairBorderSize := 1 ;if set to 0 then there will be no border
19 |
20 |
21 | ;max reticle size, default 16x16, increase if you need very large crosshair
22 | maxSize := 16
23 | halfSize := floor(maxSize/2)
24 |
25 | o := new ShinsOverlayClass(cx,cy,maxSize,maxSize)
26 |
27 | gosub update ;draw initially
28 | return
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | ; press F1 to enable positioning mode
41 | f1::
42 | setPos := !setPos
43 | if (!setPos) {
44 | iniwrite,%cx%,crosshair.ini,pos,x
45 | iniwrite,%cy%,crosshair.ini,pos,y
46 | iniwrite,%crossHairSize%,crosshair.ini,pos,s
47 | settimer,update,off
48 | gosub update
49 | } else {
50 | settimer,update,50
51 | }
52 | return
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | #if setPos
69 |
70 | ; if setting position use arrows keys to move, holding shift will move more
71 | ; page up and page down affects crosshair size
72 |
73 | pgup::
74 | crossHairSize++
75 | return
76 | pgdn::
77 | crossHairSize--
78 | if (crossHairSize <= 0)
79 | crossHairSize := 1
80 | return
81 |
82 | right::
83 | cx+=1
84 | o.SetPosition(cx,cy)
85 | return
86 | +right::
87 | cx+=10
88 | o.SetPosition(cx,cy)
89 | return
90 |
91 | left::
92 | cx-=1
93 | o.SetPosition(cx,cy)
94 | return
95 | +left::
96 | cx-=10
97 | o.SetPosition(cx,cy)
98 | return
99 |
100 |
101 | down::
102 | cy+=1
103 | o.SetPosition(cx,cy)
104 | return
105 | +down::
106 | cy+=10
107 | o.SetPosition(cx,cy)
108 | return
109 |
110 | up::
111 | cy-=1
112 | o.SetPosition(cx,cy)
113 | return
114 | +up::
115 | cy-=10
116 | o.SetPosition(cx,cy)
117 | return
118 |
119 |
120 | #if
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | update:
131 | if (o.BeginDraw()) {
132 |
133 | if (crossHairBorderSize > 0) {
134 | o.FillEllipse(halfSize,halfSize,crossHairSize,crossHairSize,crossHairBorderColor)
135 | o.FillEllipse(halfSize,halfSize,crossHairSize-crossHairBorderSize,crossHairSize-crossHairBorderSize,crossHairColor)
136 | } else {
137 | o.FillEllipse(halfSize,halfSize,crossHairSize,crossHairSize,crossHairColor)
138 | }
139 |
140 | if (setPos) {
141 | if (a_tickcount > setPosBlink) {
142 | setPosColor := !setPosColor
143 | setPosBlink := a_tickcount + 500
144 | }
145 | o.DrawRectangle(1,1,maxSize-1,maxSize-1,(setPosColor?0xFFFFFFFF:0xFF000000))
146 | }
147 |
148 | o.EndDraw()
149 | }
150 | return
151 |
152 |
153 |
154 |
155 | f9::Reload
156 |
--------------------------------------------------------------------------------
/AHK V2/Examples V2/MouseDots_V2.ahk:
--------------------------------------------------------------------------------
1 | #Requires AutoHotkey v2.0
2 |
3 | #SingleInstance force
4 |
5 | SetTitleMatchMode(2)
6 |
7 | #Include "..\shinsoverlayclass.ahk"
8 |
9 | ;simple class to handle dot behaviours
10 | class _dot {
11 |
12 | __New(x,y,size,col,dir,speed,friction,growDir,growCol) {
13 | this.x := x
14 | this.y := y
15 | this.size := size
16 | this.speed := speed
17 | this.friction := friction
18 | this.rgb := (col & 0xFFFFFF)
19 | this.alpha := (col&0xFF000000)>>24
20 | this.dir := dir
21 | this.growDir := growDir
22 | this.growCol := growCol
23 | }
24 |
25 | Draw(overlay) {
26 | this.size += this.growDir
27 | if (this.size < 0.1)
28 | return 0
29 |
30 | this.x += cos(this.dir) * this.speed
31 | this.y += sin(this.dir) * this.speed
32 |
33 | this.speed *= this.friction
34 |
35 | this.alpha += this.growCol
36 |
37 | if (this.alpha < 1)
38 | return 0
39 |
40 | overlay.fillellipse(this.x,this.y,this.size,this.size,(floor(this.alpha)<<24)+this.rgb)
41 | return 1
42 | }
43 | }
44 |
45 |
46 | if (!WinExist("Untitled - Notepad")) {
47 | MsgBox("Please open a notepad window and press OK to reload")
48 | Reload()
49 | }
50 | WinActivate("Notepad")
51 |
52 | overlay := ShinsOverlayClass("Untitled - Notepad")
53 |
54 | dots := []
55 | dotRate := 0
56 | dotIndex := 0
57 |
58 | lastX := 0
59 | lastY := 0
60 | toggle := 1 ;start on
61 | SetTimer(main,10)
62 | return
63 |
64 | f2::
65 | {
66 | global toggle
67 | toggle := !toggle
68 | if (toggle) {
69 | SetTimer(main,10)
70 | } else {
71 | SetTimer(main,0)
72 | overlay.BeginDraw()
73 | overlay.EndDraw()
74 | }
75 | return
76 | }
77 |
78 | main(){
79 | global lastX, lastY
80 | static i
81 |
82 | if (overlay.BeginDraw()) { ;must always call BeginDraw() to start, it returns true if window is valid
83 |
84 | overlay.FillRectangle(overlay.realX,overlay.realY,300,100,0xAA000000)
85 | overlay.DrawText("Press ESC to exit`nPress F2 to toggle overlay",10,10,24,0xFFFFFFFF)
86 |
87 | if (overlay.GetMousePos(&mx, &my)) { ;if mouse is within overlay area
88 | if (lastX != mx or lastY != my) { ;only draw when moving the mouse
89 | strength := 1.0 + ((abs(lastX-mx) + abs(lasty-my)) / 20)
90 | dotIndex := dotRate
91 | Loop 3
92 | dots.push(_dot(mx,my,random(3,15),random(0xFF505050,0xFFFFFFFF),random(0,360),random(0.50,1.00)*strength,random(0.92,0.99),random(-0.32,-0.13),random(-5.0,-1.7)))
93 | lastX := mx
94 | lastY := my
95 | }
96 | }
97 |
98 | ;draw the dots and remove the ones that expired
99 | i := 1
100 | }
101 | while(i < dots.Length) {
102 | if (!dots[i].draw(overlay)) {
103 | dots.removeat(i)
104 | } else {
105 | i++
106 | }
107 | }
108 |
109 | overlay.EndDraw() ;must always call EndDraw() to finish drawing
110 | return
111 | }
112 |
113 | esc::ExitApp()
114 |
--------------------------------------------------------------------------------
/AHK V2/Examples V2/CrosshairOverlay_V2.ahk:
--------------------------------------------------------------------------------
1 | #Requires Autohotkey v2.0
2 | #SingleInstance force
3 | #Include ..\ShinsOverlayClass.ahk
4 |
5 | cx := IniRead("crosshair.ini", "pos", "x", 600)
6 | cy := IniRead("crosshair.ini", "pos", "y", 600)
7 | cs := IniRead("crosshair.ini", "pos", "s", 8)
8 |
9 | ;some variables for setting the position
10 | setPos := 0
11 | setPosBlink := 0
12 | setPosColor := 0
13 |
14 | ;crosshair settings
15 | crossHairSize := cs
16 | crossHairColor := 0xFF00FF00
17 | crossHairBorderColor := 0xFF000000
18 | crossHairBorderSize := 1 ;if set to 0 then there will be no border
19 |
20 | ;max reticle size, default 16x16, increase if you need very large crosshair
21 | maxSize := 16
22 | halfSize := floor(maxSize/2)
23 |
24 | o := ShinsOverlayClass(cx,cy,maxSize,maxSize)
25 |
26 | update() ;draw initially
27 | return
28 |
29 |
30 | ; press F1 to enable positioning mode
31 | f1::
32 | {
33 | global
34 | setPos := !setPos
35 | if (!setPos) {
36 | IniWrite(cx, "crosshair.ini", "pos", "x")
37 | IniWrite(cy, "crosshair.ini", "pos", "y")
38 | IniWrite(crossHairSize, "crosshair.ini", "pos", "s")
39 | SetTimer(update,0)
40 | update()
41 | } else {
42 | SetTimer(update,50)
43 | }
44 | return
45 | }
46 |
47 |
48 | #HotIf setPos
49 |
50 | ; if setting position use arrows keys to move, holding shift will move more
51 | ; page up and page down affects crosshair size
52 |
53 | pgup::
54 | {
55 | global
56 | crossHairSize++
57 | return
58 | }
59 | pgdn::
60 | {
61 | global
62 | crossHairSize--
63 | if (crossHairSize <= 0)
64 | crossHairSize := 1
65 | return
66 | }
67 |
68 | right::
69 | {
70 | global
71 | cx+=1
72 | o.SetPosition(cx,cy)
73 | return
74 | }
75 | +right::
76 | {
77 | global
78 | cx+=10
79 | o.SetPosition(cx,cy)
80 | return
81 | }
82 |
83 | left::
84 | {
85 | global
86 | cx-=1
87 | o.SetPosition(cx,cy)
88 | return
89 | }
90 | +left::
91 | {
92 | global
93 | cx-=10
94 | o.SetPosition(cx,cy)
95 | return
96 | }
97 |
98 | down::
99 | {
100 | global
101 | cy+=1
102 | o.SetPosition(cx,cy)
103 | return
104 | }
105 | +down::
106 | {
107 | global
108 | cy+=10
109 | o.SetPosition(cx,cy)
110 | return
111 | }
112 |
113 | up::
114 | {
115 | global
116 | cy-=1
117 | o.SetPosition(cx,cy)
118 | return
119 | }
120 | +up::
121 | {
122 | global
123 | cy-=10
124 | o.SetPosition(cx,cy)
125 | return
126 | }
127 |
128 | #HotIf
129 |
130 | update(){
131 | global
132 | if (o.BeginDraw()) {
133 |
134 | if (crossHairBorderSize > 0) {
135 | o.FillEllipse(halfSize,halfSize,crossHairSize,crossHairSize,crossHairBorderColor)
136 | o.FillEllipse(halfSize,halfSize,crossHairSize-crossHairBorderSize,crossHairSize-crossHairBorderSize,crossHairColor)
137 | } else {
138 | o.FillEllipse(halfSize,halfSize,crossHairSize,crossHairSize,crossHairColor)
139 | }
140 |
141 | if (setPos) {
142 | if (a_tickcount > setPosBlink) {
143 | setPosColor := !setPosColor
144 | setPosBlink := a_tickcount + 500
145 | }
146 | o.DrawRectangle(1,1,maxSize-1,maxSize-1,(setPosColor?0xFFFFFFFF:0xFF000000))
147 | }
148 |
149 | o.EndDraw()
150 | }
151 | return
152 | }
153 |
154 |
155 | f9::Reload()
156 |
--------------------------------------------------------------------------------
/examples/GeneralExample.ahk:
--------------------------------------------------------------------------------
1 | #singleinstance,force
2 | setbatchlines,-1
3 | settitlematchmode,2
4 |
5 | #include ..\ShinsOverlayClass.ahk
6 |
7 | overlay := new ShinsOverlayClass(50,50,1100,130) ;initally create a static overlay
8 |
9 | rot := 0 ;rotation value for drawing the circling ellipse
10 | len := (overlay.width > overlay.height ? overlay.height : overlay.width) / 4 ;length to rotate around
11 | stickFrame := 0
12 | nextStickFrame := a_tickcount + 100
13 | stickRot := 0 ;rotation for stickman
14 | settimer,draw,10 ;overlay essentially requires a timer if attaching to window, as the window checks are done in the BeginDraw() function
15 | return
16 |
17 | f1::
18 | overlay.AttachToWindow("ahk_id " winexist("a"),1)
19 | len := (overlay.width > overlay.height ? overlay.height : overlay.width) / 4
20 | return
21 |
22 | esc::exitapp
23 |
24 |
25 | draw:
26 | if (overlay.BeginDraw()) { ;must always be called to start drawing; BeginDraw() also handles window checks, for position/size/foreground change (if attached)
27 |
28 | if (overlay.attachHwnd) { ;if the overlay is attached to a window
29 |
30 | ;update some math variables
31 | rot+= 0.02
32 | if (rot > 6.28)
33 | rot := 0
34 | x := (overlay.width/2) + cos(rot) * len
35 | y := (overlay.height/2) + sin(rot) * len
36 |
37 | ;draw rectangle around window using real coordinates
38 | ;otherwise by default it may include the invisible borders
39 | rx := overlay.realX
40 | ry := overlay.realY
41 | rx2 := overlay.realX2
42 | ry2 := overlay.realY2
43 | rw := overlay.realWidth
44 | rh := overlay.realHeight
45 |
46 |
47 |
48 | if (overlay.GetMousePos(mx,my,1)) {
49 |
50 | ;fill squares only if the rotation circle is within the region
51 | if (x > mx and y > my) {
52 | overlay.FillRectangle(mx,my,rx2-mx,ry2-my,0x66116666)
53 | } else if (x < mx and y > my) {
54 | overlay.FillRectangle(rx,my,mx-rx,ry2-my,0x66116611)
55 | } else if (x < mx and y < my) {
56 | overlay.FillRectangle(rx,ry,mx-rx,my-ry,0x66111166)
57 | } else {
58 | overlay.FillRectangle(mx,ry,rx2-mx,my,0x66661111)
59 | }
60 |
61 | overlay.DrawLine(rx+1,my,rx2,my,0xFF000000,3) ;draw lines to the mouse position
62 | overlay.DrawLine(mx,ry+1,mx,ry2,0xFF000000,3)
63 | overlay.DrawLine(rx+1,my,rx2,my,0xFF3EF9CE,1)
64 | overlay.DrawLine(mx,ry+1,mx,ry2,0xFF3EF9CE,1)
65 |
66 | overlay.FillEllipse(mx,my,3,3,0xFFFFFFFF)
67 | }
68 |
69 |
70 | overlay.DrawLine(rx,ry,x,y,0xFFFF00FF,4) ;draw line from top left to rotating circle
71 | overlay.DrawLine(x,y,rw-1,rh-1,0xFFFF00FF,4) ;draw line from rotating circle to bottom right
72 | overlay.DrawEllipse(x,y,30,30,0xFF000000,5)
73 | overlay.DrawEllipse(x,y,30,30,0xFFFF0000,2) ;draw the rotating circles
74 | overlay.FillEllipse(x,y,17,17,0xFF000000)
75 | overlay.FillEllipse(x,y,15,15,0xFF00FF00)
76 | overlay.DrawRectangle(rx+1,ry+1,rw-1,rh-1,0xFFFF0000,2) ;draw a rectangle around the window
77 |
78 |
79 | ;drawing stickman, scaling from 32x32 to 128x128 and animating from spritesheet
80 | overlay.DrawImage("stickMan.png",100,100,128,128,stickFrame*32,0,32,32,1,0,stickRot) ;draw a rotating stickman who animates
81 | if (a_tickcount > nextStickFrame) {
82 | stickFrame++
83 | if (stickFrame > 3)
84 | stickFrame := 0
85 | nextStickFrame := a_tickcount + 100 ;next frame in 100 ms
86 | }
87 | stickRot+= 1
88 | if (stickRot > 360)
89 | stickRot := 0
90 |
91 | overlay.DrawText("Press ESC to close!",10,200,24 + (rot*3),0xFFFFFFFF,"Courier","dsFF000000") ;draw text that grows and shrinks
92 | overlay.DrawText("Press ESC to close!",10,200 + (24+(rot*3)),24 + (rot*3),0xFF000000,"Courier","dsFFFFFFFF") ;draw text that grows and shrinks
93 | } else {
94 | overlay.FillRectangle(0,0,overlay.width,overlay.height,0xaa000000)
95 | overlay.DrawText("Press F1 to attach the overlay to a window to begin!`nYou can do this multiple times!",0,0,40,0xFFFFFFFF,"Courier","dsFF000000")
96 | }
97 | overlay.EndDraw() ;must always be called to end the drawing and update the overlay
98 | }
99 | return
100 |
--------------------------------------------------------------------------------
/AHK V2/Examples V2/GeneralExample_V2.ahk:
--------------------------------------------------------------------------------
1 | #Requires AutoHotkey v2.0
2 | #SingleInstance force
3 | ; REMOVED: setbatchlines,-1
4 | SetTitleMatchMode(2)
5 |
6 | #Include "..\ShinsOverlayClass.ahk"
7 |
8 | overlay := ShinsOverlayClass(50,50,1100,130) ;initally create a static overlay
9 |
10 | rot := 0 ;rotation value for drawing the circling ellipse
11 | len := (overlay.width > overlay.height ? overlay.height : overlay.width) / 4 ;length to rotate around
12 | stickFrame := 0
13 | nextStickFrame := a_tickcount + 100
14 | stickRot := 0 ;rotation for stickman
15 | SetTimer(draw,10) ;overlay essentially requires a timer if attaching to window, as the window checks are done in the BeginDraw() function
16 | return
17 |
18 | f1::
19 | {
20 | overlay.AttachToWindow("ahk_id " winexist("a"),1)
21 | len := (overlay.width > overlay.height ? overlay.height : overlay.width) / 4
22 | return
23 | }
24 |
25 | esc::ExitApp()
26 |
27 | draw(){
28 | global
29 | if (overlay.BeginDraw()) { ;must always be called to start drawing; BeginDraw() also handles window checks, for position/size/foreground change (if attached)
30 |
31 | if (overlay.attachHwnd) { ;if the overlay is attached to a window
32 |
33 | ;update some math variables
34 | rot+= 0.02
35 | if (rot > 6.28)
36 | rot := 0
37 | x := (overlay.width/2) + cos(rot) * len
38 | y := (overlay.height/2) + sin(rot) * len
39 |
40 | ;draw rectangle around window using real coordinates
41 | ;otherwise by default it may include the invisible borders
42 | rx := overlay.realX
43 | ry := overlay.realY
44 | rx2 := overlay.realX2
45 | ry2 := overlay.realY2
46 | rw := overlay.realWidth
47 | rh := overlay.realHeight
48 |
49 | if (overlay.GetMousePos(&mx,&my,1)) {
50 |
51 | ;fill squares only if the rotation circle is within the region
52 | if (x > mx and y > my) {
53 | overlay.FillRectangle(mx,my,rx2-mx,ry2-my,0x66116666)
54 | } else if (x < mx and y > my) {
55 | overlay.FillRectangle(rx,my,mx-rx,ry2-my,0x66116611)
56 | } else if (x < mx and y < my) {
57 | overlay.FillRectangle(rx,ry,mx-rx,my-ry,0x66111166)
58 | } else {
59 | overlay.FillRectangle(mx,ry,rx2-mx,my,0x66661111)
60 | }
61 |
62 | overlay.DrawLine(rx+1,my,rx2,my,0xFF000000,3) ;draw lines to the mouse position
63 | overlay.DrawLine(mx,ry+1,mx,ry2,0xFF000000,3)
64 | overlay.DrawLine(rx+1,my,rx2,my,0xFF3EF9CE,1)
65 | overlay.DrawLine(mx,ry+1,mx,ry2,0xFF3EF9CE,1)
66 |
67 | overlay.FillEllipse(mx,my,3,3,0xFFFFFFFF)
68 | }
69 |
70 | overlay.DrawLine(rx,ry,x,y,0xFFFF00FF,4) ;draw line from top left to rotating circle
71 | overlay.DrawLine(x,y,rw-1,rh-1,0xFFFF00FF,4) ;draw line from rotating circle to bottom right
72 | overlay.DrawEllipse(x,y,30,30,0xFF000000,5)
73 | overlay.DrawEllipse(x,y,30,30,0xFFFF0000,2) ;draw the rotating circles
74 | overlay.FillEllipse(x,y,17,17,0xFF000000)
75 | overlay.FillEllipse(x,y,15,15,0xFF00FF00)
76 | overlay.DrawRectangle(rx+1,ry+1,rw-1,rh-1,0xFFFF0000,2) ;draw a rectangle around the window
77 |
78 | ;drawing stickman, scaling from 32x32 to 128x128 and animating from spritesheet
79 | overlay.DrawImage("stickMan.png",100,100,128,128,stickFrame*32,0,32,32,1,0,stickRot) ;draw a rotating stickman who animates
80 | if (a_tickcount > nextStickFrame) {
81 | stickFrame++
82 | if (stickFrame > 3)
83 | stickFrame := 0
84 | nextStickFrame := a_tickcount + 100 ;next frame in 100 ms
85 | }
86 | stickRot+= 1
87 | if (stickRot > 360)
88 | stickRot := 0
89 |
90 | overlay.DrawText("Press ESC to close!",10,200,24 + (rot*3),0xFFFFFFFF,"Courier","dsFF000000") ;draw text that grows and shrinks
91 | overlay.DrawText("Press ESC to close!",10,200 + (24+(rot*3)),24 + (rot*3),0xFF000000,"Courier","dsFFFFFFFF") ;draw text that grows and shrinks
92 | } else {
93 | overlay.FillRectangle(0,0,overlay.width,overlay.height,0xaa000000)
94 | overlay.DrawText("Press F1 to attach the overlay to a window to begin!`nYou can do this multiple times!",0,0,40,0xFFFFFFFF,"Courier","dsFF000000")
95 | }
96 | overlay.EndDraw() ;must always be called to end the drawing and update the overlay
97 | }
98 | return
99 | }
100 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ShinsOverlayClass
2 | A direct2d overlay for AutoHotkey **V1.1+ and V2+**, made to be user friendly and fast.
3 | Supports 32bit and 64bit for systems running windows 7+ including the newest windows 11.
4 |
5 | # YouTube simple overview and examples
6 |
7 | [](https://www.youtube.com/watch?v=L2Cb1UCJDEg)
8 |
9 | ## Functions
10 | ```ruby
11 | #AttachToWindow...........Attach the overlay to a window
12 | AttachToWindow(title,AttachToClientArea:=0,foreground:=1)
13 |
14 | #BeginDraw................Begins the drawing process, MUST ALWAYS start with BeginDraw(), if attached to window returns 1 if window is available, 0 otherwise
15 | BeginDraw()
16 |
17 | #EndDraw..................End the drawing process, MUST ALWAYS end with EndDraw()
18 | EndDraw()
19 |
20 | #DrawImage................Draw an image
21 | DrawImage(image,dstX,dstY,dstW:=0,dstH:=0,srcX:=0,srcY:=0,srcW:=0,srcH:=0,alpha:=1,drawCentered:=0,rotation:=0,rotOffX:=0,rotOffY:=0)
22 |
23 | #DrawText.................Draws text, supports a dropshadow if a valid color is supplied
24 | DrawText(text,x,y,size:=18,color:=0xFF000000,fontName:="Arial",extraOptions:="") #see the comments above the function in the class file for more info
25 |
26 | #GetTextMetrics..........Get the dimensions of text
27 | GetTextMetrics(text, size, fontName, maxWidth:=5000, maxHeight:=5000)
28 |
29 | #SetTextRenderParams.....Set additional parameters for text
30 | SetTextRenderParams(gamma:=1, contrast:=0, cleartype:=1, pixelGeom:=0, renderMode:=0)
31 |
32 | #DrawEllipse..............Draws an ellipse
33 | DrawEllipse(x, y, w, h, color, thickness:=1)
34 |
35 | #FillEllipse..............Fills an ellipse
36 | FillEllipse(x, y, w, h, color)
37 |
38 | #DrawCircle...............Draw a circle
39 | DrawCircle(x, y, radius, color, thickness:=1)
40 |
41 | #FillCircle...............Fill a circle
42 | FillCircle(x, y, radius, color)
43 |
44 | #DrawRectangle............Draws a rectangle
45 | DrawRectangle(x, y, w, h, color, thickness:=1)
46 |
47 | #FillRectangle............Fills a rectangle
48 | FillRectangle(x, y, w, h, color)
49 |
50 | #DrawRoundedRectangle.....Draw a rectangle with rounded corners
51 | DrawRoundedRectangle(x, y, w, h, radiusX, radiusY, color, thickness:=1)
52 |
53 | #FillRoundedRectangle.....Fill a rectangle with rounded corners
54 | FillRoundedRectangle(x, y, w, h, radiusX, radiusY, color)
55 |
56 | #DrawLine.................Draws a line from 2 positions
57 | DrawLine(x1,y1,x2,y2,color,thickness:=1,rounded:=0)
58 |
59 | #DrawLines................Draws an array of lines, points must be in an array [[x,y],[x,y]] etc.
60 | DrawLines(points,color,connect:=0,thickness:=1,rounded:=0)
61 |
62 | #DrawPolygon..............Draws a polygon outline, points must be in an array [[x,y],[x,y]] etc.
63 | DrawPolygon(points,color,thickness:=1,rounded:=0,xOffset:=0,yOffset:=0)
64 |
65 | #FillPolygon..............Fill a polygon, points must be in an array [[x,y],[x,y]] etc.
66 | FillPolygon(points,color,xoffset:=0,yoffset:=0)
67 |
68 | #SetPosition..............Sets the overlay position, only when not attached
69 | SetPosition(x,y,w:=0,h:=0)
70 |
71 | #GetImageDimensions.......Gets the width and height of a cached image
72 | GetImageDimensions(image,byref w, byref h)
73 |
74 | #GetMousePosition.........Gets the mouse position relative to the overlay, additionally returns true if the mouse is inside the overlay, 0 otherwise
75 | GetMousePos(byref x, byref y, realRegionOnly:=0)
76 |
77 | #Clear...................Clears the canvas
78 | Clear()
79 |
80 | #RegCallback............Register a function to call when an event happens
81 | RegCallback(func, callback) ;Size, Position, Active
82 |
83 | #ClearCallback.........Clear a callback
84 | ClearCallback(callback)
85 | ```
86 |
87 | ## Notes
88 |
89 | * **V2 now supported.**
90 | *
91 | * I've only tested on my end and can confirm it works for me using 32/64 bit AHK_L (AHK V1.1) and AHK V2 on Windows 10.
92 | * If it doesn't work for you let me know, I may be able to help, or maybe not, just depends.
93 |
94 | ### Donations
95 |
96 | Thanks for stopping by! If you really enjoy my code and want to make a small donation, then here's a link! https://www.buymeacoffee.com/Spawnova
97 |
98 | **I will continue to provide code, and support released classes regardless of any monetary support**, and I'd rather none is given if you are not comfortably in a position to do so!
99 |
--------------------------------------------------------------------------------
/examples/EverythingExample.ahk:
--------------------------------------------------------------------------------
1 | #singleinstance,force
2 | #include ..\shinsoverlayclass.ahk
3 |
4 | x := floor(a_screenwidth * 0.2)
5 | y := floor(a_screenheight * 0.2)
6 | width := floor(a_screenwidth * 0.6)
7 | height := floor(a_screenheight * 0.6)
8 |
9 | overlay := new ShinsOverlayClass(x,y,width,height,0,0,0)
10 | opacity := 0xBB
11 |
12 |
13 | step := 1
14 | stepsText := []
15 | stepsText.push("Welcome to the Everything example!`nHere I will demonstrate some of the functions of the class`nPress Left or Right to progress!`nUse scrollwheel to change window opacity")
16 | stepsText.push("Drawing Lines!`nDrawLine(x1, y1, x2, y2, color, thickness:=1, rounded:=0)`n`n")
17 | stepsText.push("Drawing Lines!`nA bunch of little lines could look like rain!")
18 | stepsText.push("Drawing circles and ellipses!`nDrawEllipse(x, y, w, h, color, thickness:=1)`nFillEllipse(x, y, w, h, color)`nDrawCircle(x, y, radius, color, thickness:=1)`nFillCircle(x, y, radius, color)")
19 | stepsText.push("Drawing circles and ellipses!`nMaybe a moving ball?")
20 | stepsText.push("Drawing rectangles!`nDrawRectangle(x, y, w, h, color, thickness:=1)`nFillRectangle(x, y, w, h, color)`nDrawRoundedRectangle(x, y, w, h, radiusX, radiusY, color, thickness:=1)`nFillRoundedRectangle(x, y, w, h, radiusX, radiusY, color)")
21 | stepsText.push("Drawing rectangles!`nA bouncy block!")
22 | stepsText.push("Drawing images!`nDrawImage(image,dstX,dstY,dstW:=0,dstH:=0,srcX:=0,srcY:=0,srcW:=0,srcH:=0,alpha:=1,drawCentered:=0,rotation:=0)")
23 | stepsText.push("Drawing text!`nDrawText(text,x,y,size:=18,color:=0xFF000000,fontName:=""Arial"",extraOptions:="""")")
24 | stepsText.push("That's all folks!")
25 |
26 | overlay.GetImageDimensions("stickman.png",stickW,stickH)
27 |
28 | trails := []
29 | trailColor := 0xFF00FF00
30 | lastX := -1
31 | lastY := -1
32 |
33 | onmessage(0x201,"WindowMove")
34 | moving := false
35 | settimer,draw,10
36 | return
37 |
38 |
39 | draw:
40 | if (moving) {
41 | postmessage,0xA1,2,,,% "ahk_id " overlay.hwnd
42 | while(GetKeyState("lbutton","p")) {
43 | sleep 100
44 | }
45 | moving := false
46 | lastX := lastY := -1
47 | }
48 | if (overlay.BeginDraw()) {
49 |
50 | ;draw background
51 | overlay.FillRoundedRectangle(0,0,overlay.width,overlay.height,55,55,(opacity<<24))
52 | overlay.DrawRoundedRectangle(0,0,overlay.width,overlay.height,55,55,0xFFFFFFFF,2)
53 |
54 | ;draw examples per step
55 | if (step = 1) {
56 |
57 | overlay.DrawText("Use the left and right arrows to navigate between pages`n`nScrollwheel adjusts window opacity",0,height*0.5,42,0xFF99FF8B,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
58 |
59 | } else if (step = 2) {
60 |
61 | overlay.DrawText("Thin white line",width*0.11,height*0.2,18,0xFFFFFF00)
62 | overlay.DrawLine(width*0.1,height*0.2,width*0.1,height*0.9,0xFFFFFFFF)
63 |
64 | overlay.DrawText("Now green",width*0.26,height*0.2,18,0xFFFFFF00)
65 | overlay.DrawLine(width*0.25,height*0.2,width*0.25,height*0.9,0xFF00FF00)
66 |
67 | overlay.DrawText("Now thick",width*0.41,height*0.2,18,0xFFFFFF00)
68 | overlay.DrawLine(width*0.4,height*0.2,width*0.4,height*0.9,0xFF00FF00,15)
69 |
70 | overlay.DrawText("Now rounded",width*0.56,height*0.2,18,0xFFFFFF00)
71 | overlay.DrawLine(width*0.55,height*0.2,width*0.55,height*0.9,0xFF00FF00,15,1)
72 |
73 | overlay.DrawText("And a thicker line behind`ncan create a border!",width*0.71,height*0.2,18,0xFFFFFF00)
74 | overlay.DrawLine(width*0.7,height*0.2,width*0.7,height*0.9,0xFFFFFFFF,21,1)
75 | overlay.DrawLine(width*0.7,height*0.2,width*0.7,height*0.9,0xFF000000,19,1)
76 | overlay.DrawLine(width*0.7,height*0.2,width*0.7,height*0.9,0xFF00FF00,15,1)
77 |
78 | } else if (step = 3) {
79 |
80 | rainDir += rainInc * random(1,10)
81 | if (rainDir > 2.3) {
82 | rainInc := -0.001
83 | rainDir := 2.3
84 | } else if (rainDir < 0.7) {
85 | rainDir := 0.7
86 | rainInc := 0.001
87 | }
88 | if (objs.length() < 500)
89 | loop 1
90 | objs.push(new rain(-500,overlay.width+500,-100,0,(random(200,255)<<24)+(random(95,230)<<16)+(random(200,250)<<8)+random(222,255),overlay.height))
91 | for k,v in objs
92 | v.draw(overlay,rainDir)
93 |
94 | } else if (step = 4) {
95 |
96 | overlay.DrawText("A red circle",width*0.18,height*0.45,18,0xFFFFFF00)
97 | overlay.FillCircle(width*0.2,height*0.5,10,0xFFFF0000)
98 |
99 | overlay.DrawText("A red ellipse",width*0.23,height*0.50,18,0xFFFFFF00)
100 | overlay.FillEllipse(width*0.25,height*0.55,30,10,0xFFFF0000)
101 |
102 | overlay.DrawText("A green circle outline",width*0.38,height*0.45,18,0xFFFFFF00)
103 | overlay.DrawCircle(width*0.4,height*0.5,10,0xFF00FF00)
104 |
105 | overlay.DrawText("A green ellipse outline",width*0.43,height*0.50,18,0xFFFFFF00)
106 | overlay.DrawEllipse(width*0.45,height*0.55,30,10,0xFF00FF00)
107 |
108 | overlay.DrawText("Both!",width*0.58,height*0.45,18,0xFFFFFF00)
109 | overlay.FillCircle(width*0.6,height*0.5,10,0xFFFF0000)
110 | overlay.DrawCircle(width*0.6,height*0.5,10,0xFF00FF00)
111 |
112 | overlay.DrawText("Both with thickness!",width*0.63,height*0.50,18,0xFFFFFF00)
113 | overlay.FillEllipse(width*0.65,height*0.55,30,10,0xFFFF0000)
114 | overlay.DrawEllipse(width*0.65,height*0.55,30,10,0xFF00FF00,3)
115 |
116 |
117 | } else if (step = 5) {
118 | ballX += ballInc
119 | if (ballX > width*0.8) {
120 | ballInc := -ballInc
121 | ballX := width*0.8
122 | } else if (ballX < width*0.2) {
123 | ballInc := -ballInc
124 | ballX := width*0.2
125 | }
126 | overlay.FillEllipse(width*0.5,height*0.62,width*0.5,height*0.1,0xFF777777)
127 | overlay.DrawEllipse(width*0.5,height*0.62,width*0.5,height*0.1,0xFFFFFFFF,2)
128 |
129 | overlay.FillEllipse(ballX,ballY+30,30,15,0x44000000)
130 | overlay.FillEllipse(ballX,ballY+30,38,15,0x44000000)
131 | overlay.FillEllipse(ballX,ballY+30,45,15,0x44000000)
132 |
133 | overlay.FillCircle(ballX,ballY,30,0xFFFF0000)
134 | overlay.FillEllipse(ballX,ballY-20,20,10,0x99FFFFFF)
135 | overlay.DrawCircle(ballX,ballY,30,0xFF000000)
136 |
137 | } else if (step = 6) {
138 |
139 | overlay.DrawText("A red outline",width*0.09,height*0.3,18,0xFFFFFFFF)
140 | overlay.DrawRectangle(width*0.1,height*0.35,width*0.05,height*0.5,0xFFFF4D4D)
141 |
142 | overlay.DrawText("blue",width*0.24,height*0.3,18,0xFFFFFFFF)
143 | overlay.FillRectangle(width*0.25,height*0.35,width*0.05,height*0.5,0xFF38C8BF)
144 |
145 | overlay.DrawText("Together",width*0.39,height*0.3,18,0xFFFFFFFF)
146 | overlay.FillRectangle(width*0.4,height*0.35,width*0.05,height*0.5,0xFF38C8BF)
147 | overlay.DrawRectangle(width*0.4,height*0.35,width*0.05,height*0.5,0xFFFF4D4D,2)
148 |
149 | overlay.DrawText("Now rounded",width*0.54,height*0.3,18,0xFFFFFFFF)
150 | overlay.FillRoundedRectangle(width*0.55,height*0.35,width*0.05,height*0.5,30,30,0xFF38C8BF)
151 | overlay.DrawRoundedRectangle(width*0.55,height*0.35,width*0.05,height*0.5,30,30,0xFFFF4D4D,2)
152 |
153 | overlay.DrawText("Now thick",width*0.69,height*0.3,18,0xFFFFFFFF)
154 | overlay.FillRoundedRectangle(width*0.7,height*0.35,width*0.05,height*0.5,30,30,0xFF38C8BF)
155 | overlay.DrawRoundedRectangle(width*0.7,height*0.35,width*0.05,height*0.5,30,30,0xFFFF4D4D,6)
156 |
157 |
158 | } else if (step = 7) {
159 |
160 | if (bouncing > 0) {
161 | bouncing += blockDir * 10
162 | if (bouncing > 150) {
163 | blockDir := -blockDir
164 | bouncing := 150
165 | }
166 | bh := bouncing/2
167 | overlay.FillRoundedRectangle(blockX-bh,blockY+bh,150+bh*2,150-(bouncing/2),bouncing/2,bouncing/14,0xFF0DC8C0)
168 | overlay.DrawRoundedRectangle(blockX-bh,blockY+bh,150+bh*2,150-(bouncing/2),bouncing/2,bouncing/14,0xFF00FFF4)
169 | ;overlay.FillRoundedRectangle(blockX,blockY+(bouncing/2),150,150-(bouncing/2),bouncing/2,bouncing/4,0xFF0DC8C0)
170 | ;overlay.DrawRoundedRectangle(blockX,blockY+(bouncing/2),150,150-(bouncing/2),bouncing/2,bouncing/4,0xFF00FFF4)
171 | } else {
172 | blockY += blockDir * 10
173 | if (blockY < blockMin) {
174 | blockY := blockMin
175 | blockDir := 1
176 | } else if (blockY > blockMax) {
177 | bouncing := 1
178 | }
179 | overlay.FillRectangle(blockX,blockY,150,150,0xFF0DC8C0)
180 | overlay.DrawRectangle(blockX,blockY,150,150,0xFF00FFF4)
181 | }
182 |
183 | } else if (step = 8) {
184 |
185 | overlay.DrawText("Draw basic tile sprite",width*0.1,height*0.25,18,0xFFFFFFFF)
186 | overlay.FillRectangle(width*0.1,height*0.3,stickW,stickH,0x99FFFFFF)
187 | overlay.DrawImage("stickman.png",width*0.1,height*0.3)
188 |
189 | overlay.DrawText("Increase the size",width*0.3,height*0.25,18,0xFFFFFFFF)
190 | overlay.FillRectangle(width*0.3,height*0.3,128*4,128,0x99FFFFFF)
191 | overlay.DrawImage("stickman.png",width*0.3,height*0.3,128*4,128)
192 |
193 | overlay.DrawText("Now just 1 frame",width*0.1,height*0.45,18,0xFFFFFFFF)
194 | overlay.FillRectangle(width*0.1,height*0.5,128,128,0x99FFFFFF)
195 | overlay.DrawImage("stickman.png",width*0.1,height*0.5,128,128,0,0,32,stickH)
196 |
197 | stickIndex--
198 | if (stickIndex = 0) {
199 | stickIndex := stickSpeed
200 | stickFrame++
201 | if (stickFrame = 4)
202 | stickFrame := 0
203 | }
204 | stickRot+=1
205 | if (stickRot > 360)
206 | stickRot := 0
207 |
208 | overlay.DrawText("Now animate the frames",width*0.3,height*0.55,18,0xFFFFFFFF)
209 | overlay.FillRectangle(width*0.3,height*0.6,128,128,0x99FFFFFF)
210 | overlay.DrawImage("stickman.png",width*0.3,height*0.6,128,128,stickFrame*32,0,32,stickH)
211 |
212 | overlay.DrawText("Now rotating",width*0.5,height*0.60,18,0xFFFFFFFF)
213 | overlay.FillRectangle(width*0.5,height*0.65,128,128,0x99FFFFFF)
214 | overlay.DrawImage("stickman.png",width*0.5,height*0.65,128,128,stickFrame*32,0,32,stickH,1,0,stickRot)
215 |
216 | } else if (step = 9) {
217 |
218 | overlay.FillRectangle(width*0.1,height*0.3,width*0.3,height*0.3,0xFF999999)
219 | overlay.DrawText("Font: Arial, Size: 18",width*0.1,height*0.3,18,0xFFFFFFFF,"Arial")
220 | overlay.DrawText("Now Font = Courier",width*0.1,height*0.33,18,0xFFFFFFFF,"Courier")
221 | overlay.DrawText("Now aligned on the right",width*0.1,height*0.36,18,0xFFFFFFFF,"Courier","aRight w" width*0.3 " h" height*0.3)
222 | overlay.DrawText("Now aligned center",width*0.1,height*0.39,18,0xFFFFFFFF,"Courier","aCenter w" width*0.3 " h" height*0.3)
223 | overlay.DrawText("Now red",width*0.1,height*0.42,18,0xFFFF0000,"Courier","aCenter w" width*0.3 " h" height*0.3)
224 | overlay.DrawText("Now with a dropshadow",width*0.1,height*0.45,18,0xFFFF2D2D,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width*0.3 " h" height*0.3)
225 | overlay.DrawText("Now BIG and GREEN",width*0.1,height*0.52,32,0xFF46FF2D,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width*0.3 " h" height*0.3)
226 |
227 | } else if (step = 10) {
228 |
229 | overlay.DrawText("Check out my github for my latest projects",0,height*0.2,56,0xFF99FF8B,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
230 | overlay.DrawText("github.com/Spawnova",0,height*0.3,64,0xFF46FF2D,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
231 | overlay.DrawText("I plan to keep all my projects up to date and to add new features and functions!`n`nPlease let me know if you run into any issues by creating`nan issue/discussion on the github page`nI check there daily and always have time to answer questions and attempt to fix problems!",0,height*0.43,32,0xFFFF8B8B,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
232 | overlay.DrawText("Thank you for using my class and have fun out there!",0,height*0.8,42,0xFF5BFFF5,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
233 | }
234 |
235 | if (overlay.GetMousePos(mx,my)) {
236 | if (lastX != -1 and (lastX != mx or lastY != my)) {
237 | trails.push(new mouseTrail(lastX,lastY,mx,my,trailColor))
238 | }
239 | lastX := mx
240 | lastY := my
241 | } else {
242 | lastX := lastY := -1
243 | }
244 |
245 | i := 1
246 | while(i < trails.length()) {
247 | if (!trails[i].draw(overlay)) {
248 | trails.removeat(i)
249 | } else {
250 | i++
251 | }
252 | }
253 |
254 | ;draw text elements
255 | overlay.DrawText(stepsText[step],50,50,24,0xFFFFFFFF,"Arial","dsFF000000")
256 | overlay.DrawText("Press ESC to close",overlay.width-400,50,32,0xFFCC0000,"Arial","aRight dsFF222222 w" 400-50)
257 | overlay.DrawText("Page " step " of " stepsText.length(),50,overlay.height-74,24,0xFFFFFFFF,"Arial","dsFF000000")
258 | overlay.EndDraw()
259 | }
260 | return
261 |
262 |
263 | WindowMove() {
264 | global moving
265 | moving := 1
266 | }
267 |
268 |
269 | f9::Reload
270 | esc::exitapp
271 |
272 |
273 | #if WinActive("ahk_id " overlay.hwnd)
274 |
275 | left::
276 | if (step > 1) {
277 | step--
278 | gosub checkStep
279 | }
280 | return
281 |
282 | right::
283 | if (step < stepsText.length()) {
284 | step++
285 | gosub checkStep
286 | }
287 | return
288 |
289 | wheeldown::
290 | opacity := (opacity-10 < 1 ? 1 : opacity-10)
291 | return
292 |
293 | wheelup::
294 | opacity := (opacity+10 > 255 ? 255 : opacity+10)
295 | return
296 |
297 | #if
298 |
299 | checkStep:
300 | trailColor := 0xFF000000 + (random(128,255)<<16) + (random(128,255)<<8) + random(128,255)
301 | objs := []
302 | if (step = 3) {
303 | trailColor := 0xFFFFFF00
304 | rainDir := 1.6
305 | rainInc := 0.001
306 | } else if (step = 5) {
307 | ballX := width*0.2
308 | ballY := height*0.6
309 | ballInc := 5
310 | } else if (Step = 7) {
311 | blockX := width*0.45
312 | blockY := height*0.25
313 | blockMin := blockY
314 | blockMax := height*0.8
315 | blockDir := 1
316 | bouncing := 0
317 | } else if (step = 8) {
318 | stickFrame := 0
319 | stickSpeed := 10
320 | stickIndex := stickSpeed
321 | stickRot := 0
322 | }
323 | return
324 |
325 |
326 | class Rain {
327 | __New(minx,maxx,miny,maxy,col,maxHeight) {
328 | this.minx := minx
329 | this.maxx := maxx
330 | this.miny := miny
331 | this.maxy := maxy
332 | this.col := col
333 | this.SetRandom()
334 | this.maxHeight := maxHeight - Random(0,100)
335 | this.puddle := 0
336 | this.puddlex := random(0.33,1.00) * (this.speed/2)
337 | this.puddley := this.puddlex / 2
338 | }
339 |
340 | SetRandom() {
341 | this.speed := random(14.91,32.12)
342 | this.x := random(this.minx,this.maxx)
343 | this.y := random(this.miny,this.maxy)
344 | }
345 |
346 | Draw(o,dir) {
347 | if (this.puddle > 0) {
348 | this.puddle -= random(1,5)
349 | if (this.puddle < 1) {
350 | this.puddle := 0
351 | this.SetRandom()
352 | } else {
353 | o.FillEllipse(this.x,this.y,this.puddlex,this.puddley,(this.puddle<<24) + 0x89E0F1)
354 | }
355 | } else {
356 | x2 := this.x + (cos(dir) * this.speed)
357 | y2 := this.y + (sin(dir) * this.speed)
358 | o.DrawLine(this.x,this.y,x2,y2,this.col)
359 | this.x := x2
360 | this.y := y2
361 | if (this.y > this.maxHeight) {
362 | this.puddle := 255
363 | }
364 | }
365 | }
366 | }
367 |
368 | class mouseTrail {
369 | __New(x1,y1,x2,y2,color) {
370 | this.x1 := x1
371 | this.y1 := y1
372 | this.x2 := x2
373 | this.y2 := y2
374 | this.alpha := (color&0xFF000000)>>24
375 | this.rgb := (color&0xFFFFFF)
376 | }
377 |
378 | Draw(o) {
379 | this.alpha -= 5
380 | if (this.alpha < 1)
381 | return 0
382 | o.DrawLine(this.x1,this.y1,this.x2,this.y2,(this.alpha<<24)+this.rgb,(this.alpha / 255) * 10,1)
383 | return 1
384 | }
385 | }
386 |
387 |
388 | Random(min,max) {
389 | random,result,min,max
390 | return result
391 | }
392 |
--------------------------------------------------------------------------------
/AHK V2/Examples V2/EverythingExample_V2.ahk:
--------------------------------------------------------------------------------
1 | #Requires AutoHotkey v2.0
2 | #SingleInstance force
3 | #Include "..\shinsoverlayclass.ahk"
4 | class Rain {
5 | __New(minx,maxx,miny,maxy,col,maxHeight) {
6 | this.minx := minx
7 | this.maxx := maxx
8 | this.miny := miny
9 | this.maxy := maxy
10 | this.col := col
11 | this.SetRandom()
12 | this.maxHeight := maxHeight - Random(0,100)
13 | this.puddle := 0
14 | this.puddlex := random(0.33,1.00) * (this.speed/2)
15 | this.puddley := this.puddlex / 2
16 | }
17 |
18 | SetRandom() {
19 | this.speed := random(14.91,32.12)
20 | this.x := random(this.minx,this.maxx)
21 | this.y := random(this.miny,this.maxy)
22 | }
23 |
24 | Draw(o,dir) {
25 | if (this.puddle > 0) {
26 | this.puddle -= random(1,5)
27 | if (this.puddle < 1) {
28 | this.puddle := 0
29 | this.SetRandom()
30 | } else {
31 | o.FillEllipse(this.x,this.y,this.puddlex,this.puddley,(this.puddle<<24) + 0x89E0F1)
32 | }
33 | } else {
34 | x2 := this.x + (cos(dir) * this.speed)
35 | y2 := this.y + (sin(dir) * this.speed)
36 | o.DrawLine(this.x,this.y,x2,y2,this.col)
37 | this.x := x2
38 | this.y := y2
39 | if (this.y > this.maxHeight) {
40 | this.puddle := 255
41 | }
42 | }
43 | }
44 | }
45 |
46 | class mouseTrail {
47 | __New(x1,y1,x2,y2,color) {
48 | this.x1 := x1
49 | this.y1 := y1
50 | this.x2 := x2
51 | this.y2 := y2
52 | this.alpha := (color&0xFF000000)>>24
53 | this.rgb := (color&0xFFFFFF)
54 | }
55 |
56 | Draw(o) {
57 | this.alpha -= 5
58 | if (this.alpha < 1)
59 | return 0
60 | o.DrawLine(this.x1,this.y1,this.x2,this.y2,(this.alpha<<24)+this.rgb,(this.alpha / 255) * 10,1)
61 | return 1
62 | }
63 | }
64 |
65 | x := floor(a_screenwidth * 0.2)
66 | y := floor(a_screenheight * 0.2)
67 | width := floor(a_screenwidth * 0.6)
68 | height := floor(a_screenheight * 0.6)
69 |
70 | overlay := ShinsOverlayClass(x,y,width,height,0,0,0)
71 | opacity := 0xBB
72 |
73 | step := 1
74 | stepsText := []
75 | stepsText.push("Welcome to the Everything example!`nHere I will demonstrate some of the functions of the class`nPress Left or Right to progress!`nUse scrollwheel to change window opacity")
76 | stepsText.push("Drawing Lines!`nDrawLine(x1, y1, x2, y2, color, thickness:=1, rounded:=0)`n`n")
77 | stepsText.push("Drawing Lines!`nA bunch of little lines could look like rain!")
78 | stepsText.push("Drawing circles and ellipses!`nDrawEllipse(x, y, w, h, color, thickness:=1)`nFillEllipse(x, y, w, h, color)`nDrawCircle(x, y, radius, color, thickness:=1)`nFillCircle(x, y, radius, color)")
79 | stepsText.push("Drawing circles and ellipses!`nMaybe a moving ball?")
80 | stepsText.push("Drawing rectangles!`nDrawRectangle(x, y, w, h, color, thickness:=1)`nFillRectangle(x, y, w, h, color)`nDrawRoundedRectangle(x, y, w, h, radiusX, radiusY, color, thickness:=1)`nFillRoundedRectangle(x, y, w, h, radiusX, radiusY, color)")
81 | stepsText.push("Drawing rectangles!`nA bouncy block!")
82 | stepsText.push("Drawing images!`nDrawImage(image,dstX,dstY,dstW:=0,dstH:=0,srcX:=0,srcY:=0,srcW:=0,srcH:=0,alpha:=1,drawCentered:=0,rotation:=0)")
83 | stepsText.push("Drawing text!`nDrawText(text,x,y,size:=18,color:=0xFF000000,fontName:=`"Arial`",extraOptions:=`"`")")
84 | stepsText.push("That's all folks!")
85 |
86 | overlay.GetImageDimensions("stickman.png",&stickW,&stickH)
87 |
88 | trails := []
89 | trailColor := 0xFF00FF00
90 | lastX := -1
91 | lastY := -1
92 |
93 | OnMessage(0x201, WindowMove)
94 | moving := false
95 | SetTimer(draw,10)
96 |
97 | f9::Reload()
98 | esc::ExitApp()
99 |
100 | #HotIf WinActive("ahk_id " overlay.hwnd)
101 | left::
102 | {
103 | global
104 | if (step > 1) {
105 | step--
106 | checkStep()
107 | }
108 | return
109 | }
110 |
111 | right::
112 | {
113 | global
114 | if (step < stepsText.Length) {
115 | step++
116 | checkStep()
117 | }
118 | return
119 | }
120 |
121 | wheeldown::
122 | {
123 | global
124 | opacity := (opacity-10 < 1 ? 1 : opacity-10)
125 | return
126 | }
127 |
128 | wheelup::
129 | {
130 | global
131 | opacity := (opacity+10 > 255 ? 255 : opacity+10)
132 | return
133 | }
134 |
135 | #HotIf
136 |
137 | return
138 |
139 |
140 | draw(){
141 | global
142 | if (moving) {
143 | PostMessage(0xA1, 2, , , "ahk_id " overlay.hwnd)
144 | while(GetKeyState("lbutton","p")) {
145 | Sleep(100)
146 | }
147 | moving := false
148 | lastX := lastY := -1
149 | }
150 | if (overlay.BeginDraw()) {
151 |
152 | ;draw background
153 | overlay.FillRoundedRectangle(0,0,overlay.width,overlay.height,55,55,(opacity<<24))
154 | overlay.DrawRoundedRectangle(0,0,overlay.width,overlay.height,55,55,0xFFFFFFFF,2)
155 |
156 | ;draw examples per step
157 | if (step = 1) {
158 |
159 | overlay.DrawText("Use the left and right arrows to navigate between pages`n`nScrollwheel adjusts window opacity",0,height*0.5,42,0xFF99FF8B,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
160 |
161 | } else if (step = 2) {
162 |
163 | overlay.DrawText("Thin white line",width*0.11,height*0.2,18,0xFFFFFF00)
164 | overlay.DrawLine(width*0.1,height*0.2,width*0.1,height*0.9,0xFFFFFFFF)
165 |
166 | overlay.DrawText("Now green",width*0.26,height*0.2,18,0xFFFFFF00)
167 | overlay.DrawLine(width*0.25,height*0.2,width*0.25,height*0.9,0xFF00FF00)
168 |
169 | overlay.DrawText("Now thick",width*0.41,height*0.2,18,0xFFFFFF00)
170 | overlay.DrawLine(width*0.4,height*0.2,width*0.4,height*0.9,0xFF00FF00,15)
171 |
172 | overlay.DrawText("Now rounded",width*0.56,height*0.2,18,0xFFFFFF00)
173 | overlay.DrawLine(width*0.55,height*0.2,width*0.55,height*0.9,0xFF00FF00,15,1)
174 |
175 | overlay.DrawText("And a thicker line behind`ncan create a border!",width*0.71,height*0.2,18,0xFFFFFF00)
176 | overlay.DrawLine(width*0.7,height*0.2,width*0.7,height*0.9,0xFFFFFFFF,21,1)
177 | overlay.DrawLine(width*0.7,height*0.2,width*0.7,height*0.9,0xFF000000,19,1)
178 | overlay.DrawLine(width*0.7,height*0.2,width*0.7,height*0.9,0xFF00FF00,15,1)
179 |
180 | } else if (step = 3) {
181 |
182 | rainDir += rainInc * random(1,10)
183 | if (rainDir > 2.3) {
184 | rainInc := -0.001
185 | rainDir := 2.3
186 | } else if (rainDir < 0.7) {
187 | rainDir := 0.7
188 | rainInc := 0.001
189 | }
190 | if (objs.Length < 500)
191 | Loop 1
192 | objs.push(rain(-500,overlay.width+500,-100,0,(random(200,255)<<24)+(random(95,230)<<16)+(random(200,250)<<8)+random(222,255),overlay.height))
193 | for k,v in objs
194 | v.draw(overlay,rainDir)
195 |
196 | } else if (step = 4) {
197 |
198 | overlay.DrawText("A red circle",width*0.18,height*0.45,18,0xFFFFFF00)
199 | overlay.FillCircle(width*0.2,height*0.5,10,0xFFFF0000)
200 |
201 | overlay.DrawText("A red ellipse",width*0.23,height*0.50,18,0xFFFFFF00)
202 | overlay.FillEllipse(width*0.25,height*0.55,30,10,0xFFFF0000)
203 |
204 | overlay.DrawText("A green circle outline",width*0.38,height*0.45,18,0xFFFFFF00)
205 | overlay.DrawCircle(width*0.4,height*0.5,10,0xFF00FF00)
206 |
207 | overlay.DrawText("A green ellipse outline",width*0.43,height*0.50,18,0xFFFFFF00)
208 | overlay.DrawEllipse(width*0.45,height*0.55,30,10,0xFF00FF00)
209 |
210 | overlay.DrawText("Both!",width*0.58,height*0.45,18,0xFFFFFF00)
211 | overlay.FillCircle(width*0.6,height*0.5,10,0xFFFF0000)
212 | overlay.DrawCircle(width*0.6,height*0.5,10,0xFF00FF00)
213 |
214 | overlay.DrawText("Both with thickness!",width*0.63,height*0.50,18,0xFFFFFF00)
215 | overlay.FillEllipse(width*0.65,height*0.55,30,10,0xFFFF0000)
216 | overlay.DrawEllipse(width*0.65,height*0.55,30,10,0xFF00FF00,3)
217 |
218 |
219 | } else if (step = 5) {
220 | ballX += ballInc
221 | if (ballX > width*0.8) {
222 | ballInc := -ballInc
223 | ballX := width*0.8
224 | } else if (ballX < width*0.2) {
225 | ballInc := -ballInc
226 | ballX := width*0.2
227 | }
228 | overlay.FillEllipse(width*0.5,height*0.62,width*0.5,height*0.1,0xFF777777)
229 | overlay.DrawEllipse(width*0.5,height*0.62,width*0.5,height*0.1,0xFFFFFFFF,2)
230 |
231 | overlay.FillEllipse(ballX,ballY+30,30,15,0x44000000)
232 | overlay.FillEllipse(ballX,ballY+30,38,15,0x44000000)
233 | overlay.FillEllipse(ballX,ballY+30,45,15,0x44000000)
234 |
235 | overlay.FillCircle(ballX,ballY,30,0xFFFF0000)
236 | overlay.FillEllipse(ballX,ballY-20,20,10,0x99FFFFFF)
237 | overlay.DrawCircle(ballX,ballY,30,0xFF000000)
238 |
239 | } else if (step = 6) {
240 |
241 | overlay.DrawText("A red outline",width*0.09,height*0.3,18,0xFFFFFFFF)
242 | overlay.DrawRectangle(width*0.1,height*0.35,width*0.05,height*0.5,0xFFFF4D4D)
243 |
244 | overlay.DrawText("blue",width*0.24,height*0.3,18,0xFFFFFFFF)
245 | overlay.FillRectangle(width*0.25,height*0.35,width*0.05,height*0.5,0xFF38C8BF)
246 |
247 | overlay.DrawText("Together",width*0.39,height*0.3,18,0xFFFFFFFF)
248 | overlay.FillRectangle(width*0.4,height*0.35,width*0.05,height*0.5,0xFF38C8BF)
249 | overlay.DrawRectangle(width*0.4,height*0.35,width*0.05,height*0.5,0xFFFF4D4D,2)
250 |
251 | overlay.DrawText("Now rounded",width*0.54,height*0.3,18,0xFFFFFFFF)
252 | overlay.FillRoundedRectangle(width*0.55,height*0.35,width*0.05,height*0.5,30,30,0xFF38C8BF)
253 | overlay.DrawRoundedRectangle(width*0.55,height*0.35,width*0.05,height*0.5,30,30,0xFFFF4D4D,2)
254 |
255 | overlay.DrawText("Now thick",width*0.69,height*0.3,18,0xFFFFFFFF)
256 | overlay.FillRoundedRectangle(width*0.7,height*0.35,width*0.05,height*0.5,30,30,0xFF38C8BF)
257 | overlay.DrawRoundedRectangle(width*0.7,height*0.35,width*0.05,height*0.5,30,30,0xFFFF4D4D,6)
258 |
259 |
260 | } else if (step = 7) {
261 |
262 | if (bouncing > 0) {
263 | bouncing += blockDir * 10
264 | if (bouncing > 150) {
265 | blockDir := -blockDir
266 | bouncing := 150
267 | }
268 | bh := bouncing/2
269 | overlay.FillRoundedRectangle(blockX-bh,blockY+bh,150+bh*2,150-(bouncing/2),bouncing/2,bouncing/14,0xFF0DC8C0)
270 | overlay.DrawRoundedRectangle(blockX-bh,blockY+bh,150+bh*2,150-(bouncing/2),bouncing/2,bouncing/14,0xFF00FFF4)
271 | ;overlay.FillRoundedRectangle(blockX,blockY+(bouncing/2),150,150-(bouncing/2),bouncing/2,bouncing/4,0xFF0DC8C0)
272 | ;overlay.DrawRoundedRectangle(blockX,blockY+(bouncing/2),150,150-(bouncing/2),bouncing/2,bouncing/4,0xFF00FFF4)
273 | } else {
274 | blockY += blockDir * 10
275 | if (blockY < blockMin) {
276 | blockY := blockMin
277 | blockDir := 1
278 | } else if (blockY > blockMax) {
279 | bouncing := 1
280 | }
281 | overlay.FillRectangle(blockX,blockY,150,150,0xFF0DC8C0)
282 | overlay.DrawRectangle(blockX,blockY,150,150,0xFF00FFF4)
283 | }
284 |
285 | } else if (step = 8) {
286 |
287 | overlay.DrawText("Draw basic tile sprite",width*0.1,height*0.25,18,0xFFFFFFFF)
288 | overlay.FillRectangle(width*0.1,height*0.3,stickW,stickH,0x99FFFFFF)
289 | overlay.DrawImage("stickman.png",width*0.1,height*0.3)
290 |
291 | overlay.DrawText("Increase the size",width*0.3,height*0.25,18,0xFFFFFFFF)
292 | overlay.FillRectangle(width*0.3,height*0.3,128*4,128,0x99FFFFFF)
293 | overlay.DrawImage("stickman.png",width*0.3,height*0.3,128*4,128)
294 |
295 | overlay.DrawText("Now just 1 frame",width*0.1,height*0.45,18,0xFFFFFFFF)
296 | overlay.FillRectangle(width*0.1,height*0.5,128,128,0x99FFFFFF)
297 | overlay.DrawImage("stickman.png",width*0.1,height*0.5,128,128,0,0,32,stickH)
298 |
299 | stickIndex--
300 | if (stickIndex = 0) {
301 | stickIndex := stickSpeed
302 | stickFrame++
303 | if (stickFrame = 4)
304 | stickFrame := 0
305 | }
306 | stickRot+=1
307 | if (stickRot > 360)
308 | stickRot := 0
309 |
310 | overlay.DrawText("Now animate the frames",width*0.3,height*0.55,18,0xFFFFFFFF)
311 | overlay.FillRectangle(width*0.3,height*0.6,128,128,0x99FFFFFF)
312 | overlay.DrawImage("stickman.png",width*0.3,height*0.6,128,128,stickFrame*32,0,32,stickH)
313 |
314 | overlay.DrawText("Now rotating",width*0.5,height*0.60,18,0xFFFFFFFF)
315 | overlay.FillRectangle(width*0.5,height*0.65,128,128,0x99FFFFFF)
316 | overlay.DrawImage("stickman.png",width*0.5,height*0.65,128,128,stickFrame*32,0,32,stickH,1,0,stickRot)
317 |
318 | } else if (step = 9) {
319 |
320 | overlay.FillRectangle(width*0.1,height*0.3,width*0.3,height*0.3,0xFF999999)
321 | overlay.DrawText("Font: Arial, Size: 18",width*0.1,height*0.3,18,0xFFFFFFFF,"Arial")
322 | overlay.DrawText("Now Font = Courier",width*0.1,height*0.33,18,0xFFFFFFFF,"Courier")
323 | overlay.DrawText("Now aligned on the right",width*0.1,height*0.36,18,0xFFFFFFFF,"Courier","aRight w" width*0.3 " h" height*0.3)
324 | overlay.DrawText("Now aligned center",width*0.1,height*0.39,18,0xFFFFFFFF,"Courier","aCenter w" width*0.3 " h" height*0.3)
325 | overlay.DrawText("Now red",width*0.1,height*0.42,18,0xFFFF0000,"Courier","aCenter w" width*0.3 " h" height*0.3)
326 | overlay.DrawText("Now with a dropshadow",width*0.1,height*0.45,18,0xFFFF2D2D,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width*0.3 " h" height*0.3)
327 | overlay.DrawText("Now BIG and GREEN",width*0.1,height*0.52,32,0xFF46FF2D,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width*0.3 " h" height*0.3)
328 |
329 | } else if (step = 10) {
330 |
331 | overlay.DrawText("Check out my github for my latest projects",0,height*0.2,56,0xFF99FF8B,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
332 | overlay.DrawText("github.com/Spawnova",0,height*0.3,64,0xFF46FF2D,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
333 | overlay.DrawText("I plan to keep all my projects up to date and to add new features and functions!`n`nPlease let me know if you run into any issues by creating`nan issue/discussion on the github page`nI check there daily and always have time to answer questions and attempt to fix problems!",0,height*0.43,32,0xFFFF8B8B,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
334 | overlay.DrawText("Thank you for using my class and have fun out there!",0,height*0.8,42,0xFF5BFFF5,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
335 | }
336 |
337 | if (overlay.GetMousePos(&mx,&my)) {
338 | if (lastX != -1 and (lastX != mx or lastY != my)) {
339 | trails.push(mouseTrail(lastX,lastY,mx,my,trailColor))
340 | }
341 | lastX := mx
342 | lastY := my
343 | } else {
344 | lastX := lastY := -1
345 | }
346 |
347 | i := 1
348 | }
349 | while(i < trails.Length) {
350 | if (!trails[i].draw(overlay)) {
351 | trails.removeat(i)
352 | } else {
353 | i++
354 | }
355 | }
356 |
357 | ;draw text elements
358 | overlay.DrawText(stepsText[step],50,50,24,0xFFFFFFFF,"Arial","dsFF000000")
359 | overlay.DrawText("Press ESC to close",overlay.width-400,50,32,0xFFCC0000,"Arial","aRight dsFF222222 w" 400-50)
360 | overlay.DrawText("Page " step " of " stepsText.Length,50,overlay.height-74,24,0xFFFFFFFF,"Arial","dsFF000000")
361 | overlay.EndDraw()
362 | return
363 | }
364 |
365 | WindowMove(*) {
366 | global moving
367 | moving := 1
368 | }
369 |
370 |
371 | checkStep(){
372 | global
373 | trailColor := 0xFF000000 + (random(128,255)<<16) + (random(128,255)<<8) + random(128,255)
374 | objs := []
375 | if (step = 3) {
376 | trailColor := 0xFFFFFF00
377 | rainDir := 1.6
378 | rainInc := 0.001
379 | } else if (step = 5) {
380 | ballX := width*0.2
381 | ballY := height*0.6
382 | ballInc := 5
383 | } else if (Step = 7) {
384 | blockX := width*0.45
385 | blockY := height*0.25
386 | blockMin := blockY
387 | blockMax := height*0.8
388 | blockDir := 1
389 | bouncing := 0
390 | } else if (step = 8) {
391 | stickFrame := 0
392 | stickSpeed := 10
393 | stickIndex := stickSpeed
394 | stickRot := 0
395 | }
396 | return
397 | }
398 |
--------------------------------------------------------------------------------
/AHK V2/game_example_by_dmtr99/Raptor_V2.ahk:
--------------------------------------------------------------------------------
1 |
2 | #Requires AutoHotkey v2.0
3 | #SingleInstance force
4 | #Include "shinsoverlayclass.ahk"
5 |
6 | A_TickCount_Start := A_TickCount
7 | TickCount_Pause := 0
8 | TickCount_Pause_Start := 0
9 | game_status := 1
10 | x := floor(a_screenwidth * 0.2)
11 | y := floor(a_screenheight * 0.2)
12 | width := floor(a_screenwidth * 0.6)
13 | height := floor(a_screenheight * 0.6)
14 |
15 | MyGui := Gui( ,"Raptor_V2")
16 |
17 | MyGui.AddButton(,"test")
18 | MyGui.BackColor := "5d691e"
19 | MyGui.Show("w" width " h" height " x" x " y" y)
20 |
21 | ; overlay := ShinsOverlayClass(x,y,width,height,0,0,0)
22 | overlay := ShinsOverlayClass("Raptor_V2")
23 |
24 | opacity := 0x99
25 |
26 | step := 1
27 | stepsText := []
28 | stepsText.push("Example of a raptor game!`nPress [Alt] to shoot.`nPress [Space] to pause.")
29 | stepsText.push("Drawing Lines!`nDrawLine(x1, y1, x2, y2, color, thickness:=1, rounded:=0)`n`n")
30 |
31 | aBullets := []
32 | aEnemies := []
33 | aEBullets := []
34 | aExplosions := []
35 | aRewards := []
36 | aColors := {}
37 | aColors.shadow := 0x30000000
38 |
39 | plane := {x: Width/2, y: overlay.height-100, HP: 100, maxHP: 100, score: 0, firerate:0.3, lastfired:0, width: 40, vx:0, vy:0, ax:0,ay:0,ly:45}
40 |
41 | plane.draw := (plane,*)=> (
42 | (Shadowx := (width/2-plane.x)/10),
43 | (Shadowy := (height/2-plane.y)/10),
44 | overlay.FillPolygon(TransformCoord([[0,0],[5,10],[5,20],[20,35],[15,40],[10,40],[10,45],[5,45],[5,40],[-5,40],[-5,45],[-10,45],[-10,40],[-15,40],[-20,35],[-5,20],[-5,10]],(1-0.4*Abs(plane.vx)/10)*.8),color:= aColors.shadow ,plane.x+Shadowx,plane.y+Shadowy)
45 | overlay.FillPolygon(TransformCoord([[0,0],[5,10],[5,20],[20,35],[15,40],[10,40],[10,45],[5,45],[5,40],[-5,40],[-5,45],[-10,45],[-10,40],[-15,40],[-20,35],[-5,20],[-5,10]],(1-0.4*Abs(plane.vx)/10)),color:=0x808080,plane.x,plane.y)
46 |
47 | )
48 |
49 | mLevel1 := Map()
50 | mLevel1[1.0] := {xpos:0.8}
51 | mLevel1[2.0] := {xpos:0.6}
52 | mLevel1[3.0] := {xpos:0.4, type:2}
53 | mLevel1[4.0] := {xpos:0.2, type:2}
54 | mLevel1[5.0] := {xpos:0.4, type:2}
55 |
56 |
57 | loop 500 {
58 | mLevel1[A_index*1.5+5.0] := {xpos:Random(0.2,0.8), type:Random(1,2)}
59 | }
60 |
61 | ; OnMessage(0x201, WindowMove)
62 |
63 | SetTimer(draw,10)
64 |
65 | f9::Reload()
66 | esc::ExitApp()
67 |
68 | ~Space::
69 | {
70 | global game_status, TickCount_Pause, TickCount_Pause_Start, A_TickCount_Start
71 | game_status := !game_status
72 | if (!game_status){
73 | ; pause the game
74 | SetTimer(draw,0)
75 | TickCount_Pause_Start := A_TickCount
76 | }else{
77 | SetTimer(draw,10)
78 | A_TickCount_Start := A_TickCount_Start + A_TickCount-TickCount_Pause_Start
79 | }
80 |
81 | }
82 |
83 | return
84 |
85 |
86 | draw(){
87 | global
88 |
89 | if (overlay.BeginDraw()) {
90 |
91 | ;draw background
92 | ; overlay.FillRoundedRectangle(0,0,overlay.width,overlay.height,55,55,(opacity<<24))
93 | ; overlay.DrawRoundedRectangle(0,0,overlay.width,overlay.height,55,55,0xFFFFFFFF,2)
94 | ; overlay.FillRectangle(0,0,overlay.width,overlay.height,(opacity<<24))
95 | ; overlay.DrawRectangle(0,0,overlay.width,overlay.height,0xFFFFFFFF,2)
96 |
97 | ;draw examples per step
98 | if (step = 1) {
99 |
100 | A_TickCount_script := Round((A_TickCount-A_TickCount_Start)/1000,1)
101 |
102 | overlay.GetMousePos(&mx,&my)
103 |
104 | overlay.FillRectangle(overlay.width-20,0,20,overlay.height,0xFF000000)
105 | loop 100
106 | {
107 | if (A_Index > plane.hp){
108 | break
109 | }
110 | ExplosionOpacity := Format("{:X}", Round(255*(0.5+A_Index/200)))
111 | overlay.FillRectangle(overlay.width-18,overlay.height*(100-A_Index-1)/100-4,16,4,"0x" ExplosionOpacity "FF0000")
112 | }
113 | ; Draw plane
114 | ; plane.x := mx
115 | ; plane.y := my
116 |
117 | if (GetKeyState("Left")){
118 | plane.ax := -1
119 | } else if (GetKeyState("Right")){
120 | plane.ax := 1
121 | } else {
122 | if (plane.vx > 0){
123 | plane.ax := -1
124 | } else if (plane.vx < 0){
125 | plane.ax := 1
126 | } else {
127 | plane.ax := 0
128 | }
129 | }
130 |
131 | if (GetKeyState("Up")){
132 | plane.ay := -1
133 | } else if (GetKeyState("Down")){
134 | plane.ay := 1
135 | } else {
136 | if (plane.vy > 0){
137 | plane.ay := -1
138 | } else if (plane.vy < 0){
139 | plane.ay := 1
140 | } else {
141 | plane.ay := 0
142 | }
143 | }
144 |
145 |
146 | plane.vx += plane.ax
147 | plane.vx := max(min(plane.vx,10),-10)
148 | plane.vy += plane.ay
149 | plane.vy := max(min(plane.vy,10),-10)
150 |
151 | plane.x += plane.vx
152 | plane.y += plane.vy
153 | plane.x := max(min(plane.x,width-plane.width/2),plane.width/2)
154 | plane.y := max(min(plane.y,Height-plane.ly),plane.ly)
155 |
156 |
157 |
158 | if (GetKeyState("Alt") and (plane.lastfired + plane.firerate <= A_TickCount_script)){
159 | level := (plane.score < 500) ? 1 : (plane.score < 1000) ? 2 : 3
160 | ShootBullet(level)
161 | plane.lastfired := A_TickCount_script
162 | }
163 |
164 | if(mLevel1.Has(A_TickCount_script+0)){
165 | Enemy := mLevel1[A_TickCount_script+0]
166 | CreateEnemy(20+Enemy.xpos*(overlay.width-40),(Enemy.HasProp("type") ? Enemy.type : 1))
167 | mLevel1.Delete(A_TickCount_script)
168 | }
169 |
170 | overlay.DrawText("$" plane.score,0,height*0.03,20,0xFF99FF8B,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
171 |
172 | overlay.DrawText("HP: " plane.HP "`nTime:" A_TickCount_script "`n [" GetKeyState("Up","P") "]`n[" GetKeyState("Left","P") "] [" GetKeyState("Down","P") "] [" GetKeyState("Right","P") "]",0,height*0.5,20,0xFF99FF8B,"Courier","dsFF000000 dsx1 dsy1 w" width " h" height)
173 | if (plane.HP <=0){
174 | overlay.DrawText("GAME OVER" ,0,height*0.5,60,0xFFFF0000,"Courier","aCenter dsFF000000 dsx1 dsy1 w" width " h" height)
175 | }
176 |
177 | for Index_bullet, bullet in aBullets {
178 | bullet.y += bullet.vy
179 |
180 | (bullet.HasProp("vx")) ? (bullet.x += bullet.vx) : ""
181 |
182 | if (bullet.y < 0) {
183 | aBullets.RemoveAt(Index_bullet)
184 | } else {
185 | bullet.draw(bullet)
186 | }
187 | }
188 | for Index_Rewards, Reward in aRewards {
189 | Reward.y += Reward.vy + Random(-0.5, 0.5)
190 | Reward.x += Random(-0.5, 0.5)
191 |
192 | if (Abs(Reward.y-(plane.y+plane.ly/2)) < plane.ly/2) and (Abs(Reward.x-Plane.x) < Plane.width/2){
193 | Reward.OnHit()
194 | aRewards.RemoveAt(Index_Rewards)
195 | }
196 | else if (Reward.y < 0) {
197 | aRewards.RemoveAt(Index_Rewards)
198 | } else {
199 |
200 | Reward.Draw(Reward)
201 | }
202 | }
203 |
204 | for Index_EBullets, EBullet in aEBullets {
205 | EBullet.y += EBullet.vy
206 | if (Abs(EBullet.y-(plane.y+plane.ly/2)) < plane.ly/2) and (Abs(EBullet.x-Plane.x) < Plane.width/2){
207 | plane.hp -= EBullet.power
208 | aExplosions.Push({x: EBullet.x, y: EBullet.y, radius: 1, vr: 1, maxradius: 30})
209 | aEBullets.RemoveAt(Index_EBullets)
210 | }
211 | else if (EBullet.y < 0) {
212 | aEBullets.RemoveAt(Index_EBullets)
213 | } else {
214 | overlay.FillCircle(EBullet.x,EBullet.y,EBullet.radius,0xFF99FF8B)
215 | }
216 | }
217 |
218 | for Index_Enemy, Enemy in aEnemies {
219 | Enemy.y += Enemy.vy + Random(-0.5, 0.5)
220 | Enemy.x += Enemy.vx + Random(-0.5, 0.5)
221 |
222 | ; Check if the enemy is hit by bullets
223 | for Index_bullet, bullet in aBullets {
224 | if (Abs(bullet.y-Enemy.y) < 5) and (Abs(bullet.x-Enemy.x) < Enemy.width/2) {
225 |
226 | aExplosions.Push({x: bullet.x, y: bullet.y, radius: 1, vr: 1, maxradius: 30, vy: Enemy.vy})
227 |
228 | aBullets.RemoveAt(Index_bullet)
229 | SoundPlay "*2"
230 | Enemy.HP -= bullet.power
231 | If (Enemy.HP <= 0 ){
232 | plane.score += Enemy.points
233 |
234 | Rnumber := Random(0,1)
235 | if (Rnumber <0.3){
236 | aRewards.Push({x: Enemy.x, y: Enemy.y, draw: (Reward,*)=>(overlay.DrawText("$",Reward.x-5,Reward.y,12,0xFF99FF8B,"Courier","dsFF000000 dsx1 dsy1 w" width " h" height)), vy: 1, OnHit: (*)=>(SoundPlay("*-1"), plane.Score += 100)})
237 | } else if (Rnumber > 0.6){
238 | aRewards.Push({x: Enemy.x, y: Enemy.y, draw: (Reward,*)=>(overlay.DrawText("♥",Reward.x-5,Reward.y,12,0x99FF0000,"Courier","dsFF000000 dsx1 dsy1 w" width " h" height)), vy: 1, OnHit: (*)=>(SoundPlay("*-1"), plane.HP := Min(plane.HP+10, plane.maxHP))})
239 | }
240 |
241 | aEnemies.RemoveAt(Index_Enemy)
242 | break
243 | }
244 | }
245 | }
246 |
247 | if (Abs(Enemy.y-(plane.y+plane.ly/2)) < plane.ly/2) and (Abs(plane.x-Enemy.x) < plane.width/2){
248 | Enemy.OnCollision()
249 | aExplosions.Push({x: Enemy.x, y: Enemy.y, radius: 1, vr: 1, maxradius: 40, vy: Enemy.vy})
250 | aEnemies.RemoveAt(Index_Enemy)
251 | } else if (Enemy.y > overlay.height) {
252 | aEnemies.RemoveAt(Index_Enemy)
253 | } else {
254 | Enemy.Draw(Enemy)
255 | }
256 |
257 | if ((Enemy.lastfired + Enemy.firerate <= A_TickCount_script)){
258 | Enemy.fire(Enemy)
259 | Enemy.lastfired := A_TickCount_script
260 | }
261 |
262 | }
263 |
264 | for Index_Explosion, Explosion in aExplosions {
265 | (Explosion.HasProp("vy")) ? Explosion.y += Explosion.vy : ""
266 | Explosion.radius += Explosion.vr
267 | if (Explosion.radius >= Explosion.maxradius) {
268 | aExplosions.RemoveAt(Index_Explosion)
269 | } else {
270 | ExplosionOpacity := Format("{:X}", Round(255*(1-Explosion.radius/Explosion.maxradius)))
271 | overlay.FillCircle(Explosion.x,Explosion.y, Explosion.radius, "0x" ExplosionOpacity "99FF8B")
272 | }
273 | }
274 |
275 | plane.draw()
276 |
277 | }
278 |
279 | }
280 |
281 | ;draw text elements
282 | overlay.DrawText(stepsText[step],50,50,24,0xFFFFFFFF,"Arial","dsFF000000")
283 | overlay.DrawText("Press ESC to close",overlay.width-400,50,32,0xFFCC0000,"Arial","aRight dsFF222222 w" 400-50)
284 | overlay.EndDraw()
285 | return
286 | }
287 |
288 |
289 | ShootBullet(Level := 1){
290 | global aBullets
291 |
292 | if (Level=1){
293 | aBullets.Push({x: plane.x, y: plane.y, power: 40, vy: -2, draw: (Bullet,*)=>(overlay.DrawLine(bullet.x,bullet.y,bullet.x,bullet.y+5,0xFF99FF8B,2))})
294 | } else if (Level = 2){
295 | aBullets.Push({x: plane.x-10, y: plane.y+20, power: 40, vy: -2, draw: (Bullet,*)=>(overlay.DrawLine(bullet.x,bullet.y,bullet.x,bullet.y+5,0xFF99FF8B,2))})
296 | aBullets.Push({x: plane.x+10, y: plane.y+20, power: 40, vy: -2, draw: (Bullet,*)=>(overlay.DrawLine(bullet.x,bullet.y,bullet.x,bullet.y+5,0xFF99FF8B,2))})
297 | } else if (Level = 3){
298 | aBullets.Push({x: plane.x-10, y: plane.y+20, power: 60, vy: -3, draw: (Bullet,*)=>(overlay.DrawLine(bullet.x,bullet.y,bullet.x,bullet.y+5,0xFF8c7fe3,2))})
299 | aBullets.Push({x: plane.x+10, y: plane.y+20, power: 60, vy: -3, draw: (Bullet,*)=>(overlay.DrawLine(bullet.x,bullet.y,bullet.x,bullet.y+5,0xFF8c7fe3,2))})
300 | aBullets.Push({x: plane.x-10, y: plane.y+20, power: 60, vx: -1, vy: -2, draw: (Bullet,*)=>(overlay.DrawLine(bullet.x,bullet.y,bullet.x,bullet.y+5,0xFF8c7fe3,2))})
301 | aBullets.Push({x: plane.x+10, y: plane.y+20, power: 60, vx: 1, vy: -2, draw: (Bullet,*)=>(overlay.DrawLine(bullet.x,bullet.y,bullet.x,bullet.y+5,0xFF8c7fe3,2))})
302 | }
303 | }
304 |
305 | CreateEnemy(Xpos := Random(20,overlay.width-20), type :=1){
306 | global aEnemies
307 | if (Type=1){
308 | Enemy := {x: Xpos, y: -100, HP: 100, vy: 2, vx:0, width: 20, points: 100, firerate: 1.5, lastfired: 0, bulletpower: 10}
309 | Enemy.draw := (Enemy,*)=>(
310 | (Shadowx := (width/2-Enemy.x)/5),
311 | (Shadowy := (height/2-Enemy.y)/15),
312 | overlay.FillPolygon(TransformCoord([[0,0],[5,-5],[5,-10],[10,-15],[10,-20],[5,-15],[-5,-15],[-10,-20],[-10,-15],[-5,-10],[-5,-5]],0.8),color:= aColors.shadow ,Enemy.x+Shadowx,Enemy.y+Shadowy),
313 | overlay.FillPolygon([[0,0],[5,-5],[5,-10],[10,-15],[10,-20],[5,-15],[-5,-15],[-10,-20],[-10,-15],[-5,-10],[-5,-5]],color:=0x808080,Enemy.x,Enemy.y)
314 | )
315 | Enemy.fire := (Enemy,*)=>(aEBullets.Push({x: Enemy.x, y: Enemy.y, radius: 2, vy: Enemy.vy+1, power: Enemy.bulletpower}))
316 | Enemy.OnCollision := (Enemy,*)=>(plane.HP -= Enemy.HP/10)
317 | } else {
318 | Enemy := {x: Xpos, y: -100, HP: 100, vy: 2, vx:0, width: 30, points: 100, firerate: 2, lastfired: 0, bulletpower: 10}
319 | Enemy.draw := (Enemy,*)=>(
320 | (Shadowx := (width/2-Enemy.x)/5),
321 | (Shadowy := (height/2-Enemy.y)/5),
322 | overlay.FillPolygon(TransformCoord([[0,0],[5,0],[10,-5],[15,-15],[15,-20],[10,-20],[10,-25],[5,-25],[5,-20],[-5,-20],[-5,-25],[-10,-25],[-10,-20],[-15,-20],[-15,-15],[-10,-5],[-5,0]],0.8),color:= aColors.shadow ,Enemy.x+Shadowx,Enemy.y+Shadowy),
323 | overlay.FillPolygon([[0,0],[5,0],[10,-5],[15,-15],[15,-20],[10,-20],[10,-25],[5,-25],[5,-20],[-5,-20],[-5,-25],[-10,-25],[-10,-20],[-15,-20],[-15,-15],[-10,-5],[-5,0]],color:=0x808080,Enemy.x,Enemy.y)
324 | )
325 | Enemy.fire := (Enemy,*)=>(aEBullets.Push({x: Enemy.x-5, y: Enemy.y-5, radius: 2, vy: Enemy.vy+1, power: Enemy.bulletpower}), aEBullets.Push({x: Enemy.x+5, y: Enemy.y-5, radius: 2, vy: Enemy.vy+1, power: Enemy.bulletpower}))
326 | Enemy.OnCollision := (Enemy,*)=>(plane.HP -= Enemy.HP/10)
327 | }
328 |
329 | aEnemies.Push(Enemy)
330 | }
331 |
332 | TransformCoord(aCoord,varx:=1, vary:=1){
333 | aCoord2:= []
334 | for index, Coord in aCoord
335 | {
336 | aCoord2.Push([Coord[1]*varx,Coord[2]*vary])
337 | }
338 | return aCoord2
339 | }
340 |
--------------------------------------------------------------------------------
/AHK V2/ShinsOverlayClass.ahk:
--------------------------------------------------------------------------------
1 | ;Direct2d overlay class by Spawnova (5/27/2022)
2 | ;https://github.com/Spawnova/ShinsOverlayClass
3 | ;
4 | ;I'm not a professional programmer, I do this for fun, if it doesn't work for you I can try and help
5 | ;but I can't promise I will be able to solve the issue
6 | ;
7 | ;Special thanks to teadrinker for helping me understand some 64bit param structures! -> https://www.autohotkey.com/boards/viewtopic.php?f=76&t=105420
8 |
9 | #Requires AutoHotkey v2+
10 |
11 | class ShinsOverlayClass {
12 |
13 | ;x_orTitle : x pos of overlay OR title of window to attach to
14 | ;y_orClient : y pos of overlay OR attach to client instead of window (default window)
15 | ;width_orForeground : width of overlay OR overlay is only drawn when the attached window is in the foreground (default 1)
16 | ;height : height of overlay
17 | ;alwaysOnTop : If enabled, the window will always appear over other windows
18 | ;vsync : If enabled vsync will cause the overlay to update no more than the monitors refresh rate, useful when looping without sleeps
19 | ;clickThrough : If enabled, mouse clicks will pass through the window onto the window beneath
20 | ;taskBarIcon : If enabled, the window will have a taskbar icon
21 | ;guiID : name of the ahk gui id for the overlay window, if 0 defaults to "ShinsOverlayClass_TICKCOUNT"
22 | ;
23 | ;notes : if planning to attach to window these parameters can all be left blank
24 |
25 | __New(x_orTitle:=0,y_orClient:=1,width_orForeground:=1,height:=0,alwaysOnTop:=1,vsync:=0,clickThrough:=1,taskBarIcon:=0,guiID:=0) {
26 |
27 |
28 | ;[input variables] you can change these to affect the way the script behaves
29 |
30 | this.interpolationMode := 0 ;0 = nearestNeighbor, 1 = linear ;affects DrawImage() scaling
31 | this.data := Map() ;reserved name for general data storage
32 | this.HideOnStateChange := 1 ;hides or shows the overlay when attached windows state changes, change to 0 to turn this behaviour off
33 |
34 |
35 | ;[output variables] you can read these to get extra info, DO NOT MODIFY THESE
36 |
37 | this.x := x_orTitle ;overlay x position OR title of window to attach to
38 | this.y := y_orClient ;overlay y position OR attach to client area
39 | this.width := width_orForeground ;overlay width OR attached overlay only drawn when window is in foreground
40 | this.height := height ;overlay height
41 | this.x2 := (IsNumber(x_orTitle) ? x_orTitle : 0) + width_orForeground
42 | this.y2 := y_orClient+height
43 | this.attachHWND := 0 ;HWND of the attached window, 0 if not attached
44 | this.attachClient := 0 ;1 if using client space, 0 otherwise
45 | this.attachForeground := 0 ;1 if overlay is only drawn when the attached window is the active window; 0 otherwise
46 |
47 | ;Generally with windows there are invisible borders that allow
48 | ;the window to be resized, but it makes the window larger
49 | ;these values should contain the window x, y offset and width, height for actual postion and size
50 | this.realX := 0
51 | this.realY := 0
52 | this.realWidth := 0
53 | this.realHeight := 0
54 | this.realX2 := 0
55 | this.realY2 := 0
56 |
57 |
58 |
59 |
60 |
61 |
62 | ;#############################
63 | ; Setup internal stuff
64 | ;#############################
65 | this.bits := (a_ptrsize == 8)
66 | this.imageCache := Map()
67 | this.fonts := Map()
68 | this.lastPos := 0
69 | this.offX := -(IsNumber(x_orTitle) ? x_orTitle : 0)
70 | this.offY := -y_orClient
71 | this.lastCol := 0
72 | this.drawing := 0
73 | this.guiID := (guiID = 0 ? "ShinsOverlayClass_" a_tickcount : guiID)
74 | this.owned := 0
75 | this.lastSize := 0
76 | this.notifyActive := 0
77 | this.alwaysontop := alwaysontop
78 | pOut := 0
79 |
80 | this._cacheImage := this.mcode("VVdWMfZTg+wMi0QkLA+vRCQoi1QkMMHgAoXAfmSLTCQki1wkIA+26gHIiUQkCGaQD7Z5A4PDBIPBBIn4D7bwD7ZB/g+vxpn3/YkEJA+2Qf0Pr8aZ9/2JRCQED7ZB/A+vxpn3/Q+2FCSIU/wPtlQkBIhT/YhD/on4iEP/OUwkCHWvg8QMifBbXl9dw5CQkJCQ|V1ZTRTHbRItUJEBFD6/BRo0MhQAAAABFhcl+YUGD6QFFD7bSSYnQQcHpAkqNdIoERQ+2WANBD7ZAAkmDwARIg8EEQQ+vw5lB9/qJx0EPtkD9QQ+vw5lB9/pBicFBD7ZA/ECIefxEiEn9QQ+vw0SIWf+ZQff6iEH+TDnGdbNEidhbXl/DkJCQkJCQkJCQkJCQ")
81 |
82 | this.LoadLib("d2d1","dwrite","dwmapi","gdiplus")
83 | gsi := buffer(24,0)
84 | NumPut("uint", 1, gsi, 0)
85 | token := 0
86 | DllCall("gdiplus\GdiplusStartup", "Ptr*", &token, "Ptr", gsi, "Ptr*", 0)
87 | this.gdiplusToken := token
88 |
89 | this._guid("{06152247-6f50-465a-9245-118bfd3b6007}",&clsidFactory)
90 | this._guid("{b859ee5a-d838-4b5b-a2e8-1adc7d93db48}",&clsidwFactory)
91 |
92 | this.gui := Gui("-DPIScale -Caption +E0x80000" (clickthrough ? " +E0x20" : "") (alwaysontop ? " +Alwaysontop" : "") (!taskBarIcon ? " +toolwindow" : ""),this.guiID)
93 |
94 | this.hwnd := hwnd := this.gui.hwnd
95 | DllCall("ShowWindow","Uptr",this.hwnd,"uint",(clickThrough ? 8 : 1))
96 |
97 | this.OnEraseFunc := _SOC_ONERASE.bind(hwnd)
98 | OnMessage(0x14,this.OnEraseFunc)
99 |
100 | this.tBufferPtr := Buffer(4096,0)
101 | this.rect1Ptr := Buffer(64,0)
102 | this.rect2Ptr := Buffer(64,0)
103 | this.rtPtr := Buffer(64,0)
104 | this.hrtPtr := Buffer(64,0)
105 | this.matrixPtr := Buffer(64,0)
106 | this.colPtr := Buffer(64,0)
107 | this.clrPtr := Buffer(64,0)
108 | margins := Buffer(16,0)
109 | NumPut("int",-1,margins,0), NumPut("int",-1,margins,4), NumPut("int",-1,margins,8), NumPut("int",-1,margins,12)
110 | ext := DllCall("dwmapi\DwmExtendFrameIntoClientArea","Uptr",hwnd,"ptr",margins,"uint")
111 | if (ext != 0) {
112 | this.Err("Problem with DwmExtendFrameIntoClientArea","overlay will not function`n`nReloading the script usually fixes this`n`nError: " DllCall("GetLastError","uint") " / " ext)
113 | return
114 | }
115 | DllCall("SetLayeredWindowAttributes","Uptr",hwnd,"Uint",0,"char",255,"uint",2)
116 | if (DllCall("d2d1\D2D1CreateFactory","uint",1,"Ptr",clsidFactory,"uint*",0,"Ptr*",&pOut) != 0) {
117 | this.Err("Problem creating factory","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
118 | return
119 | }
120 | this.factory := pOut
121 | NumPut("float",255,this.tBufferPtr,16)
122 | if (DllCall(this.vTable(this.factory,11),"ptr",this.factory,"ptr",this.tBufferPtr,"ptr",0,"uint",0,"ptr*",&pOut) != 0) {
123 | this.Err("Problem creating stroke","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
124 | return
125 | }
126 | this.stroke := pOut
127 | NumPut("uint",2,this.tBufferPtr,0)
128 | NumPut("uint",2,this.tBufferPtr,4)
129 | NumPut("uint",2,this.tBufferPtr,12)
130 | NumPut("float",255,this.tBufferPtr,16)
131 | if (DllCall(this.vTable(this.factory,11),"ptr",this.factory,"ptr",this.tBufferPtr,"ptr",0,"uint",0,"ptr*",&pOut) != 0) {
132 | this.Err("Problem creating rounded stroke","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
133 | return
134 | }
135 | this.strokeRounded := pOut
136 | NumPut("uint",1,this.rtPtr,8)
137 | NumPut("float",96,this.rtPtr,12)
138 | NumPut("float",96,this.rtPtr,16)
139 | NumPut("Uptr",hwnd,this.hrtPtr,0)
140 | NumPut("uint",width_orForeground,this.hrtPtr,a_ptrsize)
141 | NumPut("uint",height,this.hrtPtr,a_ptrsize+4)
142 | NumPut("uint",(vsync?0:2),this.hrtPtr,a_ptrsize+8)
143 | if (DllCall(this.vTable(this.factory,14),"Ptr",this.factory,"Ptr",this.rtPtr,"ptr",this.hrtPtr,"Ptr*",&pOut) != 0) {
144 | this.Err("Problem creating renderTarget","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
145 | return
146 | }
147 | this.renderTarget := pOut
148 | NumPut("float",1,this.matrixPtr,0)
149 | this.SetIdentity(4)
150 | if (DllCall(this.vTable(this.renderTarget,8),"Ptr",this.renderTarget,"Ptr",this.colPtr,"Ptr",this.matrixPtr,"Ptr*",&pOut) != 0) {
151 | this.Err("Problem creating brush","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
152 | return
153 | }
154 | this.brush := pOut
155 | DllCall(this.vTable(this.renderTarget,32),"Ptr",this.renderTarget,"Uint",1)
156 | if (DllCall("dwrite\DWriteCreateFactory","uint",0,"Ptr",clsidwFactory,"Ptr*",&pOut) != 0) {
157 | this.Err("Problem creating writeFactory","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
158 | return
159 | }
160 | this.wFactory := pOut
161 |
162 | this.InitFuncs()
163 |
164 | if (x_orTitle != 0 and winexist(x_orTitle))
165 | this.AttachToWindow(x_orTitle,y_orClient,width_orForeground)
166 | else
167 | this.SetPosition(x_orTitle,y_orClient)
168 |
169 |
170 | this.Clear()
171 | }
172 |
173 |
174 | ;####################################################################################################################################################################################################################################
175 | ;AttachToWindow
176 | ;
177 | ;title : Title of the window (or other type of identifier such as 'ahk_exe notepad.exe' etc..
178 | ;attachToClientArea : Whether or not to attach the overlay to the client area, window area is used otherwise
179 | ;foreground : Whether or not to only draw the overlay if attached window is active in the foreground, otherwise always draws
180 | ;setOwner : Sets the ownership of the overlay window to the target window
181 | ;
182 | ;return ; Returns 1 if either attached window is active in the foreground or no window is attached; 0 otherwise
183 | ;
184 | ;Notes ; Does not actually 'attach', but rather every BeginDraw() fuction will check to ensure it's
185 | ; updated to the attached windows position/size
186 | ; Could use SetParent but it introduces other issues, I'll explore further later
187 |
188 | AttachToWindow(title,AttachToClientArea:=0,foreground:=1,setOwner:=0) {
189 | if (title = "") {
190 | this.Err("AttachToWindow: Error","Expected title string, but empty variable was supplied!")
191 | return 0
192 | }
193 | if (!this.attachHWND := winexist(title)) {
194 | this.Err("AttachToWindow: Error","Could not find window - " title)
195 | return 0
196 | }
197 | numput("Uptr",this.attachHwnd,this.tbufferptr,0)
198 | this.attachHWND := numget(this.tbufferptr,0,"Ptr")
199 | if (!DllCall("GetWindowRect","Uptr",this.attachHWND,"ptr",this.tBufferPtr)) {
200 | this.Err("AttachToWindow: Error","Problem getting window rect, is window minimized?`n`nError: " DllCall("GetLastError","uint"))
201 | return 0
202 | }
203 | x := NumGet(this.tBufferPtr,0,"int")
204 | y := NumGet(this.tBufferPtr,4,"int")
205 | w := NumGet(this.tBufferPtr,8,"int")-x
206 | h := NumGet(this.tBufferPtr,12,"int")-y
207 | this.attachClient := AttachToClientArea
208 | this.attachForeground := foreground
209 | this.AdjustWindow(&x,&y,&w,&h)
210 |
211 | newSize := Buffer(16,0)
212 | NumPut("uint",this.width := w,newSize,0)
213 | NumPut("uint",this.height := h,newSize,4)
214 | DllCall(this._NRSize,"Ptr",this.renderTarget,"ptr",newsize)
215 | this.SetPosition(x,y,this.width,this.height)
216 | if (setOwner) {
217 | this.alwaysontop := 0
218 | WinSetAlwaysOnTop(0, "ahk_id " this.hwnd)
219 | this.owned := 1
220 | dllcall("SetWindowLongPtr","Uptr",this.hwnd,"int",-8,"Uptr",this.attachHWND)
221 | this.SetPosition(this.x,this.y)
222 | } else {
223 | this.owned := 0
224 | }
225 | }
226 |
227 |
228 | ;####################################################################################################################################################################################################################################
229 | ;BeginDraw
230 | ;
231 | ;return ; Returns 1 if either attached window is active in the foreground or no window is attached; 0 otherwise
232 | ;
233 | ;Notes ; Must always call EndDraw to finish drawing and update the overlay
234 |
235 | BeginDraw() {
236 | local pOut := 0
237 | if (this.attachHWND) {
238 | if (!DllCall("GetWindowRect","Uptr",this.attachHWND,"ptr",this.tBufferPtr) or (this.attachForeground and DllCall("GetForegroundWindow","cdecl Ptr") != this.attachHWND)) {
239 | if (this.drawing) {
240 | this.Clear()
241 | this.drawing := 0
242 | if (this.HideOnStateChange)
243 | this.Display(0)
244 | }
245 | return 0
246 | } else if (!this.drawing) {
247 | if (this.HideOnStateChange)
248 | this.Display(1)
249 | }
250 | x := NumGet(this.tBufferPtr,0,"int")
251 | y := NumGet(this.tBufferPtr,4,"int")
252 | w := NumGet(this.tBufferPtr,8,"int")-x
253 | h := NumGet(this.tBufferPtr,12,"int")-y
254 | if ((w<<16)+h != this.lastSize) {
255 | this.AdjustWindow(&x,&y,&w,&h)
256 | newSize := Buffer(16,0)
257 | NumPut("uint",this.width := w,newSize,0)
258 | NumPut("uint",this.height := h,newSize,4)
259 | DllCall(this._NRSize,"Ptr",this.renderTarget,"ptr",newsize)
260 | this.SetPosition(x,y)
261 | } else if ((x<<16)+y != this.lastPos) {
262 | this.AdjustWindow(&x,&y,&w,&h)
263 | this.SetPosition(x,y)
264 | }
265 | if (!this.drawing and this.alwaysontop) {
266 | WinSetAlwaysOnTop(1,"ahk_id " this.hwnd)
267 | }
268 |
269 | } else {
270 | if (!DllCall("GetWindowRect","Uptr",this.hwnd,"ptr",this.tBufferPtr)) {
271 | if (this.drawing) {
272 | this.Clear()
273 | this.drawing := 0
274 | }
275 | return 0
276 | }
277 | x := NumGet(this.tBufferPtr,0,"int")
278 | y := NumGet(this.tBufferPtr,4,"int")
279 | w := NumGet(this.tBufferPtr,8,"int")-x
280 | h := NumGet(this.tBufferPtr,12,"int")-y
281 | if ((w<<16)+h != this.lastSize) {
282 | this.AdjustWindow(&x,&y,&w,&h)
283 | newSize := Buffer(16,0)
284 | NumPut("uint",this.width := w,newSize,0)
285 | NumPut("uint",this.height := h,newSize,4)
286 | DllCall(this._NRSize,"Ptr",this.renderTarget,"ptr",newsize)
287 | this.SetPosition(x,y)
288 | } else if ((x<<16)+y != this.lastPos) {
289 | this.AdjustWindow(&x,&y,&w,&h)
290 | this.SetPosition(x,y)
291 | }
292 | }
293 |
294 | DllCall(this._BeginDraw,"Ptr",this.renderTarget)
295 | DllCall(this._Clear,"Ptr",this.renderTarget,"Ptr",this.clrPtr)
296 | if (this.notifyActive) {
297 | ;if (this.callbacks["active"])
298 | ;this.callbacks["active"].call(this,1) ;not implemented yet
299 | this.notifyActive := 0
300 | }
301 | return this.drawing := 1
302 | }
303 |
304 |
305 | ;####################################################################################################################################################################################################################################
306 | ;EndDraw
307 | ;
308 | ;return ; Void
309 | ;
310 | ;Notes ; Must always call EndDraw to finish drawing and update the overlay
311 |
312 | EndDraw() {
313 | local pOut:=0
314 | if (this.drawing)
315 | DllCall(this._EndDraw,"Ptr",this.renderTarget,"Ptr*",&pOut,"Ptr*",&pOut)
316 | }
317 |
318 |
319 | ;####################################################################################################################################################################################################################################
320 | ;DrawImage
321 | ;
322 | ;dstX : X position to draw to
323 | ;dstY : Y position to draw to
324 | ;dstW : Width of image to draw to
325 | ;dstH : Height of image to draw to
326 | ;srcX : X position to draw from
327 | ;srcY : Y position to draw from
328 | ;srcW : Width of image to draw from
329 | ;srcH : Height of image to draw from
330 | ;alpha : Image transparency, float between 0 and 1
331 | ;drawCentered : Draw the image centered on dstX/dstY, otherwise dstX/dstY will be the top left of the image
332 | ;rotation : Image rotation in degrees (0-360)
333 | ;rotationOffsetX : X offset to base rotations on (defaults to center x)
334 | ;rotationOffsetY : Y offset to base rotations on (defaults to center y)
335 | ;
336 | ;return ; Void
337 |
338 | DrawImage(image,dstX,dstY,dstW:=0,dstH:=0,srcX:=0,srcY:=0,srcW:=0,srcH:=0,alpha:=1,drawCentered:=0,rotation:=0,rotOffX:=0,rotOffY:=0) {
339 | i := (this.imageCache.Has(image) ? this.imageCache[image] : this.cacheImage(image))
340 |
341 | if (dstW <= 0)
342 | dstW := i["w"]
343 | if (dstH <= 0)
344 | dstH := i["h"]
345 | x := dstX-(drawCentered?dstW/2:0)
346 | y := dstY-(drawCentered?dstH/2:0)
347 | NumPut("float", x, this.rect1Ptr, 0)
348 | NumPut("float", y, this.rect1Ptr, 4)
349 | NumPut("float", x + dstW, this.rect1Ptr, 8)
350 | NumPut("float", y + dstH, this.rect1Ptr, 12)
351 | NumPut("float", srcX, this.rect2Ptr, 0)
352 | NumPut("float", srcY,this.rect2Ptr,4)
353 | NumPut("float", srcX + (srcW=0?i["w"]:srcW),this.rect2Ptr,8)
354 | NumPut("float", srcY + (srcH=0?i["h"]:srcH),this.rect2Ptr,12)
355 |
356 | if (rotation != 0) {
357 | if (this.bits) {
358 | bf := Buffer(64)
359 | if (rotOffX or rotOffY) {
360 | NumPut("float", dstX+rotOffX, bf, 0)
361 | NumPut("float", dstY+rotOffY,bf,4)
362 | } else {
363 | NumPut("float", dstX+(drawCentered?0:dstW/2), bf, 0)
364 | NumPut("float", dstY+(drawCentered?0:dstH/2), bf, 4)
365 | }
366 | DllCall("d2d1\D2D1MakeRotateMatrix","float",rotation,"double",NumGet(bf,0,"double"),"ptr",this.matrixPtr)
367 | } else {
368 | DllCall("d2d1\D2D1MakeRotateMatrix","float",rotation,"float",dstX+(drawCentered?0:dstW/2),"float",dstY+(drawCentered?0:dstH/2),"ptr",this.matrixPtr)
369 | }
370 | DllCall(this._RMatrix,"ptr",this.renderTarget,"ptr",this.matrixPtr)
371 | DllCall(this._DrawImage,"ptr",this.renderTarget,"ptr",i["p"],"ptr",this.rect1Ptr,"float",alpha,"uint",this.interpolationMode,"ptr",this.rect2Ptr)
372 | this.SetIdentity()
373 | DllCall(this._RMatrix,"ptr",this.renderTarget,"ptr",this.matrixPtr)
374 | } else {
375 | DllCall(this._DrawImage,"ptr",this.renderTarget,"ptr",i["p"],"ptr",this.rect1Ptr,"float",alpha,"uint",this.interpolationMode,"ptr",this.rect2Ptr)
376 | }
377 | }
378 |
379 |
380 | ;####################################################################################################################################################################################################################################
381 | ;DrawText
382 | ;
383 | ;text : The text to be drawn
384 | ;x : X position
385 | ;y : Y position
386 | ;size : Size of font
387 | ;color : Color of font
388 | ;fontName : Font name (must be installed)
389 | ;extraOptions : Additonal options which may contain any of the following seperated by spaces:
390 | ; Width ............. w[number] : Example > w200 (Default: this.width)
391 | ; Height ............ h[number] : Example > h200 (Default: this.height)
392 | ; Alignment ......... a[Left/Right/Center] : Example > aCenter (Default: Left)
393 | ; DropShadow ........ ds[hex color] : Example > dsFF000000 (Default: DISABLED)
394 | ; DropShadowXOffset . dsx[number] : Example > dsx2 (Default: 1)
395 | ; DropShadowYOffset . dsy[number] : Example > dsy2 (Default: 1)
396 | ; Outline ........... ol[hex color] : Example > olFF000000 (Default: DISABLED)
397 | ;
398 | ;return ; Void
399 |
400 | DrawText(text,x,y,size:=18,color:=0xFFFFFFFF,fontName:="Arial",extraOptions:="") {
401 | local w,h,p,ds,dsx,dsy,ol
402 | w := (RegExMatch(extraOptions,"w([\d\.]+)",&w) ? w[1] : this.width)
403 | h := (RegExMatch(extraOptions,"h([\d\.]+)",&h) ? h[1] : this.height)
404 |
405 | p := (this.fonts.Has(fontName size) ? this.fonts[fontName size] : this.CacheFont(fontName,size))
406 |
407 | DllCall(this.vTable(p,3),"ptr",p,"uint",(InStr(extraOptions,"aRight") ? 1 : InStr(extraOptions,"aCenter") ? 2 : 0))
408 |
409 | if (RegExMatch(extraOptions,"ds([a-fA-F\d]+)",&ds)) {
410 | dsx := (RegExMatch(extraOptions,"dsx([\d\.]+)",&dsx) ? dsx[1] : 1)
411 | dsy := (RegExMatch(extraOptions,"dsy([\d\.]+)",&dsy) ? dsy[1] : 1)
412 | this.DrawTextShadow(p,text,x+dsx,y+dsy,w,h,"0x" ds[1])
413 | } else if (RegExMatch(extraOptions,"ol([a-fA-F\d]+)",&ol)) {
414 | this.DrawTextOutline(p,text,x,y,w,h,"0x" ol[1])
415 | }
416 |
417 | this.SetBrushColor(color)
418 | bf := Buffer(64)
419 | NumPut("float", x, bf, 0)
420 | NumPut("float", y, bf, 4)
421 | NumPut("float", x+w, bf, 8)
422 | NumPut("float", y+h, bf, 12)
423 |
424 | DllCall(this._DrawText,"ptr",this.renderTarget,"wstr",text,"uint",strlen(text),"ptr",p,"ptr",bf,"ptr",this.brush,"uint",0,"uint",0)
425 | }
426 |
427 |
428 | ;####################################################################################################################################################################################################################################
429 | ;DrawEllipse
430 | ;
431 | ;x : X position
432 | ;y : Y position
433 | ;w : Width of ellipse
434 | ;h : Height of ellipse
435 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
436 | ;thickness : Thickness of the line
437 | ;
438 | ;return ; Void
439 |
440 | DrawEllipse(x, y, w, h, color, thickness:=1) {
441 | this.SetBrushColor(color)
442 | bf := Buffer(64)
443 | NumPut("float", x, bf, 0)
444 | NumPut("float", y, bf, 4)
445 | NumPut("float", w, bf, 8)
446 | NumPut("float", h, bf, 12)
447 | DllCall(this._DrawEllipse,"Ptr",this.renderTarget,"Ptr",bf,"ptr",this.brush,"float",thickness,"ptr",this.stroke)
448 | }
449 |
450 |
451 | ;####################################################################################################################################################################################################################################
452 | ;FillEllipse
453 | ;
454 | ;x : X position
455 | ;y : Y position
456 | ;w : Width of ellipse
457 | ;h : Height of ellipse
458 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
459 | ;
460 | ;return ; Void
461 |
462 | FillEllipse(x, y, w, h, color) {
463 | this.SetBrushColor(color)
464 | bf := Buffer(64)
465 | NumPut("float", x, bf, 0)
466 | NumPut("float", y, bf, 4)
467 | NumPut("float", w, bf, 8)
468 | NumPut("float", h, bf, 12)
469 | DllCall(this._FillEllipse,"Ptr",this.renderTarget,"Ptr",bf,"ptr",this.brush)
470 | }
471 |
472 |
473 | ;####################################################################################################################################################################################################################################
474 | ;DrawCircle
475 | ;
476 | ;x : X position
477 | ;y : Y position
478 | ;radius : Radius of circle
479 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
480 | ;thickness : Thickness of the line
481 | ;
482 | ;return ; Void
483 |
484 | DrawCircle(x, y, radius, color, thickness:=1) {
485 | this.SetBrushColor(color)
486 | bf := Buffer(64)
487 | NumPut("float", x, bf, 0)
488 | NumPut("float", y, bf, 4)
489 | NumPut("float", radius, bf, 8)
490 | NumPut("float", radius, bf, 12)
491 | DllCall(this._DrawEllipse,"Ptr",this.renderTarget,"Ptr",bf,"ptr",this.brush,"float",thickness,"ptr",this.stroke)
492 | }
493 |
494 |
495 | ;####################################################################################################################################################################################################################################
496 | ;FillCircle
497 | ;
498 | ;x : X position
499 | ;y : Y position
500 | ;radius : Radius of circle
501 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
502 | ;
503 | ;return ; Void
504 |
505 | FillCircle(x, y, radius, color) {
506 | this.SetBrushColor(color)
507 | bf := Buffer(64)
508 | NumPut("float", x, bf, 0)
509 | NumPut("float", y, bf, 4)
510 | NumPut("float", radius, bf, 8)
511 | NumPut("float", radius, bf, 12)
512 | DllCall(this._FillEllipse,"Ptr",this.renderTarget,"Ptr",bf,"ptr",this.brush)
513 | }
514 |
515 |
516 | ;####################################################################################################################################################################################################################################
517 | ;DrawRectangle
518 | ;
519 | ;x : X position
520 | ;y : Y position
521 | ;w : Width of rectangle
522 | ;h : Height of rectangle
523 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
524 | ;thickness : Thickness of the line
525 | ;
526 | ;return ; Void
527 |
528 | DrawRectangle(x, y, w, h, color, thickness:=1) {
529 | this.SetBrushColor(color)
530 | bf := Buffer(64)
531 | NumPut("float", x, bf, 0)
532 | NumPut("float", y, bf, 4)
533 | NumPut("float", x+w, bf, 8)
534 | NumPut("float", y+h, bf, 12)
535 | DllCall(this._DrawRectangle,"Ptr",this.renderTarget,"Ptr",bf,"ptr",this.brush,"float",thickness,"ptr",this.stroke)
536 | }
537 |
538 |
539 | ;####################################################################################################################################################################################################################################
540 | ;FillRectangle
541 | ;
542 | ;x : X position
543 | ;y : Y position
544 | ;w : Width of rectangle
545 | ;h : Height of rectangle
546 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
547 | ;
548 | ;return ; Void
549 |
550 | FillRectangle(x, y, w, h, color) {
551 | this.SetBrushColor(color)
552 | bf := Buffer(64)
553 | NumPut("float", x, bf, 0)
554 | NumPut("float", y, bf, 4)
555 | NumPut("float", x+w, bf, 8)
556 | NumPut("float", y+h, bf, 12)
557 | DllCall(this._FillRectangle,"Ptr",this.renderTarget,"Ptr",bf,"ptr",this.brush)
558 | }
559 |
560 |
561 | ;####################################################################################################################################################################################################################################
562 | ;DrawRoundedRectangle
563 | ;
564 | ;x : X position
565 | ;y : Y position
566 | ;w : Width of rectangle
567 | ;h : Height of rectangle
568 | ;radiusX : The x-radius for the quarter ellipse that is drawn to replace every corner of the rectangle.
569 | ;radiusY : The y-radius for the quarter ellipse that is drawn to replace every corner of the rectangle.
570 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
571 | ;thickness : Thickness of the line
572 | ;
573 | ;return ; Void
574 |
575 | DrawRoundedRectangle(x, y, w, h, radiusX, radiusY, color, thickness:=1) {
576 | this.SetBrushColor(color)
577 | bf := Buffer(64)
578 | NumPut("float", x, bf, 0)
579 | NumPut("float", y, bf, 4)
580 | NumPut("float", x+w, bf, 8)
581 | NumPut("float", y+h, bf, 12)
582 | NumPut("float", radiusX, bf, 16)
583 | NumPut("float", radiusY, bf, 20)
584 | DllCall(this._DrawRoundedRectangle,"Ptr",this.renderTarget,"Ptr",bf,"ptr",this.brush,"float",thickness,"ptr",this.stroke)
585 | }
586 |
587 |
588 | ;####################################################################################################################################################################################################################################
589 | ;FillRectangle
590 | ;
591 | ;x : X position
592 | ;y : Y position
593 | ;w : Width of rectangle
594 | ;h : Height of rectangle
595 | ;radiusX : The x-radius for the quarter ellipse that is drawn to replace every corner of the rectangle.
596 | ;radiusY : The y-radius for the quarter ellipse that is drawn to replace every corner of the rectangle.
597 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
598 | ;
599 | ;return ; Void
600 |
601 | FillRoundedRectangle(x, y, w, h, radiusX, radiusY, color) {
602 | this.SetBrushColor(color)
603 | bf := Buffer(64)
604 | NumPut("float", x, bf, 0)
605 | NumPut("float", y, bf, 4)
606 | NumPut("float", x+w, bf, 8)
607 | NumPut("float", y+h, bf, 12)
608 | NumPut("float", radiusX, bf, 16)
609 | NumPut("float", radiusY, bf, 20)
610 | DllCall(this._FillRoundedRectangle,"Ptr",this.renderTarget,"Ptr",bf,"ptr",this.brush)
611 | }
612 |
613 |
614 | ;####################################################################################################################################################################################################################################
615 | ;DrawLine
616 | ;
617 | ;x1 : X position for line start
618 | ;y1 : Y position for line start
619 | ;x2 : X position for line end
620 | ;y2 : Y position for line end
621 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
622 | ;thickness : Thickness of the line
623 | ;
624 | ;return ; Void
625 |
626 | DrawLine(x1,y1,x2,y2,color:=0xFFFFFFFF,thickness:=1,rounded:=0) {
627 | this.SetBrushColor(color)
628 | if (this.bits) {
629 | bf := Buffer(64)
630 | NumPut("float", x1, bf, 0) ;Special thanks to teadrinker for helping me
631 | NumPut("float", y1, bf, 4) ;with these params!
632 | NumPut("float", x2, bf, 8)
633 | NumPut("float", y2, bf, 12)
634 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"Double",NumGet(bf,0,"double"),"Double",NumGet(bf,8,"double"),"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
635 | } else {
636 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"float",x1,"float",y1,"float",x2,"float",y2,"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
637 | }
638 |
639 | }
640 |
641 |
642 | ;####################################################################################################################################################################################################################################
643 | ;DrawLines
644 | ;
645 | ;lines : An array of 2d points, example: [[0,0],[5,0],[0,5]]
646 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
647 | ;connect : If 1 then connect the start and end together
648 | ;thickness : Thickness of the line
649 | ;
650 | ;return ; 1 on success; 0 otherwise
651 |
652 | DrawLines(points,color,connect:=0,thickness:=1,rounded:=0) {
653 | if (points.length < 2)
654 | return 0
655 | lx := sx := points[1][1]
656 | ly := sy := points[1][2]
657 | this.SetBrushColor(color)
658 | if (this.bits) {
659 | bf := Buffer(64)
660 | loop points.length-1 {
661 | NumPut("float", lx, bf, 0), NumPut("float", ly, bf, 4), NumPut("float", lx:=points[a_index+1][1], bf, 8), NumPut("float", ly:=points[a_index+1][2], bf, 12)
662 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"Double",NumGet(bf,0,"double"),"Double",NumGet(bf,8,"double"),"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
663 | }
664 | if (connect) {
665 | NumPut("float", sx, bf, 0), NumPut("float", sy, bf, 4), NumPut("float", lx, bf, 8), NumPut("float", ly, bf, 12)
666 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"Double",NumGet(bf,0,"double"),"Double",NumGet(bf,8,"double"),"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
667 | }
668 | } else {
669 | loop points.length-1 {
670 | x1 := lx
671 | y1 := ly
672 | x2 := lx := points[a_index+1][1]
673 | y2 := ly := points[a_index+1][2]
674 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"float",x1,"float",y1,"float",x2,"float",y2,"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
675 | }
676 | if (connect)
677 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"float",sx,"float",sy,"float",lx,"float",ly,"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
678 | }
679 | return 1
680 | }
681 |
682 |
683 | ;####################################################################################################################################################################################################################################
684 | ;DrawPolygon
685 | ;
686 | ;points : An array of 2d points, example: [[0,0],[5,0],[0,5]]
687 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
688 | ;thickness : Thickness of the line
689 | ;xOffset : X offset to draw the polygon array
690 | ;yOffset : Y offset to draw the polygon array
691 | ;
692 | ;return ; 1 on success; 0 otherwise
693 |
694 | DrawPolygon(points,color,thickness:=1,rounded:=0,xOffset:=0,yOffset:=0) {
695 | if (points.length < 3)
696 | return 0
697 | pGeom := sink := 0
698 | if (DllCall(this.vTable(this.factory,10),"Ptr",this.factory,"Ptr*",&pGeom) = 0) {
699 | if (DllCall(this.vTable(pGeom,17),"Ptr",pGeom,"Ptr*",&sink) = 0) {
700 | this.SetBrushColor(color)
701 | if (this.bits) {
702 | bf := Buffer(64)
703 | NumPut("float", points[1][1]+xOffset, bf, 0)
704 | NumPut("float", points[1][2]+yOffset, bf, 4)
705 | DllCall(this.vTable(sink,5),"ptr",sink,"double",numget(bf,0,"double"),"uint",1)
706 | loop points.length-1
707 | {
708 | NumPut("float", points[a_index+1][1]+xOffset, bf, 0)
709 | NumPut("float", points[a_index+1][2]+yOffset, bf, 4)
710 | DllCall(this.vTable(sink,10),"ptr",sink,"double",numget(bf,0,"double"))
711 | }
712 | DllCall(this.vTable(sink,8),"ptr",sink,"uint",1)
713 | DllCall(this.vTable(sink,9),"ptr",sink)
714 | } else {
715 | DllCall(this.vTable(sink,5),"ptr",sink,"float",points[1][1]+xOffset,"float",points[1][2]+yOffset,"uint",1)
716 | loop points.length-1
717 | DllCall(this.vTable(sink,10),"ptr",sink,"float",points[a_index+1][1]+xOffset,"float",points[a_index+1][2]+yOffset)
718 | DllCall(this.vTable(sink,8),"ptr",sink,"uint",1)
719 | DllCall(this.vTable(sink,9),"ptr",sink)
720 | }
721 |
722 | if (DllCall(this.vTable(this.renderTarget,22),"Ptr",this.renderTarget,"Ptr",pGeom,"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke)) = 0) {
723 | DllCall(this.vTable(sink,2),"ptr",sink)
724 | DllCall(this.vTable(pGeom,2),"Ptr",pGeom)
725 | return 1
726 | }
727 | DllCall(this.vTable(sink,2),"ptr",sink)
728 | DllCall(this.vTable(pGeom,2),"Ptr",pGeom)
729 | }
730 | }
731 |
732 |
733 | return 0
734 | }
735 |
736 |
737 | ;####################################################################################################################################################################################################################################
738 | ;FillPolygon
739 | ;
740 | ;points : An array of 2d points, example: [[0,0],[5,0],[0,5]]
741 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
742 | ;xOffset : X offset to draw the filled polygon array
743 | ;yOffset : Y offset to draw the filled polygon array
744 | ;
745 | ;return ; 1 on success; 0 otherwise
746 |
747 | FillPolygon(points,color,xoffset:=0,yoffset:=0) {
748 | if (points.length < 3)
749 | return 0
750 | pGeom := sink := 0
751 | if (DllCall(this.vTable(this.factory,10),"Ptr",this.factory,"Ptr*",&pGeom) = 0) {
752 | if (DllCall(this.vTable(pGeom,17),"Ptr",pGeom,"Ptr*",&sink) = 0) {
753 | this.SetBrushColor(color)
754 | if (this.bits) {
755 | bf := Buffer(64)
756 | NumPut("float", points[1][1]+xoffset, bf, 0)
757 | NumPut("float", points[1][2]+yoffset, bf, 4)
758 | DllCall(this.vTable(sink,5),"ptr",sink,"double",numget(bf,0,"double"),"uint",0)
759 | loop points.length-1
760 | {
761 | NumPut("float", points[a_index+1][1]+xoffset, bf, 0)
762 | NumPut("float", points[a_index+1][2]+yoffset, bf, 4)
763 | DllCall(this.vTable(sink,10),"ptr",sink,"double",numget(bf,0,"double"))
764 | }
765 | DllCall(this.vTable(sink,8),"ptr",sink,"uint",1)
766 | DllCall(this.vTable(sink,9),"ptr",sink)
767 | } else {
768 | DllCall(this.vTable(sink,5),"ptr",sink,"float",points[1][1]+xoffset,"float",points[1][2]+yoffset,"uint",0)
769 | loop points.length-1
770 | DllCall(this.vTable(sink,10),"ptr",sink,"float",points[a_index+1][1]+xoffset,"float",points[a_index+1][2]+yoffset)
771 | DllCall(this.vTable(sink,8),"ptr",sink,"uint",1)
772 | DllCall(this.vTable(sink,9),"ptr",sink)
773 | }
774 |
775 | if (DllCall(this.vTable(this.renderTarget,23),"Ptr",this.renderTarget,"Ptr",pGeom,"ptr",this.brush,"ptr",0) = 0) {
776 | DllCall(this.vTable(sink,2),"ptr",sink)
777 | DllCall(this.vTable(pGeom,2),"Ptr",pGeom)
778 | return 1
779 | }
780 | DllCall(this.vTable(sink,2),"ptr",sink)
781 | DllCall(this.vTable(pGeom,2),"Ptr",pGeom)
782 |
783 | }
784 | }
785 |
786 |
787 | return 0
788 | }
789 |
790 |
791 | ;####################################################################################################################################################################################################################################
792 | ;SetPosition
793 | ;
794 | ;x : X position to move the window to (screen space)
795 | ;y : Y position to move the window to (screen space)
796 | ;w : New Width (only applies when not attached)
797 | ;h : New Height (only applies when not attached)
798 | ;
799 | ;return ; Void
800 | ;
801 | ;notes : Only used when not attached to a window
802 |
803 | SetPosition(x,y,w:=0,h:=0) {
804 | this.x := x
805 | this.y := y
806 | if (!this.attachHWND and w != 0 and h != 0) {
807 | newSize := Buffer(16,0)
808 | NumPut("uint",this.width := w,newSize,0)
809 | NumPut("uint",this.height := h,newSize,4)
810 | DllCall(this._NRSize,"Ptr",this.renderTarget,"ptr",newsize)
811 | }
812 | DllCall("MoveWindow","Uptr",this.hwnd,"int",x,"int",y,"int",this.width,"int",this.height,"char",1)
813 | }
814 |
815 |
816 | ;####################################################################################################################################################################################################################################
817 | ;GetImageDimensions
818 | ;
819 | ;image : Image file name
820 | ;&w : Width of image
821 | ;&h : Height of image
822 | ;
823 | ;return ; Void
824 |
825 | GetImageDimensions(image, &w, &h) {
826 | local i
827 | i := (this.imageCache.Has(image) ? this.imageCache[image] : this.cacheImage(image))
828 | w := i["w"]
829 | h := i["h"]
830 | }
831 |
832 |
833 | ;####################################################################################################################################################################################################################################
834 | ;GetMousePos
835 | ;
836 | ;&x : X position of mouse to return
837 | ;&y : Y position of mouse to return
838 | ;realRegionOnly : Return 1 only if in the real region, which does not include the invisible borders, (client area does not have borders)
839 | ;
840 | ;return ; Returns 1 if mouse within window/client region; 0 otherwise
841 |
842 | GetMousePos(&x, &y, realRegionOnly:=0) {
843 | DllCall("GetCursorPos","ptr",this.tBufferPtr)
844 | x := NumGet(this.tBufferPtr,0,"int")
845 | y := NumGet(this.tBufferPtr,4,"int")
846 | if (!realRegionOnly) {
847 | inside := (x >= this.x and y >= this.y and x <= this.x2 and y <= this.y2)
848 | x += this.offX
849 | y += this.offY
850 | return inside
851 | }
852 | x += this.offX
853 | y += this.offY
854 | return (x >= this.realX and y >= this.realY and x <= this.realX2 and y <= this.realY2)
855 |
856 | }
857 |
858 |
859 | ;####################################################################################################################################################################################################################################
860 | ;Clear
861 | ;
862 | ;notes : Clears the overlay, essentially the same as running BegindDraw followed by EndDraw
863 |
864 | Clear() {
865 | local pOut:=0
866 | DllCall(this._BeginDraw,"Ptr",this.renderTarget)
867 | DllCall(this._Clear,"Ptr",this.renderTarget,"Ptr",this.clrPtr)
868 | DllCall(this._EndDraw,"Ptr",this.renderTarget,"Ptr*",&pOut,"Ptr*",&pOut)
869 | }
870 |
871 |
872 |
873 |
874 | ;0 = off
875 | ;1 = on
876 | SetAntialias(state:=0) {
877 | DllCall(this.vTable(this.renderTarget,32),"Ptr",this.renderTarget,"Uint",!state)
878 | }
879 |
880 |
881 |
882 | DisableOnErase() {
883 | OnMessage(0x14,this.OnEraseFunc,0)
884 | }
885 |
886 |
887 |
888 | ;##########################################
889 | ; internal functions used by the class
890 | ;##########################################
891 | AdjustWindow(&x,&y,&w,&h) {
892 | this.lastPos := (x<<16)+y
893 | this.lastSize := (w<<16)+h
894 | DllCall("GetWindowInfo","Uptr",(this.attachHWND ? this.attachHWND : this.hwnd),"ptr",this.tBufferPtr)
895 | pp := (this.attachClient ? 20 : 4)
896 | x1 := NumGet(this.tBufferPtr,pp,"int")
897 | y1 := NumGet(this.tBufferPtr,pp+4,"int")
898 | x2 := NumGet(this.tBufferPtr,pp+8,"int")
899 | y2 := NumGet(this.tBufferPtr,pp+12,"int")
900 | this.width := w := x2-x1
901 | this.height := h := y2-y1
902 | this.x := x := x1
903 | this.y := y := y1
904 | this.x2 := x + w
905 | this.y2 := y + h
906 | hBorders := (this.attachClient ? 0 : NumGet(this.tBufferPtr,48,"int"))
907 | vBorders := (this.attachClient ? 0 : NumGet(this.tBufferPtr,52,"int"))
908 | this.realX := hBorders
909 | this.realY := 0
910 | this.realWidth := w - (hBorders*2)
911 | this.realHeight := h - vBorders
912 | this.realX2 := this.realX + this.realWidth
913 | this.realY2 := this.realY + this.realHeight
914 | this.offX := -x1 ;- hBorders
915 | this.offY := -y1
916 | }
917 | SetIdentity(o:=0) {
918 | NumPut("float", 1, this.matrixPtr, o+0)
919 | NumPut("float", 0, this.matrixPtr, o+4)
920 | NumPut("float", 0, this.matrixPtr, o+8)
921 | NumPut("float", 1, this.matrixPtr, o+12)
922 | NumPut("float", 0, this.matrixPtr, o+16)
923 | NumPut("float", 0, this.matrixPtr, o+20)
924 | }
925 | DrawTextShadow(p,text,x,y,w,h,color) {
926 | this.SetBrushColor(color)
927 | bf := Buffer(64)
928 | NumPut("float", x, bf, 0)
929 | NumPut("float", y, bf, 4)
930 | NumPut("float", x+w, bf, 8)
931 | NumPut("float", y+h, bf, 12)
932 | DllCall(this._DrawText,"ptr",this.renderTarget,"wstr",text,"uint",strlen(text),"ptr",p,"ptr",bf,"ptr",this.brush,"uint",0,"uint",0)
933 | }
934 | DrawTextOutline(p,text,x,y,w,h,color) {
935 | static o := [[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]]
936 | this.SetBrushColor(color)
937 | bf := Buffer(64)
938 | for k,v in o
939 | {
940 | NumPut("float", x+v[1], bf, 0)
941 | NumPut("float", y+v[2], bf, 4)
942 | NumPut("float", x+w+v[1], bf, 8)
943 | NumPut("float", y+h+v[2], bf, 12)
944 | DllCall(this._DrawText,"ptr",this.renderTarget,"wstr",text,"uint",strlen(text),"ptr",p,"ptr",bf,"ptr",this.brush,"uint",0,"uint",0)
945 | }
946 | }
947 | Err(str*) {
948 | s := ""
949 | for k,v in str
950 | s .= (s = "" ? "" : "`n`n") v
951 | msgbox(s, "Problem!", 0x30 | 0x1000)
952 | }
953 | LoadLib(lib*) {
954 | for k,v in lib {
955 | if (!DllCall("GetModuleHandle", "str", v, "Ptr")) {
956 | DllCall("LoadLibrary", "Str", v)
957 | }
958 | }
959 | }
960 | SetBrushColor(col) {
961 | if (col <= 0xFFFFFF)
962 | col += 0xFF000000
963 | if (col != this.lastCol) {
964 | NumPut("Float",((col & 0xFF0000)>>16)/255,this.colPtr,0)
965 | NumPut("Float",((col & 0xFF00)>>8)/255,this.colPtr,4)
966 | NumPut("Float",((col & 0xFF))/255,this.colPtr,8)
967 | NumPut("Float",(col > 0xFFFFFF ? ((col & 0xFF000000)>>24)/255 : 1),this.colPtr,12)
968 | DllCall(this._SetBrush,"Ptr",this.brush,"Ptr",this.colPtr)
969 | this.lastCol := col
970 | return 1
971 | }
972 | return 0
973 | }
974 | vTable(a,p) {
975 | v := NumGet(a+0,0,"ptr")
976 | return (v ? NumGet(v+0,p*a_ptrsize,"Ptr") : 0)
977 | }
978 | _guid(guidStr,&clsid) {
979 | clsid := buffer(16,0)
980 | DllCall("ole32\CLSIDFromString", "WStr", guidStr, "Ptr", clsid)
981 | }
982 | CacheImage(image) {
983 | if (this.imageCache.has(image))
984 | return 1
985 | if (image = "") {
986 | this.Err("Error, expected resource image path but empty variable was supplied!")
987 | return 0
988 | }
989 | if (!FileExist(image)) {
990 | this.Err("Error finding resource image","'" image "' does not exist!")
991 | return 0
992 | }
993 | w := h := bm := bitmap := 0
994 | DllCall("gdiplus\GdipCreateBitmapFromFile", "Str", image, "Ptr*", &bm)
995 | DllCall("gdiplus\GdipGetImageWidth", "Ptr", bm, "Uint*", &w)
996 | DllCall("gdiplus\GdipGetImageHeight", "Ptr", bm, "Uint*", &h)
997 | r := buffer(16,0)
998 | NumPut("uint", w, r, 8)
999 | NumPut("uint", h, r, 12)
1000 | bmdata := buffer(32,0)
1001 | ret := DllCall("Gdiplus\GdipBitmapLockBits", "Ptr", bm, "Ptr", r, "uint", 3, "int", 0x26200A, "Ptr", bmdata)
1002 | scan := NumGet(bmdata, 16, "Ptr")
1003 | p := DllCall("GlobalAlloc", "uint", 0x40, "ptr", 16+((w*h)*4), "ptr")
1004 | DllCall(this._cacheImage,"Ptr",p,"Ptr",scan,"int",w,"int",h,"uchar",255,"int")
1005 | DllCall("Gdiplus\GdipBitmapUnlockBits", "Ptr", bm, "Ptr", bmdata)
1006 | DllCall("gdiplus\GdipDisposeImage", "ptr", bm)
1007 | props := buffer(64,0)
1008 | NumPut("uint", 28, props, 0)
1009 | NumPut("uint",1,props,4)
1010 | if (this.bits) {
1011 | bf := Buffer(64)
1012 | NumPut("uint", w, bf, 0)
1013 | NumPut("uint", h, bf, 4)
1014 | if (v := DllCall(this.vTable(this.renderTarget,4),"ptr",this.renderTarget,"int64",NumGet(bf,0,"int64"),"ptr",p,"uint",4 * w,"ptr",props,"Ptr*",&bitmap) != 0) {
1015 | this.Err("Problem creating D2D bitmap for image '" image "'")
1016 | return 0
1017 | }
1018 | } else {
1019 | if (v := DllCall(this.vTable(this.renderTarget,4),"ptr",this.renderTarget,"uint",w,"uint",h,"ptr",p,"uint",4 * w,"ptr",props,"Ptr*",&bitmap) != 0) {
1020 | this.Err("Problem creating D2D bitmap for image '" image "'")
1021 | return 0
1022 | }
1023 | }
1024 | return this.imageCache[image] := Map("p",bitmap, "w",w, "h",h)
1025 | }
1026 | CacheFont(name,size) {
1027 | local textFormat := 0
1028 | if (DllCall(this.vTable(this.wFactory,15),"ptr",this.wFactory,"wstr",name,"ptr",0,"uint",400,"uint",0,"uint",5,"float",size,"wstr","en-us","Ptr*",&textFormat) != 0) {
1029 | this.Err("Unable to create font: " name " (size: " size ")","Try a different font or check to see if " name " is a valid font!")
1030 | return 0
1031 | }
1032 | return this.fonts[name size] := textFormat
1033 | }
1034 | __Delete() {
1035 | DllCall("gdiplus\GdiplusShutdown", "Ptr*", this.gdiplusToken)
1036 | DllCall(this.vTable(this.factory,2),"ptr",this.factory)
1037 | DllCall(this.vTable(this.stroke,2),"ptr",this.stroke)
1038 | DllCall(this.vTable(this.strokeRounded,2),"ptr",this.strokeRounded)
1039 | DllCall(this.vTable(this.renderTarget,2),"ptr",this.renderTarget)
1040 | DllCall(this.vTable(this.brush,2),"ptr",this.brush)
1041 | DllCall(this.vTable(this.wfactory,2),"ptr",this.wfactory)
1042 | DllCall("GlobalFree", "ptr", this._cacheImage)
1043 | for k,v in this.fonts {
1044 | if (v and this.vTable(v,2)) {
1045 | DllCall(this.vTable(v,2),"ptr",v)
1046 | }
1047 | }
1048 | for k,v in this.imageCache {
1049 | if (v["p"] and this.vTable(v["p"],2)) {
1050 | DllCall(this.vTable(v["p"],2),"ptr",v["p"])
1051 | }
1052 | }
1053 | this.gui.destroy()
1054 | OnMessage(0x14,this.OnEraseFunc,0)
1055 | this.OnEraseFunc := ""
1056 | }
1057 | InitFuncs() {
1058 | this._DrawText := this.vTable(this.renderTarget,27)
1059 | this._BeginDraw := this.vTable(this.renderTarget,48)
1060 | this._Clear := this.vTable(this.renderTarget,47)
1061 | this._DrawImage := this.vTable(this.renderTarget,26)
1062 | this._EndDraw := this.vTable(this.renderTarget,49)
1063 | this._RMatrix := this.vTable(this.renderTarget,30)
1064 | this._DrawEllipse := this.vTable(this.renderTarget,20)
1065 | this._FillEllipse := this.vTable(this.renderTarget,21)
1066 | this._DrawRectangle := this.vTable(this.renderTarget,16)
1067 | this._FillRectangle := this.vTable(this.renderTarget,17)
1068 | this._DrawRoundedRectangle := this.vTable(this.renderTarget,18)
1069 | this._FillRoundedRectangle := this.vTable(this.renderTarget,19)
1070 | this._DrawLine := this.vTable(this.renderTarget,15)
1071 | this._NRSize := this.vTable(this.renderTarget,58)
1072 | this._SetBrush := this.vTable(this.brush,8)
1073 | }
1074 | Mcode(str) {
1075 | local pp := 0, op := 0
1076 | s := strsplit(str,"|")
1077 | if (s.length != 2)
1078 | return
1079 | if (!DllCall("crypt32\CryptStringToBinary", "str", s[this.bits+1], "uint", 0, "uint", 1, "ptr", 0, "uint*", &pp, "ptr", 0, "ptr", 0))
1080 | return
1081 | p := DllCall("GlobalAlloc", "uint", 0, "ptr", pp, "ptr")
1082 | if (this.bits)
1083 | DllCall("VirtualProtect", "ptr", p, "ptr", pp, "uint", 0x40, "uint*", &op)
1084 | if (DllCall("crypt32\CryptStringToBinary", "str", s[this.bits+1], "uint", 0, "uint", 1, "ptr", p, "uint*", &pp, "ptr", 0, "ptr", 0))
1085 | return p
1086 | DllCall("GlobalFree", "ptr", p)
1087 | }
1088 | Display(state) {
1089 | if (!state) {
1090 | DllCall("User32.dll\ShowWindow","Ptr",this.hwnd,"Int",0)
1091 | } else {
1092 | DllCall("User32.dll\ShowWindow","Ptr",this.hwnd,"Int",4)
1093 | }
1094 | this.notifyActive := 1
1095 | }
1096 | }
1097 | _SOC_ONERASE(oHwnd, wParam, lParam, msg, hwnd) {
1098 | if (oHwnd = hwnd)
1099 | return 0
1100 | }
1101 |
--------------------------------------------------------------------------------
/ShinsOverlayClass.ahk:
--------------------------------------------------------------------------------
1 | ;Direct2d overlay class by Spawnova (5/27/2022)
2 | ;https://github.com/Spawnova/ShinsOverlayClass
3 | ;
4 | ;I'm not a professional programmer, I do this for fun, if it doesn't work for you I can try and help
5 | ;but I can't promise I will be able to solve the issue
6 | ;
7 | ;Special thanks to teadrinker for helping me understand some 64bit param structures! -> https://www.autohotkey.com/boards/viewtopic.php?f=76&t=105420
8 |
9 | #Requires AutoHotkey v1.1.27+
10 |
11 | class ShinsOverlayClass {
12 |
13 | ;x_orTitle : x pos of overlay OR title of window to attach to
14 | ;y_orClient : y pos of overlay OR attach to client instead of window (default window)
15 | ;width_orForeground : width of overlay OR overlay is only drawn when the attached window is in the foreground (default 1)
16 | ;height : height of overlay
17 | ;alwaysOnTop : If enabled, the window will always appear over other windows
18 | ;vsync : If enabled vsync will cause the overlay to update no more than the monitors refresh rate, useful when looping without sleeps
19 | ;clickThrough : If enabled, mouse clicks will pass through the window onto the window beneath
20 | ;taskBarIcon : If enabled, the window will have a taskbar icon
21 | ;guiID : name of the ahk gui id for the overlay window, if 0 defaults to "ShinsOverlayClass_TICKCOUNT"
22 | ;
23 | ;notes : if planning to attach to window these parameters can all be left blank
24 |
25 | __New(x_orTitle:=0,y_orClient:=1,width_orForeground:=1,height:=0,alwaysOnTop:=1,vsync:=0,clickThrough:=1,taskBarIcon:=0,guiID:=0) {
26 |
27 |
28 | ;[input variables] you can change these to affect the way the script behaves
29 |
30 | this.interpolationMode := 0 ;0 = nearestNeighbor, 1 = linear ;affects DrawImage() scaling
31 | this.data := [] ;reserved name for general data storage
32 | this.HideOnStateChange := 1 ;hides or shows the overlay when attached windows state changes, change to 0 to turn this behaviour off
33 |
34 |
35 | ;[output variables] you can read these to get extra info, DO NOT MODIFY THESE
36 |
37 | this.x := x_orTitle ;overlay x position OR title of window to attach to
38 | this.y := y_orClient ;overlay y position OR attach to client area
39 | this.width := width_orForeground ;overlay width OR attached overlay only drawn when window is in foreground
40 | this.height := height ;overlay height
41 | this.x2 := x_orTitle+width_orForeground
42 | this.y2 := y_orClient+height
43 | this.attachHWND := 0 ;HWND of the attached window, 0 if not attached
44 | this.attachClient := 0 ;1 if using client space, 0 otherwise
45 | this.attachForeground := 0 ;1 if overlay is only drawn when the attached window is the active window; 0 otherwise
46 |
47 | ;Generally with windows there are invisible borders that allow
48 | ;the window to be resized, but it makes the window larger
49 | ;these values should contain the window x, y offset and width, height for actual postion and size
50 | this.realX := 0
51 | this.realY := 0
52 | this.realWidth := 0
53 | this.realHeight := 0
54 | this.realX2 := 0
55 | this.realY2 := 0
56 |
57 | this.callbacks := {"Size":0,"Position":0,"Active":0}
58 | ;Size : [this]
59 | ;Position: : [this]
60 | ;Active : [this,state]
61 |
62 |
63 |
64 |
65 |
66 | ;#############################
67 | ; Setup internal stuff
68 | ;#############################
69 | this.bits := (a_ptrsize == 8)
70 | this.imageCache := []
71 | this.fonts := []
72 | this.lastPos := 0
73 | this.offX := -x_orTitle
74 | this.offY := -y_orClient
75 | this.lastCol := 0
76 | this.drawing := -1
77 | this.guiID := guiID := (guiID = 0 ? "ShinsOverlayClass_" a_tickcount : guiID)
78 | this.owned := 0
79 | this.notifyActive := 0
80 | this.alwaysontop := alwaysontop
81 |
82 |
83 | this._cacheImage := this.mcode("VVdWMfZTg+wMi0QkLA+vRCQoi1QkMMHgAoXAfmSLTCQki1wkIA+26gHIiUQkCGaQD7Z5A4PDBIPBBIn4D7bwD7ZB/g+vxpn3/YkEJA+2Qf0Pr8aZ9/2JRCQED7ZB/A+vxpn3/Q+2FCSIU/wPtlQkBIhT/YhD/on4iEP/OUwkCHWvg8QMifBbXl9dw5CQkJCQ|V1ZTRTHbRItUJEBFD6/BRo0MhQAAAABFhcl+YUGD6QFFD7bSSYnQQcHpAkqNdIoERQ+2WANBD7ZAAkmDwARIg8EEQQ+vw5lB9/qJx0EPtkD9QQ+vw5lB9/pBicFBD7ZA/ECIefxEiEn9QQ+vw0SIWf+ZQff6iEH+TDnGdbNEidhbXl/DkJCQkJCQkJCQkJCQ")
84 | this._dtc := this.mcode("VVdWU4PsEIt8JCQPtheE0g+EKgEAADHtx0QkBAAAAAAx9jHAx0QkDAAAAAC7CQAAADHJx0QkCAAAAACJLCTrQI1Kn4D5BXdojUqpD7bRuQcAAACDwAEp2cHhAtPiAdaD+wd0XIPDAQ+2FAeJwYTSD4S2AAAAPQAQAAAPhKsAAACD+wl1u41oAYD6fHQLiejr1o20JgAAAACAfA8BY3XuiUQkDDH2g8ACMdvru410JgCNSr+A+QV3WI1KyeuOjXYAixQki2wkKINEJAgBidPB4wKJHCSLXCQEiUQkBI1LAYlMlQCLTCQMKdmJ64ssJIlMKwSJdCsIidODwwOJHCS7CQAAAOlf////kI20JgAAAACNStCA+QkPhi////+JwbsJAAAAhNIPhUr///+LRCQIg8QQW15fXcOJ9o28JwAAAADHRCQIAAAAAItEJAiDxBBbXl9dw5CQkJCQkJCQkJCQkA==|QVVBVFVXVlNJicsPtgmEyQ+EEgEAADH2Mdsx7UUx0kG5CQAAAEUx5DHARTHAvwcAAADrSA8fQABEjUGfQYD4BXdORI1BqYn5RQ+2wIPAAUQpycHhAkHT4EUBwkGD+Qd0P0GDwQFMY8BDD7YMA4TJD4SCAAAAPQAQAAB0e0GD+Ql1tkSNaAGA+Xx0fUSJ6OvVRI1Bv0GA+AV3PkSNQcnrpkxjw0SNTgGDwwNBg8QBRokMgkqNDIUAAAAAQYnoQbkJAAAAQSnwRIlUCgiJxkSJRAoE65EPH0AARI1B0EGA+AkPhmD///9MY8BBuQkAAACEyQ+Ffv///0SJ4FteX11BXEFdww8fRAAAQ4B8AwFjD4V3////icVFMdKDwAJFMcnpQf///w8fQABFMeREieBbXl9dQVxBXcOQkJCQkJCQkJA=")
85 |
86 | this.LoadLib("d2d1","dwrite","dwmapi","gdiplus")
87 | VarSetCapacity(gsi, 24, 0)
88 | NumPut(1,gsi,0,"uint")
89 | DllCall("gdiplus\GdiplusStartup", "Ptr*", token, "Ptr", &gsi, "Ptr", 0)
90 | this.gdiplusToken := token
91 | this._guid("{06152247-6f50-465a-9245-118bfd3b6007}",clsidFactory)
92 | this._guid("{b859ee5a-d838-4b5b-a2e8-1adc7d93db48}",clsidwFactory)
93 |
94 | if (clickThrough)
95 | gui %guiID%: +hwndhwnd -Caption +E0x80000 +E0x20
96 | else
97 | gui %guiID%: +hwndhwnd -Caption +E0x80000
98 | if (alwaysOnTop)
99 | gui %guiID%: +AlwaysOnTop
100 | if (!taskBarIcon)
101 | gui %guiID%: +ToolWindow
102 |
103 | this.hwnd := hwnd
104 | DllCall("ShowWindow","Uptr",this.hwnd,"uint",(clickThrough ? 8 : 1))
105 |
106 | this.OnEraseFunc := Func("_SOC_ONERASE").Bind(hwnd)
107 | OnMessage(0x14, this.OnEraseFunc)
108 |
109 | this.tBufferPtr := this.SetVarCapacity("ttBuffer",4096)
110 | this.rect1Ptr := this.SetVarCapacity("_rect1",64)
111 | this.rect2Ptr := this.SetVarCapacity("_rect2",64)
112 | this.rtPtr := this.SetVarCapacity("_rtPtr",64)
113 | this.hrtPtr := this.SetVarCapacity("_hrtPtr",64)
114 | this.matrixPtr := this.SetVarCapacity("_matrix",64)
115 | this.colPtr := this.SetVarCapacity("_colPtr",64)
116 | this.clrPtr := this.SetVarCapacity("_clrPtr",64)
117 | VarSetCapacity(margins,16)
118 | NumPut(-1,margins,0,"int"), NumPut(-1,margins,4,"int"), NumPut(-1,margins,8,"int"), NumPut(-1,margins,12,"int")
119 | ext := DllCall("dwmapi\DwmExtendFrameIntoClientArea","Uptr",hwnd,"ptr",&margins,"uint")
120 | if (ext != 0) {
121 | this.Err("Problem with DwmExtendFrameIntoClientArea","overlay will not function`n`nReloading the script usually fixes this`n`nError: " DllCall("GetLastError","uint") " / " ext)
122 | return
123 | }
124 | DllCall("SetLayeredWindowAttributes","Uptr",hwnd,"Uint",0,"char",255,"uint",2)
125 | if (DllCall("d2d1\D2D1CreateFactory","uint",1,"Ptr",&clsidFactory,"uint*",0,"Ptr*",factory) != 0) {
126 | this.Err("Problem creating factory","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
127 | return
128 | }
129 | this.factory := factory
130 | NumPut(255,this.tBufferPtr,16,"float")
131 | if (DllCall(this.vTable(this.factory,11),"ptr",this.factory,"ptr",this.tBufferPtr,"ptr",0,"uint",0,"ptr*",stroke) != 0) {
132 | this.Err("Problem creating stroke","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
133 | return
134 | }
135 | this.stroke := stroke
136 | NumPut(2,this.tBufferPtr,0,"uint")
137 | NumPut(2,this.tBufferPtr,4,"uint")
138 | NumPut(2,this.tBufferPtr,12,"uint")
139 | NumPut(255,this.tBufferPtr,16,"float")
140 | if (DllCall(this.vTable(this.factory,11),"ptr",this.factory,"ptr",this.tBufferPtr,"ptr",0,"uint",0,"ptr*",stroke) != 0) {
141 | this.Err("Problem creating rounded stroke","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
142 | return
143 | }
144 | this.strokeRounded := stroke
145 | NumPut(1,this.rtPtr,8,"uint")
146 | NumPut(96,this.rtPtr,12,"float")
147 | NumPut(96,this.rtPtr,16,"float")
148 | NumPut(hwnd,this.hrtPtr,0,"Uptr")
149 | NumPut(width_orForeground,this.hrtPtr,a_ptrsize,"uint")
150 | NumPut(height,this.hrtPtr,a_ptrsize+4,"uint")
151 | NumPut((vsync?0:2),this.hrtPtr,a_ptrsize+8,"uint")
152 | if (DllCall(this.vTable(this.factory,14),"Ptr",this.factory,"Ptr",this.rtPtr,"ptr",this.hrtPtr,"Ptr*",renderTarget) != 0) {
153 | this.Err("Problem creating renderTarget","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
154 | return
155 | }
156 | this.renderTarget := renderTarget
157 | NumPut(1,this.matrixPtr,0,"float")
158 | this.SetIdentity(4)
159 | if (DllCall(this.vTable(this.renderTarget,8),"Ptr",this.renderTarget,"Ptr",this.colPtr,"Ptr",this.matrixPtr,"Ptr*",brush) != 0) {
160 | this.Err("Problem creating brush","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
161 | return
162 | }
163 | this.brush := brush
164 | DllCall(this.vTable(this.renderTarget,32),"Ptr",this.renderTarget,"Uint",1)
165 | if (DllCall("dwrite\DWriteCreateFactory","uint",0,"Ptr",&clsidwFactory,"Ptr*",wFactory) != 0) {
166 | this.Err("Problem creating writeFactory","overlay will not function`n`nError: " DllCall("GetLastError","uint"))
167 | return
168 | }
169 | this.wFactory := wFactory
170 |
171 | this.InitFuncs()
172 |
173 | if (x_orTitle != 0 and winexist(x_orTitle))
174 | this.AttachToWindow(x_orTitle,y_orClient,width_orForeground)
175 | else
176 | this.SetPosition(x_orTitle,y_orClient)
177 |
178 |
179 | this.Clear()
180 |
181 | }
182 |
183 |
184 | ;####################################################################################################################################################################################################################################
185 | ;AttachToWindow
186 | ;
187 | ;title : Title of the window (or other type of identifier such as 'ahk_exe notepad.exe' etc..
188 | ;attachToClientArea : Whether or not to attach the overlay to the client area, window area is used otherwise
189 | ;foreground : Whether or not to only draw the overlay if attached window is active in the foreground, otherwise always draws
190 | ;setOwner : Sets the ownership of the overlay window to the target window
191 | ;
192 | ;return ; Returns 1 if either attached window is active in the foreground or no window is attached; 0 otherwise
193 | ;
194 | ;Notes ; Does not actually 'attach', but rather every BeginDraw() fuction will check to ensure it's
195 | ; updated to the attached windows position/size
196 | ; Could use SetParent but it introduces other issues, I'll explore further later
197 |
198 | AttachToWindow(title,AttachToClientArea:=0,foreground:=1,setOwner:=0) {
199 | if (title = "") {
200 | this.Err("AttachToWindow: Error","Expected title string, but empty variable was supplied!")
201 | return 0
202 | }
203 | if (!this.attachHWND := winexist(title)) {
204 | this.Err("AttachToWindow: Error","Could not find window - " title)
205 | return 0
206 | }
207 | numput(this.attachHwnd,this.tbufferptr,0,"UPtr")
208 | this.attachHWND := numget(this.tbufferptr,0,"Uptr")
209 | if (!DllCall("GetWindowRect","Uptr",this.attachHWND,"ptr",this.tBufferPtr)) {
210 | this.Err("AttachToWindow: Error","Problem getting window rect, is window minimized?`n`nError: " DllCall("GetLastError","uint"))
211 | return 0
212 | }
213 | x := NumGet(this.tBufferPtr,0,"int")
214 | y := NumGet(this.tBufferPtr,4,"int")
215 | w := NumGet(this.tBufferPtr,8,"int")-x
216 | h := NumGet(this.tBufferPtr,12,"int")-y
217 | this.attachClient := AttachToClientArea
218 | this.attachForeground := foreground
219 | this.AdjustWindow(x,y,w,h)
220 |
221 | VarSetCapacity(newSize,16)
222 | NumPut(this.width,newSize,0,"uint")
223 | NumPut(this.height,newSize,4,"uint")
224 | DllCall(this.vTable(this.renderTarget,58),"Ptr",this.renderTarget,"ptr",&newsize)
225 | this.SetPosition(x,y,this.width,this.height)
226 | if (setOwner) {
227 | this.alwaysontop := 0
228 | WinSet, AlwaysOnTop, off, % "ahk_id " this.hwnd
229 | this.owned := 1
230 | dllcall("SetWindowLongPtr","Uptr",this.hwnd,"int",-8,"Uptr",this.attachHWND)
231 | this.SetPosition(this.x,this.y)
232 | } else {
233 | this.owned := 0
234 | }
235 | }
236 |
237 |
238 | ;####################################################################################################################################################################################################################################
239 | ;BeginDraw
240 | ;
241 | ;return ; Returns 1 if either attached window is active in the foreground or no window is attached; 0 otherwise
242 | ;
243 | ;Notes ; Must always call EndDraw to finish drawing and update the overlay
244 |
245 |
246 |
247 | BeginDraw() {
248 | if (this.attachHWND) {
249 | if (!DllCall("GetWindowRect","Uptr",this.attachHWND,"ptr",this.tBufferPtr) or (this.attachForeground and DllCall("GetForegroundWindow","cdecl Ptr") != this.attachHWND)) {
250 | if (this.drawing) {
251 | if (this.callbacks["active"])
252 | this.callbacks["active"].call(this,0)
253 | this.Clear()
254 | this.drawing := 0
255 | if (this.HideOnStateChange)
256 | this.Display(0)
257 | }
258 | return 0
259 | } else if (!this.drawing) {
260 | if (this.HideOnStateChange)
261 | this.Display(1)
262 | }
263 | x := NumGet(this.tBufferPtr,0,"int")
264 | y := NumGet(this.tBufferPtr,4,"int")
265 | w := NumGet(this.tBufferPtr,8,"int")-x
266 | h := NumGet(this.tBufferPtr,12,"int")-y
267 | if ((w<<16)+h != this.lastSize) {
268 | this.AdjustWindow(x,y,w,h)
269 | VarSetCapacity(newSize,16,0)
270 | NumPut(this.width,newSize,0,"uint")
271 | NumPut(this.height,newSize,4,"uint")
272 | DllCall(this.vTable(this.renderTarget,58),"Ptr",this.renderTarget,"ptr",&newsize)
273 | this.SetPosition(x,y)
274 | if (this.callbacks["size"])
275 | this.callbacks["size"].call(this)
276 | } else if ((x<<16)+y != this.lastPos) {
277 | this.AdjustWindow(x,y,w,h)
278 | this.SetPosition(x,y)
279 | if (this.callbacks["position"])
280 | this.callbacks["position"].call(this)
281 | }
282 | if (!this.drawing and this.alwaysontop) {
283 | winset,alwaysontop,on,% "ahk_id " this.hwnd
284 | }
285 |
286 | } else {
287 | if (!DllCall("GetWindowRect","Uptr",this.hwnd,"ptr",this.tBufferPtr)) {
288 | if (this.drawing) {
289 | if (this.callbacks["active"])
290 | this.callbacks["active"].call(this,0)
291 | this.Clear()
292 | this.drawing := 0
293 | }
294 | return 0
295 | }
296 | x := NumGet(this.tBufferPtr,0,"int")
297 | y := NumGet(this.tBufferPtr,4,"int")
298 | w := NumGet(this.tBufferPtr,8,"int")-x
299 | h := NumGet(this.tBufferPtr,12,"int")-y
300 | if ((w<<16)+h != this.lastSize) {
301 | this.AdjustWindow(x,y,w,h)
302 | VarSetCapacity(newSize,16)
303 | NumPut(this.width,newSize,0,"uint")
304 | NumPut(this.height,newSize,4,"uint")
305 | DllCall(this.vTable(this.renderTarget,58),"Ptr",this.renderTarget,"ptr",&newsize)
306 | this.SetPosition(x,y)
307 | if (this.callbacks["size"])
308 | this.callbacks["size"].call(this)
309 | } else if ((x<<16)+y != this.lastPos) {
310 | this.AdjustWindow(x,y,w,h)
311 | this.SetPosition(x,y)
312 | if (this.callbacks["position"])
313 | this.callbacks["position"].call(this)
314 | }
315 | }
316 |
317 | DllCall(this._BeginDraw,"Ptr",this.renderTarget)
318 | DllCall(this._Clear,"Ptr",this.renderTarget,"Ptr",this.clrPtr)
319 | if (this.notifyActive) {
320 | if (this.callbacks["active"])
321 | this.callbacks["active"].call(this,1)
322 | this.notifyActive := 0
323 | }
324 | return this.drawing := 1
325 | }
326 |
327 |
328 |
329 | ;####################################################################################################################################################################################################################################
330 | ;EndDraw
331 | ;
332 | ;return ; Void
333 | ;
334 | ;Notes ; Must always call EndDraw to finish drawing and update the overlay
335 |
336 | EndDraw() {
337 | if (this.drawing)
338 | DllCall(this._EndDraw,"Ptr",this.renderTarget,"Ptr*",tag1,"Ptr*",tag2)
339 | }
340 |
341 |
342 | ;####################################################################################################################################################################################################################################
343 | ;DrawImage
344 | ;
345 | ;dstX : X position to draw to
346 | ;dstY : Y position to draw to
347 | ;dstW : Width of image to draw to
348 | ;dstH : Height of image to draw to
349 | ;srcX : X position to draw from
350 | ;srcY : Y position to draw from
351 | ;srcW : Width of image to draw from
352 | ;srcH : Height of image to draw from
353 | ;alpha : Image transparency, float between 0 and 1
354 | ;drawCentered : Draw the image centered on dstX/dstY, otherwise dstX/dstY will be the top left of the image
355 | ;rotation : Image rotation in degrees (0-360)
356 | ;rotationOffsetX : X offset to base rotations on (defaults to center x)
357 | ;rotationOffsetY : Y offset to base rotations on (defaults to center y)
358 | ;
359 | ;return ; Void
360 |
361 | DrawImage(image,dstX,dstY,dstW:=0,dstH:=0,srcX:=0,srcY:=0,srcW:=0,srcH:=0,alpha:=1,drawCentered:=0,rotation:=0,rotOffX:=0,rotOffY:=0) {
362 | if (!i := this.imageCache[image]) {
363 | i := this.cacheImage(image)
364 | }
365 | if (dstW <= 0)
366 | dstW := i.w
367 | if (dstH <= 0)
368 | dstH := i.h
369 | x := dstX-(drawCentered?dstW/2:0)
370 | y := dstY-(drawCentered?dstH/2:0)
371 | NumPut(x,this.rect1Ptr,0,"float")
372 | NumPut(y,this.rect1Ptr,4,"float")
373 | NumPut(x + dstW,this.rect1Ptr,8,"float")
374 | NumPut(y + dstH,this.rect1Ptr,12,"float")
375 | NumPut(srcX,this.rect2Ptr,0,"float")
376 | NumPut(srcY,this.rect2Ptr,4,"float")
377 | NumPut(srcX + (srcW=0?i.w:srcW),this.rect2Ptr,8,"float")
378 | NumPut(srcY + (srcH=0?i.h:srcH),this.rect2Ptr,12,"float")
379 |
380 | if (rotation != 0) {
381 | if (this.bits) {
382 | if (rotOffX or rotOffY) {
383 | NumPut(dstX+rotOffX,this.tBufferPtr,0,"float")
384 | NumPut(dstY+rotOffY,this.tBufferPtr,4,"float")
385 | } else {
386 | NumPut(dstX+(drawCentered?0:dstW/2),this.tBufferPtr,0,"float")
387 | NumPut(dstY+(drawCentered?0:dstH/2),this.tBufferPtr,4,"float")
388 | }
389 | DllCall("d2d1\D2D1MakeRotateMatrix","float",rotation,"double",NumGet(this.tBufferPtr,"double"),"ptr",this.matrixPtr)
390 | } else {
391 | DllCall("d2d1\D2D1MakeRotateMatrix","float",rotation,"float",dstX+(drawCentered?0:dstW/2),"float",dstY+(drawCentered?0:dstH/2),"ptr",this.matrixPtr)
392 | }
393 | DllCall(this._RMatrix,"ptr",this.renderTarget,"ptr",this.matrixPtr)
394 | DllCall(this._DrawImage,"ptr",this.renderTarget,"ptr",i.p,"ptr",this.rect1Ptr,"float",alpha,"uint",this.interpolationMode,"ptr",this.rect2Ptr)
395 | this.SetIdentity()
396 | DllCall(this._RMatrix,"ptr",this.renderTarget,"ptr",this.matrixPtr)
397 | } else {
398 | DllCall(this._DrawImage,"ptr",this.renderTarget,"ptr",i.p,"ptr",this.rect1Ptr,"float",alpha,"uint",this.interpolationMode,"ptr",this.rect2Ptr)
399 | }
400 | }
401 |
402 |
403 | ;####################################################################################################################################################################################################################################
404 | ;GetTextMetrics
405 | ;
406 | ;text : The text to get the metrics of
407 | ;size : Font size to measure with
408 | ;fontName : Name of the font to use
409 | ;maxWidth : Max width (smaller width may cause wrapping)
410 | ;maxHeight : Max Height
411 | ;
412 | ;return ; An array containing width, height and line count of the string
413 | ;
414 | ;Notes ; Used to measure a string before drawing it
415 |
416 | GetTextMetrics(text,size,fontName,bold:=0,maxWidth:=5000,maxHeight:=5000) {
417 | local
418 | bold := (bold ? "700" : "400")
419 | if (!p := this.fonts[fontName size bold]) {
420 | p := this.CacheFont(fontName,size,bold)
421 | }
422 | varsetcapacity(bf,64)
423 | DllCall(this.vTable(this.wFactory,18),"ptr",this.wFactory,"WStr",text,"uint",strlen(text),"Ptr",p,"float",maxWidth,"float",maxHeight,"Ptr*",layout)
424 | DllCall(this.vTable(layout,60),"ptr",layout,"ptr",&bf,"uint")
425 |
426 | w := numget(bf,8,"float")
427 | wTrailing := numget(bf,12,"float")
428 | h := numget(bf,16,"float")
429 |
430 | DllCall(this.vTable(layout,2),"ptr",layout)
431 |
432 | return {w:w,width:w,h:h,height:h,wt:wTrailing,widthTrailing:w,lines:numget(bf,32,"uint")}
433 |
434 | }
435 |
436 |
437 | ;####################################################################################################################################################################################################################################
438 | ;SetTextRenderParams
439 | ;
440 | ;gamma : Gamma value ................. (1 > 256)
441 | ;contrast : Contrast value .............. (0.0 > 1.0)
442 | ;clearType : Clear type level ............ (0.0 > 1.0)
443 | ;pixelGeom :
444 | ; 0 - DWRITE_PIXEL_GEOMETRY_FLAT
445 | ; 1 - DWRITE_PIXEL_GEOMETRY_RGB
446 | ; 2 - DWRITE_PIXEL_GEOMETRY_BGR
447 | ;
448 | ;renderMode :
449 | ; 0 - DWRITE_RENDERING_MODE_DEFAULT
450 | ; 1 - DWRITE_RENDERING_MODE_ALIASED
451 | ; 2 - DWRITE_RENDERING_MODE_GDI_CLASSIC
452 | ; 3 - DWRITE_RENDERING_MODE_GDI_NATURAL
453 | ; 4 - DWRITE_RENDERING_MODE_NATURAL
454 | ; 5 - DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
455 | ; 6 - DWRITE_RENDERING_MODE_OUTLINE
456 | ; 7 - DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC
457 | ; 8 - DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
458 | ; 9 - DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
459 | ; 10 - DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
460 | ;
461 | ;return ; Void
462 | ;
463 | ;Notes ; Used to affect how text is rendered
464 |
465 | SetTextRenderParams(gamma:=1,contrast:=0,cleartype:=1,pixelGeom:=0,renderMode:=0) {
466 | local
467 | DllCall(this.vTable(this.wFactory,12),"ptr",this.wFactory,"Float",gamma,"Float",contrast,"Float",cleartype,"Uint",pixelGeom,"Uint",renderMode,"Ptr*",params) "`n" params
468 | DllCall(this.vTable(this.renderTarget,36),"Ptr",this.renderTarget,"Ptr",params)
469 | }
470 |
471 |
472 |
473 |
474 | ;####################################################################################################################################################################################################################################
475 | ;DrawText
476 | ;
477 | ;text : The text to be drawn
478 | ;x : X position
479 | ;y : Y position
480 | ;size : Size of font
481 | ;color : Color of font
482 | ;fontName : Font name (must be installed)
483 | ;extraOptions : Additonal options which may contain any of the following seperated by spaces:
484 | ; Width ............. w[number] : Example > w200 (Default: this.width)
485 | ; Height ............ h[number] : Example > h200 (Default: this.height)
486 | ; Alignment ......... a[Left/Right/Center] : Example > aCenter (Default: Left)
487 | ; DropShadow ........ ds[hex color] : Example > dsFF000000 (Default: DISABLED)
488 | ; DropShadowXOffset . dsx[number] : Example > dsx2 (Default: 1)
489 | ; DropShadowYOffset . dsy[number] : Example > dsy2 (Default: 1)
490 | ; Outline ........... ol[hex color] : Example > olFF000000 (Default: DISABLED)
491 | ;
492 | ;return ; Void
493 |
494 | DrawText(text,x,y,size:=18,color:=0xFFFFFFFF,fontName:="Arial",extraOptions:="") {
495 | local
496 | if (!RegExMatch(extraOptions,"w([\d\.]+)",w))
497 | w1 := this.width
498 | if (!RegExMatch(extraOptions,"h([\d\.]+)",h))
499 | h1 := this.height
500 | bold := (RegExMatch(extraOptions,"bold") ? 700 : 400)
501 |
502 | if (!p := this.fonts[fontName size bold]) {
503 | p := this.CacheFont(fontName,size,bold)
504 | }
505 |
506 | DllCall(this.vTable(p,3),"ptr",p,"uint",(InStr(extraOptions,"aRight") ? 1 : InStr(extraOptions,"aCenter") ? 2 : 0))
507 |
508 | if (RegExMatch(extraOptions,"ds([a-fA-F\d]+)",ds)) {
509 | if (!RegExMatch(extraOptions,"dsx([\d\.]+)",dsx))
510 | dsx1 := 1
511 | if (!RegExMatch(extraOptions,"dsy([\d\.]+)",dsy))
512 | dsy1 := 1
513 | this.DrawTextShadow(p,text,x+dsx1,y+dsy1,w1,h1,"0x" ds1)
514 | } else if (RegExMatch(extraOptions,"ol(\w{8})",ol)) {
515 | this.DrawTextOutline(p,text,x,y,w1,h1,"0x" ol1)
516 | }
517 |
518 | this.SetBrushColor(color)
519 | NumPut(x,this.tBufferPtr,0,"float")
520 | NumPut(y,this.tBufferPtr,4,"float")
521 | NumPut(x+w1,this.tBufferPtr,8,"float")
522 | NumPut(y+h1,this.tBufferPtr,12,"float")
523 |
524 | DllCall(this._DrawText,"ptr",this.renderTarget,"wstr",text,"uint",strlen(text),"ptr",p,"ptr",this.tBufferPtr,"ptr",this.brush,"uint",0,"uint",0)
525 | }
526 |
527 | DrawTextExt(text,x,y,size:=18,color:=0xFFFFFFFF,fontName:="Arial",extraOptions:="") {
528 | local
529 | if (!RegExMatch(extraOptions,"w([\d\.]+)",w))
530 | w1 := this.width
531 | if (!RegExMatch(extraOptions,"h([\d\.]+)",h))
532 | h1 := this.height
533 | bold := (RegExMatch(extraOptions,"i)bold") ? 700 : 400)
534 |
535 | if (!p := this.fonts[fontName size bold]) {
536 | p := this.CacheFont(fontName,size,bold)
537 | }
538 |
539 | DllCall(this.vTable(p,3),"ptr",p,"uint",(InStr(extraOptions,"aRight") ? 1 : InStr(extraOptions,"aCenter") ? 2 : 0))
540 |
541 | if (RegExMatch(extraOptions,"ds([a-fA-F\d]+)",ds)) {
542 | if (!RegExMatch(extraOptions,"dsx([\d\.]+)",dsx))
543 | dsx1 := 1
544 | if (!RegExMatch(extraOptions,"dsy([\d\.]+)",dsy))
545 | dsy1 := 1
546 | this.DrawTextShadow(p,text,x+dsx1,y+dsy1,w1,h1,"0x" ds1)
547 | } else if (RegExMatch(extraOptions,"ol(\w{8})",ol)) {
548 | this.DrawTextOutline(p,text,x,y,w1,h1,"0x" ol1)
549 | }
550 | if (InStr(text,"|c")) {
551 | varsetcapacity(res,512,0)
552 | varsetcapacity(_dat,(strlen(text)+1)*4,0)
553 | strput(text,&_dat,"utf-8")
554 | if (t := dllcall(this._dtc,"ptr",&_dat,"ptr",&res)) {
555 | loop % t {
556 | i := ((a_index-1)*12)
557 | s := numget(res,i,"int"),
558 | if (e := numget(res,i+4,"int")) {
559 | str := substr(text,s,e)
560 | this.SetBrushColor(color)
561 | NumPut(x,this.tBufferPtr,0,"float"),NumPut(y,this.tBufferPtr,4,"float")
562 | NumPut(x+w1,this.tBufferPtr,8,"float"),NumPut(y+h1,this.tBufferPtr,12,"float")
563 | DllCall(this._DrawText,"ptr",this.renderTarget,"wstr",str,"uint",strlen(str),"ptr",p,"ptr",this.tBufferPtr,"ptr",this.brush,"uint",0,"uint",0)
564 | mets := this.GetTextMetrics(str,size,fontName)
565 | x+=mets.wt
566 | }
567 | color := numget(res,i+8,"uint")
568 | }
569 | str := substr(text,s+e+10)
570 | this.SetBrushColor(color)
571 | NumPut(x,this.tBufferPtr,0,"float"),NumPut(y,this.tBufferPtr,4,"float")
572 | NumPut(x+w1,this.tBufferPtr,8,"float"),NumPut(y+h1,this.tBufferPtr,12,"float")
573 | DllCall(this._DrawText,"ptr",this.renderTarget,"wstr",str,"uint",strlen(str),"ptr",p,"ptr",this.tBufferPtr,"ptr",this.brush,"uint",0,"uint",0)
574 | } else {
575 | this.SetBrushColor(color)
576 | NumPut(x,this.tBufferPtr,0,"float"),NumPut(y,this.tBufferPtr,4,"float")
577 | NumPut(x+w1,this.tBufferPtr,8,"float"),NumPut(y+h1,this.tBufferPtr,12,"float")
578 | DllCall(this._DrawText,"ptr",this.renderTarget,"wstr",text,"uint",strlen(text),"ptr",p,"ptr",this.tBufferPtr,"ptr",this.brush,"uint",0,"uint",0)
579 | }
580 | } else {
581 | this.SetBrushColor(color)
582 | NumPut(x,this.tBufferPtr,0,"float"),NumPut(y,this.tBufferPtr,4,"float")
583 | NumPut(x+w1,this.tBufferPtr,8,"float"),NumPut(y+h1,this.tBufferPtr,12,"float")
584 | DllCall(this._DrawText,"ptr",this.renderTarget,"wstr",text,"uint",strlen(text),"ptr",p,"ptr",this.tBufferPtr,"ptr",this.brush,"uint",0,"uint",0)
585 | }
586 | }
587 |
588 |
589 |
590 | ;####################################################################################################################################################################################################################################
591 | ;DrawEllipse
592 | ;
593 | ;x : X position
594 | ;y : Y position
595 | ;w : Width of ellipse
596 | ;h : Height of ellipse
597 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
598 | ;thickness : Thickness of the line
599 | ;
600 | ;return ; Void
601 |
602 | DrawEllipse(x, y, w, h, color, thickness:=1) {
603 | this.SetBrushColor(color)
604 | NumPut(x,this.tBufferPtr,0,"float")
605 | NumPut(y,this.tBufferPtr,4,"float")
606 | NumPut(w,this.tBufferPtr,8,"float")
607 | NumPut(h,this.tBufferPtr,12,"float")
608 | DllCall(this._DrawEllipse,"Ptr",this.renderTarget,"Ptr",this.tBufferPtr,"ptr",this.brush,"float",thickness,"ptr",this.stroke)
609 | }
610 |
611 |
612 | ;####################################################################################################################################################################################################################################
613 | ;FillEllipse
614 | ;
615 | ;x : X position
616 | ;y : Y position
617 | ;w : Width of ellipse
618 | ;h : Height of ellipse
619 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
620 | ;
621 | ;return ; Void
622 |
623 | FillEllipse(x, y, w, h, color) {
624 | this.SetBrushColor(color)
625 | NumPut(x,this.tBufferPtr,0,"float")
626 | NumPut(y,this.tBufferPtr,4,"float")
627 | NumPut(w,this.tBufferPtr,8,"float")
628 | NumPut(h,this.tBufferPtr,12,"float")
629 | DllCall(this._FillEllipse,"Ptr",this.renderTarget,"Ptr",this.tBufferPtr,"ptr",this.brush)
630 | }
631 |
632 |
633 | ;####################################################################################################################################################################################################################################
634 | ;DrawCircle
635 | ;
636 | ;x : X position
637 | ;y : Y position
638 | ;radius : Radius of circle
639 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
640 | ;thickness : Thickness of the line
641 | ;
642 | ;return ; Void
643 |
644 | DrawCircle(x, y, radius, color, thickness:=1) {
645 | this.SetBrushColor(color)
646 | NumPut(x,this.tBufferPtr,0,"float")
647 | NumPut(y,this.tBufferPtr,4,"float")
648 | NumPut(radius,this.tBufferPtr,8,"float")
649 | NumPut(radius,this.tBufferPtr,12,"float")
650 | DllCall(this._DrawEllipse,"Ptr",this.renderTarget,"Ptr",this.tBufferPtr,"ptr",this.brush,"float",thickness,"ptr",this.stroke)
651 | }
652 |
653 |
654 | ;####################################################################################################################################################################################################################################
655 | ;FillCircle
656 | ;
657 | ;x : X position
658 | ;y : Y position
659 | ;radius : Radius of circle
660 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
661 | ;
662 | ;return ; Void
663 |
664 | FillCircle(x, y, radius, color) {
665 | this.SetBrushColor(color)
666 | NumPut(x,this.tBufferPtr,0,"float")
667 | NumPut(y,this.tBufferPtr,4,"float")
668 | NumPut(radius,this.tBufferPtr,8,"float")
669 | NumPut(radius,this.tBufferPtr,12,"float")
670 | DllCall(this._FillEllipse,"Ptr",this.renderTarget,"Ptr",this.tBufferPtr,"ptr",this.brush)
671 | }
672 |
673 |
674 | ;####################################################################################################################################################################################################################################
675 | ;DrawRectangle
676 | ;
677 | ;x : X position
678 | ;y : Y position
679 | ;w : Width of rectangle
680 | ;h : Height of rectangle
681 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
682 | ;thickness : Thickness of the line
683 | ;
684 | ;return ; Void
685 |
686 | DrawRectangle(x, y, w, h, color, thickness:=1) {
687 | this.SetBrushColor(color)
688 | NumPut(x,this.tBufferPtr,0,"float")
689 | NumPut(y,this.tBufferPtr,4,"float")
690 | NumPut(x+w,this.tBufferPtr,8,"float")
691 | NumPut(y+h,this.tBufferPtr,12,"float")
692 | DllCall(this._DrawRectangle,"Ptr",this.renderTarget,"Ptr",this.tBufferPtr,"ptr",this.brush,"float",thickness,"ptr",this.stroke)
693 | }
694 |
695 |
696 | ;####################################################################################################################################################################################################################################
697 | ;FillRectangle
698 | ;
699 | ;x : X position
700 | ;y : Y position
701 | ;w : Width of rectangle
702 | ;h : Height of rectangle
703 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
704 | ;
705 | ;return ; Void
706 |
707 | FillRectangle(x, y, w, h, color) {
708 | this.SetBrushColor(color)
709 | NumPut(x,this.tBufferPtr,0,"float")
710 | NumPut(y,this.tBufferPtr,4,"float")
711 | NumPut(x+w,this.tBufferPtr,8,"float")
712 | NumPut(y+h,this.tBufferPtr,12,"float")
713 | DllCall(this._FillRectangle,"Ptr",this.renderTarget,"Ptr",this.tBufferPtr,"ptr",this.brush)
714 | }
715 |
716 |
717 | ;####################################################################################################################################################################################################################################
718 | ;DrawRoundedRectangle
719 | ;
720 | ;x : X position
721 | ;y : Y position
722 | ;w : Width of rectangle
723 | ;h : Height of rectangle
724 | ;radiusX : The x-radius for the quarter ellipse that is drawn to replace every corner of the rectangle.
725 | ;radiusY : The y-radius for the quarter ellipse that is drawn to replace every corner of the rectangle.
726 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
727 | ;thickness : Thickness of the line
728 | ;
729 | ;return ; Void
730 |
731 | DrawRoundedRectangle(x, y, w, h, radiusX, radiusY, color, thickness:=1) {
732 | this.SetBrushColor(color)
733 | NumPut(x,this.tBufferPtr,0,"float")
734 | NumPut(y,this.tBufferPtr,4,"float")
735 | NumPut(x+w,this.tBufferPtr,8,"float")
736 | NumPut(y+h,this.tBufferPtr,12,"float")
737 | NumPut(radiusX,this.tBufferPtr,16,"float")
738 | NumPut(radiusY,this.tBufferPtr,20,"float")
739 | DllCall(this._DrawRoundedRectangle,"Ptr",this.renderTarget,"Ptr",this.tBufferPtr,"ptr",this.brush,"float",thickness,"ptr",this.stroke)
740 | }
741 |
742 |
743 | ;####################################################################################################################################################################################################################################
744 | ;FillRectangle
745 | ;
746 | ;x : X position
747 | ;y : Y position
748 | ;w : Width of rectangle
749 | ;h : Height of rectangle
750 | ;radiusX : The x-radius for the quarter ellipse that is drawn to replace every corner of the rectangle.
751 | ;radiusY : The y-radius for the quarter ellipse that is drawn to replace every corner of the rectangle.
752 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
753 | ;
754 | ;return ; Void
755 |
756 | FillRoundedRectangle(x, y, w, h, radiusX, radiusY, color) {
757 | this.SetBrushColor(color)
758 | NumPut(x,this.tBufferPtr,0,"float")
759 | NumPut(y,this.tBufferPtr,4,"float")
760 | NumPut(x+w,this.tBufferPtr,8,"float")
761 | NumPut(y+h,this.tBufferPtr,12,"float")
762 | NumPut(radiusX,this.tBufferPtr,16,"float")
763 | NumPut(radiusY,this.tBufferPtr,20,"float")
764 | DllCall(this._FillRoundedRectangle,"Ptr",this.renderTarget,"Ptr",this.tBufferPtr,"ptr",this.brush)
765 | }
766 |
767 |
768 | ;####################################################################################################################################################################################################################################
769 | ;DrawLine
770 | ;
771 | ;x1 : X position for line start
772 | ;y1 : Y position for line start
773 | ;x2 : X position for line end
774 | ;y2 : Y position for line end
775 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
776 | ;thickness : Thickness of the line
777 | ;
778 | ;return ; Void
779 |
780 | DrawLine(x1,y1,x2,y2,color:=0xFFFFFFFF,thickness:=1,rounded:=0) {
781 | this.SetBrushColor(color)
782 | if (this.bits) {
783 | NumPut(x1,this.tBufferPtr,0,"float") ;Special thanks to teadrinker for helping me
784 | NumPut(y1,this.tBufferPtr,4,"float") ;with these params!
785 | NumPut(x2,this.tBufferPtr,8,"float")
786 | NumPut(y2,this.tBufferPtr,12,"float")
787 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"Double",NumGet(this.tBufferPtr,0,"double"),"Double",NumGet(this.tBufferPtr,8,"double"),"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
788 | } else {
789 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"float",x1,"float",y1,"float",x2,"float",y2,"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
790 | }
791 |
792 | }
793 |
794 |
795 | ;####################################################################################################################################################################################################################################
796 | ;DrawLines
797 | ;
798 | ;lines : An array of 2d points, example: [[0,0],[5,0],[0,5]]
799 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
800 | ;connect : If 1 then connect the start and end together
801 | ;thickness : Thickness of the line
802 | ;
803 | ;return ; 1 on success; 0 otherwise
804 |
805 | DrawLines(points,color,connect:=0,thickness:=1,rounded:=0) {
806 | if (points.length() < 2)
807 | return 0
808 | lx := sx := points[1][1]
809 | ly := sy := points[1][2]
810 | this.SetBrushColor(color)
811 | if (this.bits) {
812 | loop % points.length()-1 {
813 | NumPut(lx,this.tBufferPtr,0,"float"), NumPut(ly,this.tBufferPtr,4,"float"), NumPut(lx:=points[a_index+1][1],this.tBufferPtr,8,"float"), NumPut(ly:=points[a_index+1][2],this.tBufferPtr,12,"float")
814 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"Double",NumGet(this.tBufferPtr,0,"double"),"Double",NumGet(this.tBufferPtr,8,"double"),"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
815 | }
816 | if (connect) {
817 | NumPut(sx,this.tBufferPtr,0,"float"), NumPut(sy,this.tBufferPtr,4,"float"), NumPut(lx,this.tBufferPtr,8,"float"), NumPut(ly,this.tBufferPtr,12,"float")
818 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"Double",NumGet(this.tBufferPtr,0,"double"),"Double",NumGet(this.tBufferPtr,8,"double"),"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
819 | }
820 | } else {
821 | loop % points.length()-1 {
822 | x1 := lx
823 | y1 := ly
824 | x2 := lx := points[a_index+1][1]
825 | y2 := ly := points[a_index+1][2]
826 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"float",x1,"float",y1,"float",x2,"float",y2,"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
827 | }
828 | if (connect)
829 | DllCall(this._DrawLine,"Ptr",this.renderTarget,"float",sx,"float",sy,"float",lx,"float",ly,"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke))
830 | }
831 | return 1
832 | }
833 |
834 |
835 | ;####################################################################################################################################################################################################################################
836 | ;DrawPolygon
837 | ;
838 | ;points : An array of 2d points, example: [[0,0],[5,0],[0,5]]
839 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
840 | ;thickness : Thickness of the line
841 | ;xOffset : X offset to draw the polygon array
842 | ;yOffset : Y offset to draw the polygon array
843 | ;
844 | ;return ; 1 on success; 0 otherwise
845 |
846 | DrawPolygon(points,color,thickness:=1,rounded:=0,xOffset:=0,yOffset:=0) {
847 | if (points.length() < 3)
848 | return 0
849 |
850 | if (DllCall(this.vTable(this.factory,10),"Ptr",this.factory,"Ptr*",pGeom) = 0) {
851 | if (DllCall(this.vTable(pGeom,17),"Ptr",pGeom,"ptr*",sink) = 0) {
852 | this.SetBrushColor(color)
853 | if (this.bits) {
854 | numput(points[1][1]+xOffset,this.tBufferPtr,0,"float")
855 | numput(points[1][2]+yOffset,this.tBufferPtr,4,"float")
856 | DllCall(this.vTable(sink,5),"ptr",sink,"double",numget(this.tBufferPtr,0,"double"),"uint",1)
857 | loop % points.length()-1
858 | {
859 | numput(points[a_index+1][1]+xOffset,this.tBufferPtr,0,"float")
860 | numput(points[a_index+1][2]+yOffset,this.tBufferPtr,4,"float")
861 | DllCall(this.vTable(sink,10),"ptr",sink,"double",numget(this.tBufferPtr,0,"double"))
862 | }
863 | DllCall(this.vTable(sink,8),"ptr",sink,"uint",1)
864 | DllCall(this.vTable(sink,9),"ptr",sink)
865 | } else {
866 | DllCall(this.vTable(sink,5),"ptr",sink,"float",points[1][1]+xOffset,"float",points[1][2]+yOffset,"uint",1)
867 | loop % points.length()-1
868 | DllCall(this.vTable(sink,10),"ptr",sink,"float",points[a_index+1][1]+xOffset,"float",points[a_index+1][2]+yOffset)
869 | DllCall(this.vTable(sink,8),"ptr",sink,"uint",1)
870 | DllCall(this.vTable(sink,9),"ptr",sink)
871 | }
872 |
873 | if (DllCall(this.vTable(this.renderTarget,22),"Ptr",this.renderTarget,"Ptr",pGeom,"ptr",this.brush,"float",thickness,"ptr",(rounded?this.strokeRounded:this.stroke)) = 0) {
874 | DllCall(this.vTable(sink,2),"ptr",sink)
875 | DllCall(this.vTable(pGeom,2),"Ptr",pGeom)
876 | return 1
877 | }
878 | DllCall(this.vTable(sink,2),"ptr",sink)
879 | DllCall(this.vTable(pGeom,2),"Ptr",pGeom)
880 | }
881 | }
882 |
883 |
884 | return 0
885 | }
886 |
887 |
888 | ;####################################################################################################################################################################################################################################
889 | ;FillPolygon
890 | ;
891 | ;points : An array of 2d points, example: [[0,0],[5,0],[0,5]]
892 | ;color : Color in 0xAARRGGBB or 0xRRGGBB format (if 0xRRGGBB then alpha is set to FF (255))
893 | ;xOffset : X offset to draw the filled polygon array
894 | ;yOffset : Y offset to draw the filled polygon array
895 | ;
896 | ;return ; 1 on success; 0 otherwise
897 |
898 | FillPolygon(points,color,xoffset:=0,yoffset:=0) {
899 | if (points.length() < 3)
900 | return 0
901 |
902 | if (DllCall(this.vTable(this.factory,10),"Ptr",this.factory,"Ptr*",pGeom) = 0) {
903 | if (DllCall(this.vTable(pGeom,17),"Ptr",pGeom,"ptr*",sink) = 0) {
904 | this.SetBrushColor(color)
905 | if (this.bits) {
906 | numput(points[1][1]+xoffset,this.tBufferPtr,0,"float")
907 | numput(points[1][2]+yoffset,this.tBufferPtr,4,"float")
908 | DllCall(this.vTable(sink,5),"ptr",sink,"double",numget(this.tBufferPtr,0,"double"),"uint",0)
909 | loop % points.length()-1
910 | {
911 | numput(points[a_index+1][1]+xoffset,this.tBufferPtr,0,"float")
912 | numput(points[a_index+1][2]+yoffset,this.tBufferPtr,4,"float")
913 | DllCall(this.vTable(sink,10),"ptr",sink,"double",numget(this.tBufferPtr,0,"double"))
914 | }
915 | DllCall(this.vTable(sink,8),"ptr",sink,"uint",1)
916 | DllCall(this.vTable(sink,9),"ptr",sink)
917 | } else {
918 | DllCall(this.vTable(sink,5),"ptr",sink,"float",points[1][1]+xoffset,"float",points[1][2]+yoffset,"uint",0)
919 | loop % points.length()-1
920 | DllCall(this.vTable(sink,10),"ptr",sink,"float",points[a_index+1][1]+xoffset,"float",points[a_index+1][2]+yoffset)
921 | DllCall(this.vTable(sink,8),"ptr",sink,"uint",1)
922 | DllCall(this.vTable(sink,9),"ptr",sink)
923 | }
924 |
925 | if (DllCall(this.vTable(this.renderTarget,23),"Ptr",this.renderTarget,"Ptr",pGeom,"ptr",this.brush,"ptr",0) = 0) {
926 | DllCall(this.vTable(sink,2),"ptr",sink)
927 | DllCall(this.vTable(pGeom,2),"Ptr",pGeom)
928 | return 1
929 | }
930 | DllCall(this.vTable(sink,2),"ptr",sink)
931 | DllCall(this.vTable(pGeom,2),"Ptr",pGeom)
932 |
933 | }
934 | }
935 |
936 |
937 | return 0
938 | }
939 |
940 |
941 | ;####################################################################################################################################################################################################################################
942 | ;SetPosition
943 | ;
944 | ;x : X position to move the window to (screen space)
945 | ;y : Y position to move the window to (screen space)
946 | ;w : New Width (only applies when not attached)
947 | ;h : New Height (only applies when not attached)
948 | ;
949 | ;return ; Void
950 | ;
951 | ;notes : Only used when not attached to a window
952 |
953 | SetPosition(x,y,w:=0,h:=0) {
954 | this.x := x
955 | this.y := y
956 | if (!this.attachHWND and w != 0 and h != 0) {
957 | VarSetCapacity(newSize,16)
958 | NumPut(this.width := w,newSize,0,"uint")
959 | NumPut(this.height := h,newSize,4,"uint")
960 | DllCall(this._NRSize,"Ptr",this.renderTarget,"ptr",&newsize)
961 | }
962 | DllCall("MoveWindow","Uptr",this.hwnd,"int",x,"int",y,"int",this.width,"int",this.height,"char",1)
963 | }
964 |
965 |
966 | ;####################################################################################################################################################################################################################################
967 | ;GetImageDimensions
968 | ;
969 | ;image : Image file name
970 | ;&w : Width of image
971 | ;&h : Height of image
972 | ;
973 | ;return ; Void
974 |
975 | GetImageDimensions(image,byref w, byref h) {
976 | if (!i := this.imageCache[image]) {
977 | i := this.cacheImage(image)
978 | }
979 | w := i.w
980 | h := i.h
981 | }
982 |
983 |
984 | ;####################################################################################################################################################################################################################################
985 | ;GetMousePos
986 | ;
987 | ;&x : X position of mouse to return
988 | ;&y : Y position of mouse to return
989 | ;realRegionOnly : Return 1 only if in the real region, which does not include the invisible borders, (client area does not have borders)
990 | ;
991 | ;return ; Returns 1 if mouse within window/client region; 0 otherwise
992 |
993 | GetMousePos(byref x, byref y, realRegionOnly:=0) {
994 | DllCall("GetCursorPos","ptr",this.tBufferPtr)
995 | x := NumGet(this.tBufferPtr,0,"int")
996 | y := NumGet(this.tBufferPtr,4,"int")
997 | if (!realRegionOnly) {
998 | inside := (x >= this.x and y >= this.y and x <= this.x2 and y <= this.y2)
999 | x += this.offX
1000 | y += this.offY
1001 | return inside
1002 | }
1003 | x += this.offX
1004 | y += this.offY
1005 | return (x >= this.realX and y >= this.realY and x <= this.realX2 and y <= this.realY2)
1006 |
1007 | }
1008 |
1009 |
1010 | ;####################################################################################################################################################################################################################################
1011 | ;Clear
1012 | ;
1013 | ;notes : Clears the overlay, essentially the same as running BeginDraw followed by EndDraw
1014 |
1015 | Clear() {
1016 | DllCall(this._BeginDraw,"Ptr",this.renderTarget)
1017 | DllCall(this._Clear,"Ptr",this.renderTarget,"Ptr",this.clrPtr)
1018 | DllCall(this._EndDraw,"Ptr",this.renderTarget,"Ptr*",tag1,"Ptr*",tag2)
1019 | }
1020 |
1021 |
1022 | ;####################################################################################################################################################################################################################################
1023 | ;RegCallback
1024 | ;
1025 | ;&func : Function object to call
1026 | ;&callback : Name of the callback to assign the function to
1027 | ;
1028 | ;notes : Example: overlay.RegCallback(Func("funcName"),"Size"); See top for param info
1029 |
1030 | RegCallback(func,callback) {
1031 | if (this.callbacks.haskey(callback))
1032 | this.callbacks[callback] := func
1033 | }
1034 |
1035 |
1036 | ;####################################################################################################################################################################################################################################
1037 | ;ClearCallback
1038 | ;
1039 | ;&callback : Name of the callback to clear functions of
1040 | ;
1041 | ;notes : Clears callback
1042 |
1043 | ClearCallback(callback) {
1044 | if (this.callbacks.haskey(callback))
1045 | this.callbacks[callback] := 0
1046 | }
1047 |
1048 | PushLayerRectangle(x,y,w,h) {
1049 | VarSetCapacity(info,64,0)
1050 | NumPut(x,info,0,"float")
1051 | NumPut(y,info,4,"float")
1052 | Numput(x+w,info,8,"float")
1053 | NumPut(y+h,info,12,"float")
1054 | if (DllCall(this.vTable(this.factory,5),"Ptr",this.factory,"Ptr",&info,"Ptr*",pGeom) = 0) {
1055 | NumPut(0xFF800000,info,0,"Uint")
1056 | NumPut(0xFF800000,info,4,"Uint")
1057 | Numput(0x7F800000,info,8,"Uint")
1058 | NumPut(0x7F800000,info,12,"Uint")
1059 | NumPut(pGeom,info,16,"Ptr"), i := 16 + a_ptrsize
1060 | NumPut(0,info,i,"Uint")
1061 | NumPut(1,info,i+4,"float")
1062 | NumPut(1,info,i+16,"float")
1063 | NumPut(1,info,i+28,"float")
1064 | DllCall(this.vTable(this.renderTarget,40),"Ptr",this.renderTarget, "Ptr", &info, "ptr", 0)
1065 | DllCall(this.vTable(pGeom,2),"Ptr",pGeom)
1066 | }
1067 | }
1068 | PushLayerEllipse(x,y,w,h) {
1069 | VarSetCapacity(info,64,0)
1070 | NumPut(x,info,0,"float")
1071 | NumPut(y,info,4,"float")
1072 | Numput(w,info,8,"float")
1073 | NumPut(h,info,12,"float")
1074 | if (DllCall(this.vTable(this.factory,7),"Ptr",this.factory,"Ptr",&info,"Ptr*",pGeom) = 0) {
1075 | NumPut(0xFF800000,info,0,"Uint")
1076 | NumPut(0xFF800000,info,4,"Uint")
1077 | Numput(0x7F800000,info,8,"Uint")
1078 | NumPut(0x7F800000,info,12,"Uint")
1079 | NumPut(pGeom,info,16,"Ptr"), i := 16 + a_ptrsize
1080 | NumPut(0,info,i,"Uint")
1081 | NumPut(1,info,i+4,"float")
1082 | NumPut(1,info,i+16,"float")
1083 | NumPut(1,info,i+28,"float")
1084 | DllCall(this.vTable(this.renderTarget,40),"Ptr",this.renderTarget, "Ptr", &info, "ptr", 0)
1085 | DllCall(this.vTable(pGeom,2),"Ptr",pGeom)
1086 | }
1087 | }
1088 | PopLayer() {
1089 | DllCall(this.vTable(this.renderTarget,41),"Ptr",this.renderTarget)
1090 | }
1091 |
1092 | ;0 = off
1093 | ;1 = on
1094 | SetAntialias(state:=0) {
1095 | DllCall(this.vTable(this.renderTarget,32),"Ptr",this.renderTarget,"Uint",!state)
1096 | }
1097 |
1098 |
1099 | DisableOnErase() {
1100 | OnMessage(0x14, this.OnEraseFunc,0)
1101 | }
1102 |
1103 |
1104 | Release() {
1105 | this.DisableOnErase()
1106 | this.OnEraseFunc := ""
1107 | this.__Delete()
1108 | }
1109 |
1110 | ;##########################################
1111 | ; internal functions used by the class
1112 | ;##########################################
1113 | AdjustWindow(byref x,byref y,byref w,byref h) {
1114 | local
1115 | this.lastPos := (x<<16)+y
1116 | this.lastSize := (w<<16)+h
1117 | DllCall("GetWindowInfo","Uptr",(this.attachHWND ? this.attachHWND : this.hwnd),"ptr",this.tBufferPtr)
1118 | pp := (this.attachClient ? 20 : 4)
1119 | x1 := NumGet(this.tBufferPtr,pp,"int")
1120 | y1 := NumGet(this.tBufferPtr,pp+4,"int")
1121 | x2 := NumGet(this.tBufferPtr,pp+8,"int")
1122 | y2 := NumGet(this.tBufferPtr,pp+12,"int")
1123 | this.width := w := x2-x1
1124 | this.height := h := y2-y1
1125 | this.x := x := x1
1126 | this.y := y := y1
1127 | this.x2 := x + w
1128 | this.y2 := y + h
1129 |
1130 | hBorders := (this.attachClient ? 0 : NumGet(this.tBufferPtr,48,"int"))
1131 | vBorders := (this.attachClient ? 0 : NumGet(this.tBufferPtr,52,"int"))
1132 | this.realX := hBorders
1133 | this.realY := 0
1134 | this.realWidth := w - (hBorders*2)
1135 | this.realHeight := h - vBorders
1136 | this.realX2 := this.realX + this.realWidth
1137 | this.realY2 := this.realY + this.realHeight
1138 | this.offX := -x1 ;- hBorders
1139 | this.offY := -y1
1140 | }
1141 | SetIdentity(o:=0) {
1142 | NumPut(1,this.matrixPtr,o+0,"float")
1143 | NumPut(0,this.matrixPtr,o+4,"float")
1144 | NumPut(0,this.matrixPtr,o+8,"float")
1145 | NumPut(1,this.matrixPtr,o+12,"float")
1146 | NumPut(0,this.matrixPtr,o+16,"float")
1147 | NumPut(0,this.matrixPtr,o+20,"float")
1148 | }
1149 | DrawTextShadow(p,text,x,y,w,h,color) {
1150 | this.SetBrushColor(color)
1151 | NumPut(x,this.tBufferPtr,0,"float")
1152 | NumPut(y,this.tBufferPtr,4,"float")
1153 | NumPut(x+w,this.tBufferPtr,8,"float")
1154 | NumPut(y+h,this.tBufferPtr,12,"float")
1155 | DllCall(this._DrawText,"ptr",this.renderTarget,"wstr",text,"uint",strlen(text),"ptr",p,"ptr",this.tBufferPtr,"ptr",this.brush,"uint",0,"uint",0)
1156 | }
1157 | DrawTextOutline(p,text,x,y,w,h,color) {
1158 | static o := [[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]]
1159 | this.SetBrushColor(color)
1160 | for k,v in o
1161 | {
1162 | NumPut(x+v[1],this.tBufferPtr,0,"float")
1163 | NumPut(y+v[2],this.tBufferPtr,4,"float")
1164 | NumPut(x+w+v[1],this.tBufferPtr,8,"float")
1165 | NumPut(y+h+v[2],this.tBufferPtr,12,"float")
1166 | DllCall(this._DrawText,"ptr",this.renderTarget,"wstr",text,"uint",strlen(text),"ptr",p,"ptr",this.tBufferPtr,"ptr",this.brush,"uint",0,"uint",0)
1167 | }
1168 | }
1169 | Err(str*) {
1170 | local
1171 | s := ""
1172 | for k,v in str
1173 | s .= (s = "" ? "" : "`n`n") v
1174 | msgbox,% 0x30 | 0x1000,% "Problem!",% s
1175 | }
1176 | LoadLib(lib*) {
1177 | for k,v in lib {
1178 | if (!DllCall("GetModuleHandle", "str", v, "Ptr")) {
1179 | DllCall("LoadLibrary", "Str", v)
1180 | }
1181 | }
1182 | }
1183 | SetBrushColor(col) {
1184 | if (col <= 0xFFFFFF)
1185 | col += 0xFF000000
1186 | if (col != this.lastCol) {
1187 | NumPut(((col & 0xFF0000)>>16)/255,this.colPtr,0,"float")
1188 | NumPut(((col & 0xFF00)>>8)/255,this.colPtr,4,"float")
1189 | NumPut(((col & 0xFF))/255,this.colPtr,8,"float")
1190 | NumPut((col > 0xFFFFFF ? ((col & 0xFF000000)>>24)/255 : 1),this.colPtr,12,"float")
1191 | DllCall(this._SetBrush,"Ptr",this.brush,"Ptr",this.colPtr)
1192 | this.lastCol := col
1193 | return 1
1194 | }
1195 | return 0
1196 | }
1197 | vTable(a,p) {
1198 | v := NumGet(a+0,0,"ptr")
1199 | return (v ? NumGet(v+0,p*a_ptrsize,"Ptr") : 0)
1200 | }
1201 | _guid(guidStr,byref clsid) {
1202 | VarSetCapacity(clsid,16)
1203 | DllCall("ole32\CLSIDFromString", "WStr", guidStr, "Ptr", &clsid)
1204 | }
1205 | SetVarCapacity(key,size,fill=0) {
1206 | this.SetCapacity(key,size)
1207 | DllCall("RtlFillMemory","Ptr",this.GetAddress(key),"Ptr",size,"uchar",fill)
1208 | return this.GetAddress(key)
1209 | }
1210 | CacheImage(image) {
1211 | local
1212 | if (this.imageCache.haskey(image))
1213 | return 1
1214 | if (image = "") {
1215 | this.Err("Error, expected resource image path but empty variable was supplied!")
1216 | return 0
1217 | }
1218 | if (!FileExist(image)) {
1219 | this.Err("Error finding resource image","'" image "' does not exist!")
1220 | return 0
1221 | }
1222 | DllCall("gdiplus\GdipCreateBitmapFromFile", "Ptr", &image, "Ptr*", bm)
1223 | DllCall("gdiplus\GdipGetImageWidth", "Ptr", bm, "Uint*", w)
1224 | DllCall("gdiplus\GdipGetImageHeight", "Ptr", bm, "Uint*", h)
1225 | VarSetCapacity(r,16,0)
1226 | NumPut(w,r,8,"uint")
1227 | NumPut(h,r,12,"uint")
1228 | VarSetCapacity(bmdata, 32, 0)
1229 | DllCall("Gdiplus\GdipBitmapLockBits", "Ptr", bm, "Ptr", &r, "uint", 3, "int", 0x26200A, "Ptr", &bmdata)
1230 | scan := NumGet(bmdata, 16, "Ptr")
1231 | p := DllCall("GlobalAlloc", "uint", 0x40, "ptr", 16+((w*h)*4), "ptr")
1232 | DllCall(this._cacheImage,"Ptr",p,"Ptr",scan,"int",w,"int",h,"uchar",255)
1233 | DllCall("Gdiplus\GdipBitmapUnlockBits", "Ptr", bm, "Ptr", &bmdata)
1234 | DllCall("gdiplus\GdipDisposeImage", "ptr", bm)
1235 | VarSetCapacity(props,64,0)
1236 | NumPut(28,props,0,"uint")
1237 | NumPut(1,props,4,"uint")
1238 | if (this.bits) {
1239 | NumPut(w,this.tBufferPtr,0,"uint")
1240 | NumPut(h,this.tBufferPtr,4,"uint")
1241 | if (v := DllCall(this.vTable(this.renderTarget,4),"ptr",this.renderTarget,"int64",NumGet(this.tBufferPtr,"int64"),"ptr",p,"uint",4 * w,"ptr",&props,"ptr*",bitmap) != 0) {
1242 | this.Err("Problem creating D2D bitmap for image '" image "'")
1243 | return 0
1244 | }
1245 | } else {
1246 | if (v := DllCall(this.vTable(this.renderTarget,4),"ptr",this.renderTarget,"uint",w,"uint",h,"ptr",p,"uint",4 * w,"ptr",&props,"ptr*",bitmap) != 0) {
1247 | this.Err("Problem creating D2D bitmap for image '" image "'")
1248 | return 0
1249 | }
1250 | }
1251 | return this.imageCache[image] := {p:bitmap,w:w,h:h}
1252 | }
1253 | CacheFont(name,size,bold:=400) {
1254 | if (DllCall(this.vTable(this.wFactory,15),"ptr",this.wFactory,"wstr",name,"ptr",0,"uint",bold,"uint",0,"uint",5,"float",size,"wstr","en-us","ptr*",textFormat) != 0) {
1255 | this.Err("Unable to create font: " name " (size: " size ", bold: " bold ")","Try a different font or check to see if " name " is a valid font!")
1256 | return 0
1257 | }
1258 | return this.fonts[name size bold] := textFormat
1259 | }
1260 | __Delete() {
1261 | DllCall("gdiplus\GdiplusShutdown", "Ptr*", this.gdiplusToken)
1262 | DllCall(this.vTable(this.factory,2),"ptr",this.factory)
1263 | DllCall(this.vTable(this.stroke,2),"ptr",this.stroke)
1264 | DllCall(this.vTable(this.strokeRounded,2),"ptr",this.strokeRounded)
1265 | DllCall(this.vTable(this.renderTarget,2),"ptr",this.renderTarget)
1266 | DllCall(this.vTable(this.brush,2),"ptr",this.brush)
1267 | DllCall(this.vTable(this.wfactory,2),"ptr",this.wfactory)
1268 | DllCall("GlobalFree", "ptr", this._cacheImage)
1269 | DllCall("GlobalFree", "ptr", this._dtc)
1270 | for k,v in this.fonts {
1271 | if (v and this.vTable(v,2)) {
1272 | DllCall(this.vTable(v,2),"ptr",v)
1273 | }
1274 | }
1275 | for k,v in this.imageCache {
1276 | if (v.p and this.vTable(v.p,2)) {
1277 | DllCall(this.vTable(v.p,2),"ptr",v.p)
1278 | }
1279 | }
1280 | guiID := this.guiID
1281 | gui %guiID%:destroy
1282 | OnMessage(0x14, this.OnEraseFunc,0)
1283 | this.OnEraseFunc := ""
1284 | }
1285 | InitFuncs() {
1286 | this._DrawText := this.vTable(this.renderTarget,27)
1287 | this._BeginDraw := this.vTable(this.renderTarget,48)
1288 | this._Clear := this.vTable(this.renderTarget,47)
1289 | this._DrawImage := this.vTable(this.renderTarget,26)
1290 | this._EndDraw := this.vTable(this.renderTarget,49)
1291 | this._RMatrix := this.vTable(this.renderTarget,30)
1292 | this._DrawEllipse := this.vTable(this.renderTarget,20)
1293 | this._FillEllipse := this.vTable(this.renderTarget,21)
1294 | this._DrawRectangle := this.vTable(this.renderTarget,16)
1295 | this._FillRectangle := this.vTable(this.renderTarget,17)
1296 | this._DrawRoundedRectangle := this.vTable(this.renderTarget,18)
1297 | this._FillRoundedRectangle := this.vTable(this.renderTarget,19)
1298 | this._DrawLine := this.vTable(this.renderTarget,15)
1299 | this._NRSize := this.vTable(this.renderTarget,58)
1300 | this._SetBrush := this.vTable(this.brush,8)
1301 | }
1302 | Mcode(str) {
1303 | local
1304 | s := strsplit(str,"|")
1305 | if (s.length() != 2)
1306 | return
1307 | if (!DllCall("crypt32\CryptStringToBinary", "str", s[this.bits+1], "uint", 0, "uint", 1, "ptr", 0, "uint*", pp, "ptr", 0, "ptr", 0))
1308 | return
1309 | p := DllCall("GlobalAlloc", "uint", 0, "ptr", pp, "ptr")
1310 | if (this.bits)
1311 | DllCall("VirtualProtect", "ptr", p, "ptr", pp, "uint", 0x40, "uint*", op)
1312 | if (DllCall("crypt32\CryptStringToBinary", "str", s[this.bits+1], "uint", 0, "uint", 1, "ptr", p, "uint*", pp, "ptr", 0, "ptr", 0))
1313 | return p
1314 | DllCall("GlobalFree", "ptr", p)
1315 | }
1316 | Display(state) {
1317 | if (!state) {
1318 | DllCall("User32.dll\ShowWindow","Ptr",this.hwnd,"Int",0)
1319 | } else {
1320 | DllCall("User32.dll\ShowWindow","Ptr",this.hwnd,"Int",4)
1321 | }
1322 | this.notifyActive := 1
1323 | }
1324 | }
1325 | _SOC_ONERASE(oHwnd, wParam, lParam, msg, hwnd) {
1326 | if (oHwnd = hwnd)
1327 | return 0
1328 | }
1329 |
--------------------------------------------------------------------------------