├── 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 | [![Video](https://img.youtube.com/vi/L2Cb1UCJDEg/default.jpg)](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 | --------------------------------------------------------------------------------