1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Initial checkin

This commit is contained in:
Brian Fiete 2019-08-23 11:56:54 -07:00
parent c74712dad9
commit 078564ac9e
3242 changed files with 1616395 additions and 0 deletions

411
Beef.sln Normal file
View file

@ -0,0 +1,411 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27205.2004
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BeefySysLib", "BeefySysLib\BeefySysLib.vcxproj", "{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7340A6F8-D716-4DD6-93AC-F5056D850D06}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IDEHelper", "IDEHelper\IDEHelper.vcxproj", "{F8D29C38-D37C-4AF2-8540-2F6E543264F1}"
ProjectSection(ProjectDependencies) = postProject
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D} = {ECEAB68D-2F15-495F-A29C-5EA9548AA23D}
{53609BB3-D874-465C-AF7B-DF626DB0D89B} = {53609BB3-D874-465C-AF7B-DF626DB0D89B}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BeefySysLib_static", "BeefySysLib\BeefySysLib_static.vcxproj", "{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BeefRT", "BeefRT\BeefRT.vcxproj", "{5BE0B958-C13B-4986-A588-97A8F707E42E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhunspell", "extern\hunspell\src\win_api\libhunspell.vcxproj", "{53609BB3-D874-465C-AF7B-DF626DB0D89B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Debugger32", "Debugger32\Debugger32.vcxproj", "{29025CF2-07CC-4C25-A672-6324C95AA28E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Debugger64", "Debugger64\Debugger64.vcxproj", "{29025CF2-07CC-4C25-A672-6324C95AA28F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BeefLink", "BeefLink\BeefLink.vcxproj", "{78BE2825-EF6A-4C57-B22D-FF69EB925359}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BeefBoot", "BeefBoot\BeefBoot.vcxproj", "{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BeefDbg", "BeefRT\BeefDbg\BeefDbg.vcxproj", "{8F529049-889A-4FC6-9F4C-FAAFC42C9519}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug Static CStatic|x64 = Debug Static CStatic|x64
Debug Static CStatic|x86 = Debug Static CStatic|x86
Debug Static|x64 = Debug Static|x64
Debug Static|x86 = Debug Static|x86
Debug_dll|x64 = Debug_dll|x64
Debug_dll|x86 = Debug_dll|x86
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release Static CStatic|x64 = Release Static CStatic|x64
Release Static CStatic|x86 = Release Static CStatic|x86
Release Static|x64 = Release Static|x64
Release Static|x86 = Release Static|x86
Release_dll|x64 = Release_dll|x64
Release_dll|x86 = Release_dll|x86
Release_NoDbgInfo|x64 = Release_NoDbgInfo|x64
Release_NoDbgInfo|x86 = Release_NoDbgInfo|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug Static CStatic|x64.ActiveCfg = Debug Static|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug Static CStatic|x64.Build.0 = Debug Static|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug Static CStatic|x86.ActiveCfg = Debug Static|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug Static CStatic|x86.Build.0 = Debug Static|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug Static|x64.ActiveCfg = Debug Static|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug Static|x64.Build.0 = Debug Static|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug Static|x86.ActiveCfg = Debug Static|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug Static|x86.Build.0 = Debug Static|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug_dll|x64.ActiveCfg = Debug|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug_dll|x64.Build.0 = Debug|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug_dll|x86.ActiveCfg = Debug|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug_dll|x86.Build.0 = Debug|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug|x64.ActiveCfg = Debug|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug|x64.Build.0 = Debug|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug|x86.ActiveCfg = Debug|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Debug|x86.Build.0 = Debug|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release Static CStatic|x64.ActiveCfg = Release Static|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release Static CStatic|x64.Build.0 = Release Static|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release Static CStatic|x86.ActiveCfg = Release Static|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release Static CStatic|x86.Build.0 = Release Static|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release Static|x64.ActiveCfg = Release Static|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release Static|x64.Build.0 = Release Static|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release Static|x86.ActiveCfg = Release Static|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release Static|x86.Build.0 = Release Static|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release_dll|x64.ActiveCfg = Release|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release_dll|x64.Build.0 = Release|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release_dll|x86.ActiveCfg = Release|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release_dll|x86.Build.0 = Release|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release_NoDbgInfo|x64.ActiveCfg = Release|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release_NoDbgInfo|x64.Build.0 = Release|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release_NoDbgInfo|x86.ActiveCfg = Release|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release|x64.ActiveCfg = Release|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release|x64.Build.0 = Release|x64
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release|x86.ActiveCfg = Release|Win32
{E958BC7A-F2D8-4765-AFD6-85BBF54CD921}.Release|x86.Build.0 = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug Static CStatic|x64.ActiveCfg = Debug|x64
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug Static CStatic|x64.Build.0 = Debug|x64
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug Static CStatic|x86.ActiveCfg = Debug|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug Static CStatic|x86.Build.0 = Debug|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug Static|x64.ActiveCfg = Debug|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug Static|x86.ActiveCfg = Debug|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug Static|x86.Build.0 = Debug|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug_dll|x64.ActiveCfg = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug_dll|x64.Build.0 = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug_dll|x86.ActiveCfg = Debug|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug_dll|x86.Build.0 = Debug|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug|x64.ActiveCfg = Debug|x64
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug|x64.Build.0 = Debug|x64
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug|x86.ActiveCfg = Debug|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Debug|x86.Build.0 = Debug|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release Static CStatic|x64.ActiveCfg = Release_NoDbgInfo|x64
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release Static CStatic|x64.Build.0 = Release_NoDbgInfo|x64
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release Static CStatic|x86.ActiveCfg = Release_NoDbgInfo|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release Static CStatic|x86.Build.0 = Release_NoDbgInfo|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release Static|x64.ActiveCfg = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release Static|x86.ActiveCfg = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release Static|x86.Build.0 = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release_dll|x64.ActiveCfg = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release_dll|x64.Build.0 = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release_dll|x86.ActiveCfg = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release_dll|x86.Build.0 = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release_NoDbgInfo|x64.ActiveCfg = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release_NoDbgInfo|x86.ActiveCfg = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release_NoDbgInfo|x86.Build.0 = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release|x64.ActiveCfg = Release|x64
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release|x64.Build.0 = Release|x64
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release|x86.ActiveCfg = Release|Win32
{F8D29C38-D37C-4AF2-8540-2F6E543264F1}.Release|x86.Build.0 = Release|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug Static CStatic|x64.ActiveCfg = Debug|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug Static CStatic|x64.Build.0 = Debug|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug Static CStatic|x86.ActiveCfg = Debug|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug Static CStatic|x86.Build.0 = Debug|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug Static|x64.ActiveCfg = Debug|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug Static|x64.Build.0 = Debug|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug Static|x86.ActiveCfg = Debug|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug Static|x86.Build.0 = Debug|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug_dll|x64.ActiveCfg = Debug|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug_dll|x64.Build.0 = Debug|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug_dll|x86.ActiveCfg = Debug|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug_dll|x86.Build.0 = Debug|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug|x64.ActiveCfg = Debug|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug|x64.Build.0 = Debug|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug|x86.ActiveCfg = Debug|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Debug|x86.Build.0 = Debug|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release Static CStatic|x64.ActiveCfg = Release|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release Static CStatic|x64.Build.0 = Release|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release Static CStatic|x86.ActiveCfg = Release|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release Static CStatic|x86.Build.0 = Release|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release Static|x64.ActiveCfg = Release|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release Static|x64.Build.0 = Release|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release Static|x86.ActiveCfg = Release|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release Static|x86.Build.0 = Release|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release_dll|x64.ActiveCfg = Release|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release_dll|x64.Build.0 = Release|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release_dll|x86.ActiveCfg = Release|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release_dll|x86.Build.0 = Release|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release_NoDbgInfo|x64.ActiveCfg = Release|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release_NoDbgInfo|x64.Build.0 = Release|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release_NoDbgInfo|x86.ActiveCfg = Release|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release_NoDbgInfo|x86.Build.0 = Release|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release|x64.ActiveCfg = Release|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release|x64.Build.0 = Release|x64
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release|x86.ActiveCfg = Release|Win32
{ECEAB68D-2F15-495F-A29C-5EA9548AA23D}.Release|x86.Build.0 = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug Static CStatic|x64.ActiveCfg = Debug Static CStatic|x64
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug Static CStatic|x64.Build.0 = Debug Static CStatic|x64
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug Static CStatic|x86.ActiveCfg = Debug Static CStatic|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug Static CStatic|x86.Build.0 = Debug Static CStatic|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug Static|x64.ActiveCfg = Debug|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug Static|x86.ActiveCfg = Debug|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug Static|x86.Build.0 = Debug|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug_dll|x64.ActiveCfg = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug_dll|x64.Build.0 = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug_dll|x86.ActiveCfg = Debug|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug_dll|x86.Build.0 = Debug|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug|x64.ActiveCfg = Debug|x64
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug|x64.Build.0 = Debug|x64
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug|x86.ActiveCfg = Debug|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Debug|x86.Build.0 = Debug|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release Static CStatic|x64.ActiveCfg = Release Static CStatic|x64
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release Static CStatic|x64.Build.0 = Release Static CStatic|x64
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release Static CStatic|x86.ActiveCfg = Release Static CStatic|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release Static CStatic|x86.Build.0 = Release Static CStatic|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release Static|x64.ActiveCfg = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release Static|x86.ActiveCfg = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release Static|x86.Build.0 = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release_dll|x64.ActiveCfg = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release_dll|x64.Build.0 = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release_dll|x86.ActiveCfg = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release_dll|x86.Build.0 = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release_NoDbgInfo|x64.ActiveCfg = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release_NoDbgInfo|x86.ActiveCfg = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release_NoDbgInfo|x86.Build.0 = Release|Win32
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release|x64.ActiveCfg = Release|x64
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release|x64.Build.0 = Release|x64
{5BE0B958-C13B-4986-A588-97A8F707E42E}.Release|x86.ActiveCfg = Release|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug Static CStatic|x64.ActiveCfg = Debug_dll|x64
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug Static CStatic|x64.Build.0 = Debug_dll|x64
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug Static CStatic|x86.ActiveCfg = Debug_dll|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug Static CStatic|x86.Build.0 = Debug_dll|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug Static|x64.ActiveCfg = Release|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug Static|x64.Build.0 = Release|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug Static|x86.ActiveCfg = Debug|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug Static|x86.Build.0 = Debug|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug_dll|x64.ActiveCfg = Debug_dll|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug_dll|x86.ActiveCfg = Debug_dll|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug_dll|x86.Build.0 = Debug_dll|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug|x64.ActiveCfg = Debug|x64
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug|x64.Build.0 = Debug|x64
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug|x86.ActiveCfg = Debug|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Debug|x86.Build.0 = Debug|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release Static CStatic|x64.ActiveCfg = Release_dll|x64
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release Static CStatic|x64.Build.0 = Release_dll|x64
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release Static CStatic|x86.ActiveCfg = Release_dll|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release Static CStatic|x86.Build.0 = Release_dll|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release Static|x64.ActiveCfg = Release|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release Static|x64.Build.0 = Release|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release Static|x86.ActiveCfg = Release|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release Static|x86.Build.0 = Release|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release_dll|x64.ActiveCfg = Release_dll|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release_dll|x86.ActiveCfg = Release_dll|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release_dll|x86.Build.0 = Release_dll|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release_NoDbgInfo|x64.ActiveCfg = Release|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release_NoDbgInfo|x86.ActiveCfg = Release|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release_NoDbgInfo|x86.Build.0 = Release|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release|x64.ActiveCfg = Release|x64
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release|x64.Build.0 = Release|x64
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release|x86.ActiveCfg = Release|Win32
{53609BB3-D874-465C-AF7B-DF626DB0D89B}.Release|x86.Build.0 = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug Static CStatic|x64.ActiveCfg = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug Static CStatic|x64.Build.0 = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug Static CStatic|x86.ActiveCfg = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug Static CStatic|x86.Build.0 = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug Static|x64.ActiveCfg = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug Static|x64.Build.0 = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug Static|x86.ActiveCfg = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug Static|x86.Build.0 = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug_dll|x64.ActiveCfg = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug_dll|x64.Build.0 = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug_dll|x86.ActiveCfg = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug_dll|x86.Build.0 = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug|x64.ActiveCfg = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug|x64.Build.0 = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug|x86.ActiveCfg = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Debug|x86.Build.0 = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release Static CStatic|x64.ActiveCfg = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release Static CStatic|x64.Build.0 = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release Static CStatic|x86.ActiveCfg = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release Static CStatic|x86.Build.0 = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release Static|x64.ActiveCfg = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release Static|x64.Build.0 = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release Static|x86.ActiveCfg = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release Static|x86.Build.0 = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release_dll|x64.ActiveCfg = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release_dll|x64.Build.0 = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release_dll|x86.ActiveCfg = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release_dll|x86.Build.0 = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release_NoDbgInfo|x64.ActiveCfg = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release_NoDbgInfo|x64.Build.0 = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release_NoDbgInfo|x86.ActiveCfg = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release_NoDbgInfo|x86.Build.0 = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release|x64.ActiveCfg = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release|x64.Build.0 = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release|x86.ActiveCfg = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28E}.Release|x86.Build.0 = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug Static CStatic|x64.ActiveCfg = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug Static CStatic|x64.Build.0 = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug Static CStatic|x86.ActiveCfg = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug Static CStatic|x86.Build.0 = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug Static|x64.ActiveCfg = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug Static|x64.Build.0 = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug Static|x86.ActiveCfg = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug Static|x86.Build.0 = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug_dll|x64.ActiveCfg = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug_dll|x64.Build.0 = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug_dll|x86.ActiveCfg = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug_dll|x86.Build.0 = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug|x64.ActiveCfg = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug|x64.Build.0 = Debug|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug|x86.ActiveCfg = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Debug|x86.Build.0 = Debug|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release Static CStatic|x64.ActiveCfg = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release Static CStatic|x64.Build.0 = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release Static CStatic|x86.ActiveCfg = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release Static CStatic|x86.Build.0 = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release Static|x64.ActiveCfg = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release Static|x64.Build.0 = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release Static|x86.ActiveCfg = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release Static|x86.Build.0 = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release_dll|x64.ActiveCfg = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release_dll|x64.Build.0 = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release_dll|x86.ActiveCfg = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release_dll|x86.Build.0 = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release_NoDbgInfo|x64.ActiveCfg = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release_NoDbgInfo|x64.Build.0 = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release_NoDbgInfo|x86.ActiveCfg = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release_NoDbgInfo|x86.Build.0 = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release|x64.ActiveCfg = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release|x64.Build.0 = Release|x64
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release|x86.ActiveCfg = Release|Win32
{29025CF2-07CC-4C25-A672-6324C95AA28F}.Release|x86.Build.0 = Release|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug Static CStatic|x64.ActiveCfg = Debug|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug Static CStatic|x64.Build.0 = Debug|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug Static CStatic|x86.ActiveCfg = Debug|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug Static CStatic|x86.Build.0 = Debug|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug Static|x64.ActiveCfg = Debug|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug Static|x64.Build.0 = Debug|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug Static|x86.ActiveCfg = Debug|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug Static|x86.Build.0 = Debug|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug_dll|x64.ActiveCfg = Debug|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug_dll|x64.Build.0 = Debug|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug_dll|x86.ActiveCfg = Debug|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug_dll|x86.Build.0 = Debug|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug|x64.ActiveCfg = Debug|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug|x64.Build.0 = Debug|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug|x86.ActiveCfg = Debug|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Debug|x86.Build.0 = Debug|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release Static CStatic|x64.ActiveCfg = Release|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release Static CStatic|x64.Build.0 = Release|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release Static CStatic|x86.ActiveCfg = Release|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release Static CStatic|x86.Build.0 = Release|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release Static|x64.ActiveCfg = Release|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release Static|x64.Build.0 = Release|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release Static|x86.ActiveCfg = Release|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release Static|x86.Build.0 = Release|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release_dll|x64.ActiveCfg = Release|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release_dll|x64.Build.0 = Release|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release_dll|x86.ActiveCfg = Release|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release_dll|x86.Build.0 = Release|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release_NoDbgInfo|x64.ActiveCfg = Release|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release_NoDbgInfo|x64.Build.0 = Release|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release_NoDbgInfo|x86.ActiveCfg = Release|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release_NoDbgInfo|x86.Build.0 = Release|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release|x64.ActiveCfg = Release|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release|x64.Build.0 = Release|x64
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release|x86.ActiveCfg = Release|Win32
{78BE2825-EF6A-4C57-B22D-FF69EB925359}.Release|x86.Build.0 = Release|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug Static CStatic|x64.ActiveCfg = Debug|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug Static CStatic|x64.Build.0 = Debug|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug Static CStatic|x86.ActiveCfg = Debug|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug Static CStatic|x86.Build.0 = Debug|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug Static|x64.ActiveCfg = Debug|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug Static|x64.Build.0 = Debug|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug Static|x86.ActiveCfg = Debug|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug Static|x86.Build.0 = Debug|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug_dll|x64.ActiveCfg = Debug|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug_dll|x64.Build.0 = Debug|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug_dll|x86.ActiveCfg = Debug|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug_dll|x86.Build.0 = Debug|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug|x64.ActiveCfg = Debug|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug|x64.Build.0 = Debug|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug|x86.ActiveCfg = Debug|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Debug|x86.Build.0 = Debug|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release Static CStatic|x64.ActiveCfg = Release|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release Static CStatic|x64.Build.0 = Release|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release Static CStatic|x86.ActiveCfg = Release|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release Static CStatic|x86.Build.0 = Release|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release Static|x64.ActiveCfg = Release|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release Static|x64.Build.0 = Release|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release Static|x86.ActiveCfg = Release|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release Static|x86.Build.0 = Release|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release_dll|x64.ActiveCfg = Release|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release_dll|x64.Build.0 = Release|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release_dll|x86.ActiveCfg = Release|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release_dll|x86.Build.0 = Release|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release_NoDbgInfo|x64.ActiveCfg = Release|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release_NoDbgInfo|x64.Build.0 = Release|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release_NoDbgInfo|x86.ActiveCfg = Release|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release_NoDbgInfo|x86.Build.0 = Release|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release|x64.ActiveCfg = Release|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release|x64.Build.0 = Release|x64
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release|x86.ActiveCfg = Release|Win32
{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}.Release|x86.Build.0 = Release|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug Static CStatic|x64.ActiveCfg = Debug|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug Static CStatic|x64.Build.0 = Debug|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug Static CStatic|x86.ActiveCfg = Debug|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug Static CStatic|x86.Build.0 = Debug|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug Static|x64.ActiveCfg = Debug|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug Static|x64.Build.0 = Debug|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug Static|x86.ActiveCfg = Debug|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug Static|x86.Build.0 = Debug|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug_dll|x64.ActiveCfg = Debug|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug_dll|x64.Build.0 = Debug|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug_dll|x86.ActiveCfg = Debug|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug_dll|x86.Build.0 = Debug|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug|x64.ActiveCfg = Debug|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug|x64.Build.0 = Debug|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug|x86.ActiveCfg = Debug|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Debug|x86.Build.0 = Debug|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release Static CStatic|x64.ActiveCfg = Release|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release Static CStatic|x64.Build.0 = Release|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release Static CStatic|x86.ActiveCfg = Release|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release Static CStatic|x86.Build.0 = Release|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release Static|x64.ActiveCfg = Release|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release Static|x64.Build.0 = Release|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release Static|x86.ActiveCfg = Release|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release Static|x86.Build.0 = Release|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release_dll|x64.ActiveCfg = Release|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release_dll|x64.Build.0 = Release|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release_dll|x86.ActiveCfg = Release|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release_dll|x86.Build.0 = Release|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release_NoDbgInfo|x64.ActiveCfg = Release|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release_NoDbgInfo|x64.Build.0 = Release|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release_NoDbgInfo|x86.ActiveCfg = Release|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release_NoDbgInfo|x86.Build.0 = Release|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release|x64.ActiveCfg = Release|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release|x64.Build.0 = Release|x64
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release|x86.ActiveCfg = Release|Win32
{8F529049-889A-4FC6-9F4C-FAAFC42C9519}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
VD_Solution = <?xml version="1.0" encoding="utf-16"?>|§r|§n<DocumentsSolution xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">|§r|§n <m_persistedPinnedDocumentGroupLabels>|§r|§n <string>X86</string>|§r|§n </m_persistedPinnedDocumentGroupLabels>|§r|§n</DocumentsSolution>
SolutionGuid = {460361DC-9F40-4AE7-B647-82D5D69B70DC}
EndGlobalSection
EndGlobal

93
BeefBoot/BeefBoot.cpp Normal file
View file

@ -0,0 +1,93 @@
//#define USE_OLD_BEEFBUILD
#pragma warning(disable:4996)
#include <iostream>
#include "BeefySysLib/Common.h"
#include "BeefySysLib/util/Array.h"
#include "BeefySysLib/util/SizedArray.h"
#include "BeefySysLib/util/Dictionary.h"
#include "BeefySysLib/util/CabUtil.h"
#include "BeefySysLib/util/BeefPerf.h"
#include "BeefySysLib/util/Deque.h"
#include "BeefySysLib/util/HashSet.h"
#include "BeefySysLib/util/MultiHashSet.h"
//#include <mmsystem.h>
//#include <shellapi.h>
//#include <Objbase.h>
#define BF_DBG_64
#include "IDEHelper/StrHashMap.h"
using namespace Beefy;
#include "BootApp.h"
BF_IMPORT void BF_CALLTYPE Debugger_ProgramDone();
int main(int argc, char* argv[])
{
BfpSystem_SetCommandLine(argc, argv);
BfpThread_SetName(NULL, "MainThread", NULL);
BfpSystem_Init(BFP_VERSION, BfpSystemInitFlag_InstallCrashCatcher);
gApp = new BootApp();
bool success = true;
for (int i = 1; i < argc; i++)
{
std::string arg = argv[i];
if (arg[0] == '"')
{
arg.erase(0, 1);
if ((arg.length() > 1) && (arg[arg.length() - 1] == '"'))
arg.erase(arg.length() - 1);
success &= gApp->HandleCmdLine(arg, "");
continue;
}
int eqPos = (int)arg.find('=');
if (eqPos == -1)
{
success &= gApp->HandleCmdLine(arg, "");
continue;
}
std::string cmd = arg.substr(0, eqPos);
std::string param = arg.substr(eqPos + 1);
if ((param.length() > 1) && (param[0] == '"'))
{
param.erase(0, 1);
if ((param.length() > 1) && (param[param.length() - 1] == '"'))
param.erase(param.length() - 1);
}
success &= gApp->HandleCmdLine(cmd, param);
}
if (!gApp->mShowedHelp)
{
if (success)
success = gApp->Init();
if (success)
success = gApp->Compile();
if (success)
gApp->OutputLine("SUCCESS", OutputPri_Critical);
else
gApp->OutputLine("FAILED", OutputPri_Critical);
}
delete gApp;
Debugger_ProgramDone();
BfpSystem_Shutdown();
BP_SHUTDOWN();
return success ? 0 : 1;
}

180
BeefBoot/BeefBoot.h Normal file
View file

@ -0,0 +1,180 @@
#pragma once
#include "BeefySysLib/Common.h"
#include "BeefySysLib/util/Array.h"
#include "BeefySysLib/util/String.h"
#include <set>
//#include <direct.h>
#pragma warning(disable:4996)
NS_BF_BEGIN
#define APPEND2(VAL1, VAL2) VAL1##VAL2
#define APPEND(VAL1, VAL2) APPEND2(VAL1, VAL2)
#define ENUM_VAL_GENERATE(ENUM_ENTRY) APPEND(ENUM_TYPE, _##ENUM_ENTRY),
#define ENUM_NAME_GENERATE(ENUM_ENTRY) #ENUM_ENTRY,
#define ENUM_CREATE_DO2(EnumName) \
static const char* EnumName##_Names[] = { ENUM_DECLARE(ENUM_NAME_GENERATE) }; \
enum EnumName { ENUM_DECLARE(ENUM_VAL_GENERATE) }; \
static bool EnumParse(const String& name, EnumName& result) \
{ \
for (int i = 0; i < sizeof(EnumName##_Names)/sizeof(const char*); i++) \
if (name == EnumName##_Names[i]) { result = (EnumName)i; return true; } \
return false; \
} \
static const char* EnumToString(EnumName enumVal) \
{ \
return EnumName##_Names[(int)enumVal]; \
}
#define ENUM_CREATE_DO(EnumType) ENUM_CREATE_DO2(EnumType)
#define ENUM_CREATE ENUM_CREATE_DO(ENUM_TYPE)
class IDEUtils
{
public:
static bool FixFilePath(String& filePath)
{
if (filePath.length() == 0)
return false;
if (filePath[0] == '<')
return false;
if ((filePath.length() > 1) && (filePath[1] == ':'))
filePath[0] = tolower(filePath[0]);
bool prevWasSlash = false;
for (int i = 0; i < filePath.length(); i++)
{
//if ((filePath[i] == '/') && (filePath[i - 1])
if (filePath[i] == DIR_SEP_CHAR_ALT)
filePath[i] = DIR_SEP_CHAR;
if (filePath[i] == DIR_SEP_CHAR)
{
if ((prevWasSlash) && (i > 1))
{
filePath.Remove(i, 1);
i--;
continue;
}
prevWasSlash = true;
}
else
prevWasSlash = false;
if ((i >= 4) && (filePath[i - 3] == DIR_SEP_CHAR) && (filePath[i - 2] == '.') && (filePath[i - 1] == '.') && (filePath[i] == DIR_SEP_CHAR))
{
int prevSlash = (int)filePath.LastIndexOf(DIR_SEP_CHAR, i - 4);
if (prevSlash != -1)
{
filePath.Remove(prevSlash, i - prevSlash);
i = prevSlash;
}
}
}
return true;
}
static void GetDirWithSlash(String& dirName)
{
if (dirName.length() == 0)
return;
char lastC = dirName[dirName.length() - 1];
if ((lastC != '\\') && (lastC != '/'))
dirName += DIR_SEP_CHAR;
}
static FILE* CreateFileWithDir(const String& fileName, const char* options)
{
FILE* fp = fopen(fileName.c_str(), options);
if (fp == NULL)
{
String fileDir = GetFileDir(fileName);
if (!fileDir.empty())
{
RecursiveCreateDirectory(fileDir);
fp = fopen(fileName.c_str(), "w");
}
}
return fp;
}
static bool WriteAllText(const String& fileName, const String& data)
{
FILE* fp = CreateFileWithDir(fileName, "w");
if (fp == NULL)
return false;
fwrite(data.c_str(), 1, data.length(), fp);
fclose(fp);
return true;
}
static void GetFileNameWithoutExtension(const String& filePath, String& outFileName)
{
outFileName += GetFileName(filePath);
int dot = (int)outFileName.LastIndexOf('.');
if (dot != -1)
outFileName.RemoveToEnd(dot);
}
static void GetExtension(const String& filePath, String& ext)
{
int idx = (int)filePath.LastIndexOf('.');
if (idx != -1)
ext = filePath.Substring(idx);
}
static void AppendWithOptionalQuotes(String& targetStr, const String& srcFileName)
{
if ((int)srcFileName.IndexOf(' ') == -1)
targetStr += srcFileName;
else
targetStr += "\"" + srcFileName + "\"";
}
};
class ArgBuilder
{
public:
String* mTarget;
bool mDoLongBreak;
int mLastBreak;
std::multiset<String> mLinkPaths;
public:
ArgBuilder(String& target, bool doLongBreak)
{
mTarget = &target;
mDoLongBreak = doLongBreak;
if (mDoLongBreak)
mLastBreak = (int)mTarget->LastIndexOf('\n');
else
mLastBreak = 0;
}
void AddSep()
{
if (mDoLongBreak)
{
if (mTarget->length() - mLastBreak > 0x1F000)
{
mLastBreak = (int)mTarget->length();
mTarget->Append('\n');
return;
}
}
mTarget->Append(' ');
}
void AddFileName(const String& filePath)
{
IDEUtils::AppendWithOptionalQuotes(*mTarget, filePath);
}
};
NS_BF_END

177
BeefBoot/BeefBoot.vcxproj Normal file
View file

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{755663F3-7C3F-4321-ABFF-CB036C0F2C9F}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>BeefBoot</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\ide\dist\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<TargetName>$(ProjectName)_d</TargetName>
<OutDir>$(SolutionDir)\ide\dist\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)\ide\dist\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)\ide\dist\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../;../IDEHelper;../BeefySysLib/platform/win;../BeefySysLib/third_party;..\extern\llvm-project_8_0_0\llvm\include;..\extern\llvm_win64_8_0_0\include;..\extern\llvm-project_8_0_0\llvm\lib\Target;..\extern\llvm_win64_8_0_0\lib\Target\X86;..\extern\llvm-project_8_0_0\llvm\tools\clang\include</AdditionalIncludeDirectories>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
<OutputFile>$(SolutionDir)\ide\dist\$(TargetName).exe</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<AdditionalIncludeDirectories>../;../IDEHelper;../BeefySysLib/platform/win;../BeefySysLib/third_party;..\extern\llvm-project_8_0_0\llvm\include;..\extern\llvm_win64_8_0_0\include;..\extern\llvm-project_8_0_0\llvm\lib\Target;..\extern\llvm_win64_8_0_0\lib\Target\X86;..\extern\llvm\tools\clang\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
<OutputFile>$(SolutionDir)\ide\dist\$(TargetName).exe</OutputFile>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="BeefBoot.cpp" />
<ClCompile Include="BootApp.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BeefySysLib\BeefySysLib_static.vcxproj">
<Project>{eceab68d-2f15-495f-a29c-5ea9548aa23d}</Project>
</ProjectReference>
<ProjectReference Include="..\IDEHelper\IDEHelper.vcxproj">
<Project>{f8d29c38-d37c-4af2-8540-2f6e543264f1}</Project>
<Private>false</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="BeefBoot.h" />
<ClInclude Include="BootApp.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BeefBoot.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="BootApp.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="BootApp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BeefBoot.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

841
BeefBoot/BootApp.cpp Normal file
View file

@ -0,0 +1,841 @@
#pragma warning(disable:4996)
//#define BFBUILD_MAIN_THREAD_COMPILE
#include "BootApp.h"
#include <iostream>
#include "BeefySysLib/util/String.h"
#include "BeefySysLib/util/FileEnumerator.h"
#include "BeefySysLib/util/WorkThread.h"
#include "BeefySysLib/platform/PlatformHelper.h"
#include "Compiler/BfSystem.h"
#ifdef BF_PLATFORM_WINDOWS
#include <direct.h>
#endif
BF_IMPORT void BF_CALLTYPE Targets_Create();
BF_IMPORT void BF_CALLTYPE Targets_Delete();
BF_IMPORT void BF_CALLTYPE BfSystem_ReportMemory(void* bfSystem);
BF_EXPORT void BF_CALLTYPE BfCompiler_ProgramDone();
BF_IMPORT void BF_CALLTYPE Debugger_FullReportMemory();
//////////////////////////////////////////////////////////////////////////
enum BfCompilerOptionFlags
{
BfCompilerOptionFlag_None = 0,
BfCompilerOptionFlag_EmitDebugInfo = 1,
BfCompilerOptionFlag_EmitLineInfo = 2,
BfCompilerOptionFlag_WriteIR = 4,
BfCompilerOptionFlag_GenerateOBJ = 8,
BfCompilerOptionFlag_NoFramePointerElim = 0x10,
BfCompilerOptionFlag_ClearLocalVars = 0x20,
BfCompilerOptionFlag_ArrayBoundsCheck = 0x40,
BfCompilerOptionFlag_EmitDynamicCastCheck = 0x80,
BfCompilerOptionFlag_EnableObjectDebugFlags = 0x100,
BfCompilerOptionFlag_EmitObjectAccessCheck = 0x200,
BfCompilerOptionFlag_EnableCustodian = 0x400,
BfCompilerOptionFlag_EnableRealtimeLeakCheck = 0x800,
BfCompilerOptionFlag_EnableSideStack = 0x1000,
BfCompilerOptionFlag_EnableHotSwapping = 0x2000
};
BF_IMPORT void BF_CALLTYPE BfCompiler_Delete(void* bfCompiler);
BF_EXPORT void BF_CALLTYPE BfCompiler_SetOptions(void* bfCompiler, void* hotProject, int hotIdx,
int machineType, int toolsetType, int simdSetting, int allocStackCount, int maxWorkerThreads,
BfCompilerOptionFlags optionFlags, const char* mallocLinkName, const char* freeLinkName);
BF_IMPORT void BF_CALLTYPE BfCompiler_ClearBuildCache(void* bfCompiler);
BF_IMPORT bool BF_CALLTYPE BfCompiler_Compile(void* bfCompiler, void* bfPassInstance, const char* outputPath);
BF_IMPORT float BF_CALLTYPE BfCompiler_GetCompletionPercentage(void* bfCompiler);
BF_IMPORT const char* BF_CALLTYPE BfCompiler_GetOutputFileNames(void* bfCompiler, void* bfProject, bool* hadOutputChanges);
BF_IMPORT const char* BF_CALLTYPE BfCompiler_GetUsedOutputFileNames(void* bfCompiler, void* bfProject, bool flushQueuedHotFiles, bool* hadOutputChanges);
BF_IMPORT void* BF_CALLTYPE BfSystem_CreateParser(void* bfSystem, void* bfProject);
BF_IMPORT void BF_CALLTYPE BfParser_SetSource(void* bfParser, const char* data, int length, const char* fileName);
BF_IMPORT void BF_CALLTYPE BfParser_SetCharIdData(void* bfParser, uint8* data, int length);
BF_IMPORT bool BF_CALLTYPE BfParser_Parse(void* bfParser, void* bfPassInstance, bool compatMode);
BF_IMPORT bool BF_CALLTYPE BfParser_Reduce(void* bfParser, void* bfPassInstance);
BF_IMPORT bool BF_CALLTYPE BfParser_BuildDefs(void* bfParser, void* bfPassInstance, void* resolvePassData, bool fullRefresh);
//////////////////////////////////////////////////////////////////////////
BF_IMPORT void* BF_CALLTYPE BfSystem_Create();
BF_IMPORT void BF_CALLTYPE BfSystem_ReportMemory(void* bfSystem);
BF_IMPORT void BF_CALLTYPE BfSystem_Delete(void* bfSystem);
BF_IMPORT void* BF_CALLTYPE BfSystem_CreatePassInstance(void* bfSystem);
BF_IMPORT void* BF_CALLTYPE BfSystem_CreateCompiler(void* bfSystem, bool isResolveOnly);
BF_IMPORT void* BF_CALLTYPE BfSystem_CreateProject(void* bfSystem, const char* projectName);
BF_IMPORT void BF_CALLTYPE BfParser_Delete(void* bfParser);
BF_IMPORT void BF_CALLTYPE BfSystem_AddTypeOptions(void* bfSystem, const char* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 arrayBoundsCheck,
int32 initLocalVariables, int32 emitDynamicCastCheck, int32 emitObjectAccessCheck, int32 allocStackTraceDepth);
//////////////////////////////////////////////////////////////////////////
BF_IMPORT void BF_CALLTYPE BfProject_SetDisabled(void* bfProject, bool disabled);
BF_IMPORT void BF_CALLTYPE BfProject_SetOptions(void* bfProject, int targetType, const char* startupObject, const char* preprocessorMacros,
int optLevel, int ltoType, bool mergeFunctions, bool combineLoads, bool vectorizeLoops, bool vectorizeSLP);
BF_IMPORT void BF_CALLTYPE BfProject_ClearDependencies(void* bfProject);
BF_IMPORT void BF_CALLTYPE BfProject_AddDependency(void* bfProject, void* depProject);
//////////////////////////////////////////////////////////////////////////
BF_IMPORT const char* BF_CALLTYPE BfPassInstance_PopOutString(void* bfPassInstance);
BF_IMPORT void BF_CALLTYPE BfPassInstance_Delete(void* bfPassInstance);
//////////////////////////////////////////////////////////////////////////
BF_IMPORT const char* BF_CALLTYPE VSSupport_Find();
//////////////////////////////////////////////////////////////////////////
USING_NS_BF;
BootApp* Beefy::gApp = NULL;
uint32 gConsoleFGColor = 0;
uint32 gConsoleBGColor = 0;
static bool GetConsoleColor(uint32& fgColor, uint32& bgColor)
{
#ifdef _WIN32
static uint32 consoleColors[16] = { 0xff000000, 0xff000080, 0xff008000, 0xff008080, 0xff800000, 0xff800080, 0xff808000, 0xffc0c0c0,
0xff808080, 0xff0000ff, 0xff00ff00, 0xff00ffff, 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff };
CONSOLE_SCREEN_BUFFER_INFO screenBuffInfo = { 0 };
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &screenBuffInfo);
fgColor = consoleColors[screenBuffInfo.wAttributes & 0xF];
bgColor = consoleColors[(screenBuffInfo.wAttributes >> 4) & 0xF];
return true;
#else
fgColor = 0xFF808080;
bgColor = 0xFF000000;
return false;
#endif
}
static WORD GetColorCode(uint32 color)
{
WORD code = 0;
#ifdef _WIN32
if (((color >> 0) & 0xFF) > 0x40)
code |= FOREGROUND_BLUE;
if (((color >> 8) & 0xFF) > 0x40)
code |= FOREGROUND_GREEN;
if (((color >> 16) & 0xFF) > 0x40)
code |= FOREGROUND_RED;
if ((((color >> 0) & 0xFF) > 0xC0) ||
(((color >> 8) & 0xFF) > 0xC0) ||
(((color >> 16) & 0xFF) > 0xC0))
code |= FOREGROUND_INTENSITY;
#endif
return code;
}
static bool SetConsoleColor(uint32 fgColor, uint32 bgColor)
{
#ifdef _WIN32
WORD attr = GetColorCode(fgColor) | (GetColorCode(bgColor) << 4);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attr);
SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), attr);
return true;
#else
return false;
#endif
}
BootApp::BootApp()
{
Targets_Create();
mVerbosity = Verbosity_Normal;
mTargetType = BfTargetType_BeefConsoleApplication;
//char str[MAX_PATH];
//GetModuleFileNameA(NULL, str, MAX_PATH);
//mInstallDir = GetFileDir(str) + "/";
//getcwd(str, MAX_PATH);
//mStartupDir = str;
//mStartupDir += "/";
//mDoClean = false;
mHadCmdLine = false;
mShowedHelp = false;
mHadErrors = false;
mSystem = NULL;
mCompiler = NULL;
mProject = NULL;
#ifdef BF_PLATFORM_WINDOWS
mOptLevel = BfOptLevel_OgPlus;
mToolset = BfToolsetType_Microsoft;
#else
mOptLevel = BfOptLevel_O0;
mToolset = BfToolsetType_GNU;
#endif
mEmitIR = false;
GetConsoleColor(gConsoleFGColor, gConsoleBGColor);
}
BootApp::~BootApp()
{
Targets_Delete();
}
void BootApp::OutputLine(const String& text, OutputPri outputPri)
{
if (mLogFile.IsOpen())
{
mLogFile.WriteSNZ(text);
mLogFile.WriteSNZ("\n");
}
if (outputPri == OutputPri_Error)
mHadErrors = true;
switch (outputPri)
{
case OutputPri_Low:
if (mVerbosity < Verbosity_Detailed)
return;
break;
case OutputPri_Normal:
if (mVerbosity < Verbosity_Normal)
return;
break;
case OutputPri_High:
case OutputPri_Warning:
case OutputPri_Error:
if (mVerbosity < Verbosity_Minimal)
return;
break;
}
if (outputPri == OutputPri_Warning)
{
SetConsoleColor(0xFFFFFF00, gConsoleBGColor);
std::cerr << text.c_str() << std::endl;
SetConsoleColor(gConsoleFGColor, gConsoleBGColor);
}
else if (outputPri == OutputPri_Error)
{
SetConsoleColor(0xFFFF0000, gConsoleBGColor);
std::cerr << text.c_str() << std::endl;
SetConsoleColor(gConsoleFGColor, gConsoleBGColor);
}
else
std::cout << text.c_str() << std::endl;
}
void BootApp::Fail(const String& error)
{
if (mLogFile.IsOpen())
mLogFile.WriteSNZ("FAIL: " + error + "\n");
std::cerr << "FAIL: " << error.c_str() << std::endl;
mHadErrors = true;
}
bool BootApp::HandleCmdLine(const String &cmd, const String& param)
{
mHadCmdLine = true;
bool wantedParam = false;
if ((cmd == "--help") || (cmd == "-h") || (cmd == "/?"))
{
mShowedHelp = true;
std::cout << "BeefBoot - Beef bootstrapping tool" << std::endl;
return false;
}
else if (cmd == "--src")
{
mRequestedSrc.Add(param);
wantedParam = true;
}
else if (cmd == "--verbosity")
{
if (param == "quiet")
mVerbosity = Verbosity_Quiet;
else if (param == "minimal")
mVerbosity = Verbosity_Minimal;
else if (param == "normal")
mVerbosity = Verbosity_Normal;
else if (param == "detailed")
mVerbosity = Verbosity_Detailed;
else if (param == "diagnostic")
mVerbosity = Verbosity_Diagnostic;
else
{
Fail(StrFormat("Invalid verbosity level: '%s'", param.c_str()));
return false;
}
wantedParam = true;
}
else if (cmd == "--define")
{
if (!mDefines.IsEmpty())
mDefines += "\n";
mDefines += param;
wantedParam = true;
}
else if (cmd == "--startup")
{
mStartupObject = param;
wantedParam = true;
}
else if (cmd == "--out")
{
mTargetPath = param;
wantedParam = true;
}
else if (cmd == "--linkparams")
{
mLinkParams = param;
wantedParam = true;
}
else if (cmd == "-Og+")
{
mOptLevel = BfOptLevel_OgPlus;
}
else if (cmd == "-O0")
{
mOptLevel = BfOptLevel_O0;
}
else if (cmd == "-O1")
{
mOptLevel = BfOptLevel_O1;
}
else if (cmd == "-O2")
{
mOptLevel = BfOptLevel_O2;
}
else if (cmd == "-O3")
{
mOptLevel = BfOptLevel_O3;
}
else if (cmd == "-gnu")
{
mToolset = BfToolsetType_GNU;
}
else if (cmd == "-emitir")
{
mEmitIR = true;
}
else
{
Fail("Unknown option: " + cmd);
return false;
}
if ((wantedParam) && (param.empty()))
{
Fail(StrFormat("Parameter expected for '%s'", cmd.c_str()));
return false;
}
else if ((!wantedParam) && (!param.empty()))
{
Fail(StrFormat("No parameter expected for '%s'", cmd.c_str()));
return false;
}
return true;
}
bool BootApp::Init()
{
char* cwdPtr = getcwd(NULL, 0);
mWorkingDir = cwdPtr;
free(cwdPtr);
if (mTargetPath.IsEmpty())
{
Fail("'Out' path not specified");
}
if (mRequestedSrc.IsEmpty())
{
Fail("No source specified");
}
return !mHadErrors;
}
void BootApp::QueueFile(const StringImpl& path)
{
String ext;
ext = GetFileExtension(path);
if ((ext.Equals(".bf", StringImpl::CompareKind_OrdinalIgnoreCase)) ||
(ext.Equals(".cs", StringImpl::CompareKind_OrdinalIgnoreCase)))
{
int len;
const char* data = LoadTextData(path, &len);
if (data == NULL)
{
Fail(StrFormat("Unable to load file '%s'", path.c_str()));
return;
}
bool worked = true;
void* bfParser = BfSystem_CreateParser(mSystem, mProject);
BfParser_SetSource(bfParser, data, len, path.c_str());
//bfParser.SetCharIdData(charIdData);
worked &= BfParser_Parse(bfParser, mPassInstance, false);
worked &= BfParser_Reduce(bfParser, mPassInstance);
worked &= BfParser_BuildDefs(bfParser, mPassInstance, NULL, false);
delete data;
}
}
void BootApp::QueuePath(const StringImpl& path)
{
if (DirectoryExists(path))
{
for (auto& fileEntry : FileEnumerator(path, FileEnumerator::Flags_Files))
{
String filePath = fileEntry.GetFilePath();
String fileName;
fileName = GetFileName(filePath);
QueueFile(filePath);
}
for (auto& fileEntry : FileEnumerator(path, FileEnumerator::Flags_Directories))
{
String childPath = fileEntry.GetFilePath();
String dirName;
dirName = GetFileName(childPath);
if (dirName == "build")
continue;
QueuePath(childPath);
}
}
else
{
QueueFile(path);
}
}
static void CompileThread(void* param)
{
BfpThread_SetName(NULL, "CompileThread", NULL);
BootApp* app = (BootApp*)param;
BfCompiler_ClearBuildCache(app->mCompiler);
if (!BfCompiler_Compile(app->mCompiler, app->mPassInstance, app->mBuildDir.c_str()))
app->mHadErrors = true;
}
void BootApp::DoCompile()
{
#ifdef BFBUILD_MAIN_THREAD_COMPILE
mOutputDirectory = outputDirectory;
CompileThread(this);
#else
WorkThreadFunc workThread;
workThread.Start(CompileThread, this);
int lastProgressTicks = 0;
bool showProgress = mVerbosity >= Verbosity_Normal;
int progressSize = 30;
if (showProgress)
{
std::cout << "[";
for (int i = 0; i < progressSize; i++)
std::cout << " ";
std::cout << "]";
for (int i = 0; i < progressSize + 1; i++)
std::cout << "\b";
std::cout.flush();
}
while (true)
{
bool isDone = workThread.WaitForFinish(100);
float pct = BfCompiler_GetCompletionPercentage(mCompiler);
if (isDone)
pct = 1.0;
int progressTicks = (int)(pct * progressSize + 0.5f);
while (progressTicks > lastProgressTicks)
{
if (showProgress)
{
std::cout << "*";
std::cout.flush();
}
lastProgressTicks++;
}
if (isDone)
break;
}
if (showProgress)
std::cout << std::endl;
#endif
}
struct OutputContext
{
bool mIsError;
BfpFile* mFile;
};
static void OutputThread(void* param)
{
OutputContext* context = (OutputContext*)param;
String queuedStr;
while (true)
{
char data[1024];
BfpFileResult result;
int bytesRead = (int)BfpFile_Read(context->mFile, data, 1023, -1, &result);
if ((result != BfpFileResult_Ok) && (result != BfpFileResult_PartialData))
return;
data[bytesRead] = 0;
if (context->mIsError)
{
std::cerr << data;
std::cerr.flush();
}
else
{
std::cout << data;
std::cout.flush();
}
if (gApp->mLogFile.IsOpen())
{
// This is to ensure that error and output lines are not merged together, though they may interleave
queuedStr.Append(data, bytesRead);
while (true)
{
int crPos = (int)queuedStr.IndexOf('\n');
if (crPos == -1)
break;
AutoCrit autoCrit(gApp->mLogCritSect);
if (context->mIsError)
gApp->mLogFile.WriteSNZ("err> ");
else
gApp->mLogFile.WriteSNZ("out> ");
int endPos = crPos;
if ((endPos > 0) && (queuedStr[endPos - 1] == '\r'))
endPos--;
gApp->mLogFile.Write((void*)queuedStr.c_str(), endPos);
gApp->mLogFile.WriteSNZ("\n");
queuedStr.Remove(0, crPos + 1);
}
}
}
}
bool BootApp::QueueRun(const String& fileName, const String& args, const String& workingDir, BfpSpawnFlags extraFlags)
{
OutputLine(StrFormat("EXECUTING: %s %s", fileName.c_str(), args.c_str()), OutputPri_Low);
BfpSpawnFlags spawnFlags = (BfpSpawnFlags)(BfpSpawnFlag_NoWindow | BfpSpawnFlag_RedirectStdOutput | BfpSpawnFlag_RedirectStdError | extraFlags);
BfpSpawn* spawn = BfpSpawn_Create(fileName.c_str(), args.c_str(), workingDir.c_str(), NULL, spawnFlags, NULL);
if (spawn == NULL)
{
Fail(StrFormat("Failed to execute '%s'", fileName.c_str()));
return false;
}
int exitCode = 0;
OutputContext outputContext;;
outputContext.mIsError = false;
OutputContext errorContext;
errorContext.mIsError = false;
BfpSpawn_GetStdHandles(spawn, NULL, &outputContext.mFile, &errorContext.mFile);
BfpThread* outputThread = BfpThread_Create(OutputThread, (void*)&outputContext);
BfpThread* errorThread = BfpThread_Create(OutputThread, (void*)&errorContext);
BfpSpawn_WaitFor(spawn, -1, &exitCode, NULL);
if (outputContext.mFile != NULL)
BfpFile_Close(outputContext.mFile, NULL);
if (errorContext.mFile != NULL)
BfpFile_Close(errorContext.mFile, NULL);
BfpThread_WaitFor(outputThread, -1);
BfpThread_WaitFor(errorThread, -1);
BfpThread_Release(outputThread);
BfpThread_Release(errorThread);
BfpSpawn_Release(spawn);
if (exitCode != 0)
{
Fail(StrFormat("Exit code returned: %d", exitCode));
return false;
}
return true;
}
#ifdef BF_PLATFORM_WINDOWS
void BootApp::DoLinkMS()
{
String vsStr = VSSupport_Find();
int toolIdx = (int)vsStr.IndexOf("TOOL64\t");
int toolCrIdx = (int)vsStr.IndexOf('\n', toolIdx + 1);
if ((toolIdx == -1) || (toolCrIdx == -1))
{
Fail("Failed to detect Visual Studio configuration. Is Visual Studio 2015 or later installed?");
return;
}
String linkerPath = vsStr.Substring(toolIdx + 7, toolCrIdx - toolIdx - 7);
linkerPath.Append("\\link.exe");
String linkLine;
String targetPath = mTargetPath;
bool hadOutputChanges;
const char* result = BfCompiler_GetUsedOutputFileNames(mCompiler, mProject, true, &hadOutputChanges);
if (result == NULL)
return;
std::string fileNamesStr;
fileNamesStr += result;
if (fileNamesStr.length() == 0)
return;
int curIdx = -1;
while (curIdx < (int)fileNamesStr.length())
{
int nextBr = (int)fileNamesStr.find('\n', curIdx + 1);
if (nextBr == -1)
nextBr = (int)fileNamesStr.length();
linkLine.Append(fileNamesStr.substr(curIdx + 1, nextBr - curIdx - 1));
linkLine.Append(" ");
curIdx = nextBr;
}
linkLine.Append("-out:");
IDEUtils::AppendWithOptionalQuotes(linkLine, targetPath);
linkLine.Append(" ");
if (mTargetType == BfTargetType_BeefConsoleApplication)
linkLine.Append("-subsystem:console ");
else
linkLine.Append("-subsystem:windows ");
linkLine.Append("-defaultlib:libcmtd ");
linkLine.Append("-nologo ");
linkLine.Append("-pdb:");
int lastDotPos = (int)targetPath.LastIndexOf('.');
if (lastDotPos == -1)
lastDotPos = (int)targetPath.length();
auto pdbName = String(targetPath, 0, lastDotPos);
pdbName.Append(".pdb");
IDEUtils::AppendWithOptionalQuotes(linkLine, pdbName);
linkLine.Append(" ");
linkLine.Append("-debug ");
int checkIdx = 0;
while (true)
{
int libIdx = (int)vsStr.IndexOf("LIB64\t", checkIdx);
if (libIdx == -1)
break;
int libCrIdx = (int)vsStr.IndexOf('\n', libIdx + 1);
if (libCrIdx == -1)
break;
String libPath = vsStr.Substring(libIdx + 6, libCrIdx - libIdx - 6);
linkLine.Append("-libpath:\"");
linkLine.Append(libPath);
linkLine.Append("\" ");
checkIdx = libCrIdx + 1;
}
linkLine.Append(mLinkParams);
BfpSpawnFlags flags = BfpSpawnFlag_None;
if (true)
{
//if (linkLine.HasMultibyteChars())
if (true)
flags = (BfpSpawnFlags)(BfpSpawnFlag_UseArgsFile | BfpSpawnFlag_UseArgsFile_Native | BfpSpawnFlag_UseArgsFile_BOM);
else
flags = (BfpSpawnFlags)(BfpSpawnFlag_UseArgsFile);
}
auto runCmd = QueueRun(linkerPath, linkLine, mWorkingDir, flags);
}
#endif
void BootApp::DoLinkGNU()
{
String linkerPath = "/usr/bin/c++";
String linkLine;
String targetPath = mTargetPath;
bool hadOutputChanges;
const char* result = BfCompiler_GetUsedOutputFileNames(mCompiler, mProject, true, &hadOutputChanges);
if (result == NULL)
return;
std::string fileNamesStr;
fileNamesStr += result;
if (fileNamesStr.length() == 0)
return;
int curIdx = -1;
while (curIdx < (int)fileNamesStr.length())
{
int nextBr = (int)fileNamesStr.find('\n', curIdx + 1);
if (nextBr == -1)
nextBr = (int)fileNamesStr.length();
linkLine.Append(fileNamesStr.substr(curIdx + 1, nextBr - curIdx - 1));
linkLine.Append(" ");
curIdx = nextBr;
}
linkLine.Append("-o ");
IDEUtils::AppendWithOptionalQuotes(linkLine, targetPath);
linkLine.Append(" ");
linkLine.Append("-g ");
linkLine.Append("-debug -no-pie ");
linkLine.Append(mLinkParams);
auto runCmd = QueueRun(linkerPath, linkLine, mWorkingDir, true ? BfpSpawnFlag_UseArgsFile : BfpSpawnFlag_None);
}
bool BootApp::Compile()
{
DWORD startTick = BFTickCount();
mSystem = BfSystem_Create();
mCompiler = BfSystem_CreateCompiler(mSystem, false);
String projectName = GetFileName(mTargetPath);
int dotPos = (int)projectName.IndexOf('.');
if (dotPos != -1)
projectName.RemoveToEnd(dotPos);
mProject = BfSystem_CreateProject(mSystem, projectName.c_str());
int ltoType = 0;
BfProject_SetOptions(mProject, mTargetType, mStartupObject.c_str(), mDefines.c_str(), mOptLevel, ltoType, false, false, false, false);
mPassInstance = BfSystem_CreatePassInstance(mSystem);
Beefy::String exePath;
BfpGetStrHelper(exePath, [](char* outStr, int* inOutStrSize, BfpResult* result)
{
BfpSystem_GetExecutablePath(outStr, inOutStrSize, (BfpSystemResult*)result);
});
mBuildDir = GetFileDir(exePath) + "/build";
RecursiveCreateDirectory(mBuildDir + "/" + projectName);
BfCompilerOptionFlags optionFlags = (BfCompilerOptionFlags)(BfCompilerOptionFlag_EmitDebugInfo | BfCompilerOptionFlag_EmitLineInfo | BfCompilerOptionFlag_GenerateOBJ);
if (mEmitIR)
optionFlags = (BfCompilerOptionFlags)(optionFlags | BfCompilerOptionFlag_WriteIR);
int maxWorkerThreads = BfpSystem_GetNumLogicalCPUs(NULL);
if (maxWorkerThreads <= 1)
maxWorkerThreads = 6;
BfCompiler_SetOptions(mCompiler, NULL, 0, BfMachineType_x64, mToolset, BfSIMDSetting_SSE2, 1, maxWorkerThreads, optionFlags, "malloc", "free");
for (auto& srcName : mRequestedSrc)
{
String absPath = GetAbsPath(srcName, mWorkingDir);
QueuePath(absPath);
}
if (!mHadErrors)
{
DoCompile();
OutputLine(StrFormat("TIMING: Beef compiling: %0.1fs", (BFTickCount() - startTick) / 1000.0), OutputPri_Normal);
}
while (true)
{
const char* msg = BfPassInstance_PopOutString(mPassInstance);
if (msg == NULL)
break;
if ((strncmp(msg, ":warn ", 6) == 0))
{
OutputLine(msg + 6, OutputPri_Warning);
}
else if ((strncmp(msg, ":error ", 7) == 0))
{
OutputLine(msg + 7, OutputPri_Error);
}
else if ((strncmp(msg, ":med ", 5) == 0))
{
OutputLine(msg + 5, OutputPri_Normal);
}
else if ((strncmp(msg, ":low ", 5) == 0))
{
OutputLine(msg + 5, OutputPri_Low);
}
else if ((strncmp(msg, "ERROR(", 6) == 0) || (strncmp(msg, "ERROR:", 6) == 0))
{
OutputLine(msg, OutputPri_Error);
}
else if ((strncmp(msg, "WARNING(", 8) == 0) || (strncmp(msg, "WARNING:", 8) == 0))
{
OutputLine(msg, OutputPri_Warning);
}
else
OutputLine(msg);
}
if (!mHadErrors)
{
if (mVerbosity == Verbosity_Normal)
{
std::cout << "Linking " << mTargetPath.c_str() << "...";
std::cout.flush();
}
#ifdef BF_PLATFORM_WINDOWS
DoLinkMS();
#else
DoLinkGNU();
#endif
if (mVerbosity == Verbosity_Normal)
std::cout << std::endl;
}
BfPassInstance_Delete(mPassInstance);
BfCompiler_Delete(mCompiler);
BfSystem_Delete(mSystem);
return !mHadErrors;
}

80
BeefBoot/BootApp.h Normal file
View file

@ -0,0 +1,80 @@
#pragma once
#include "BeefBoot.h"
#include "BeefySysLib/FileStream.h"
#include "BeefySysLib/util/CritSect.h"
#include "BeefySysLib/util/String.h"
#include "BeefySysLib/util/Array.h"
#include "Compiler/BfSystem.h"
NS_BF_BEGIN
enum OutputPri
{
OutputPri_Low,
OutputPri_Normal,
OutputPri_High,
OutputPri_Warning,
OutputPri_Error,
OutputPri_Critical
};
enum Verbosity
{
Verbosity_Quiet,
Verbosity_Minimal,
Verbosity_Normal,
Verbosity_Detailed,
Verbosity_Diagnostic,
};
class BootApp
{
public:
CritSect mLogCritSect;
FileStream mLogFile;
Verbosity mVerbosity;
BfTargetType mTargetType;
bool mHadCmdLine;
bool mShowedHelp;
bool mHadErrors;
Array<String> mRequestedSrc;
BfOptLevel mOptLevel;
BfToolsetType mToolset;
bool mEmitIR;
String mBuildDir;
String mWorkingDir;
String mDefines;
String mStartupObject;
String mTargetPath;
String mLinkParams;
void* mSystem;
void* mCompiler;
void* mProject;
void* mPassInstance;
public:
void Fail(const String & error);
void OutputLine(const String& text, OutputPri outputPri = OutputPri_Normal);
bool QueueRun(const String& fileName, const String& args, const String& workingDir, BfpSpawnFlags extraFlags);
void QueueFile(const StringImpl& path);
void QueuePath(const StringImpl& path);
void DoCompile();
void DoLinkMS();
void DoLinkGNU();
public:
BootApp();
~BootApp();
bool HandleCmdLine(const String& cmd, const String& param);
bool Init();
bool Compile();
};
extern BootApp* gApp;
NS_BF_END

122
BeefBoot/CMakeLists.txt Normal file
View file

@ -0,0 +1,122 @@
cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
################### Variables. ####################
# Change if you want modify path or other values. #
###################################################
set(PROJECT_NAME BeefBoot)
# Output Variables
set(OUTPUT_DEBUG Debug/bin)
set(OUTPUT_RELEASE Release/bin)
############## CMake Project ################
# The main options of project #
#############################################
project(${PROJECT_NAME} CXX C)
# Define Release by default.
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
message(STATUS "Build type not specified: Use Debug by default.")
endif(NOT CMAKE_BUILD_TYPE)
# Definition of Macros
add_definitions(
-DIDEHELPER_EXPORTS
-DBFSYSLIB_DYNAMIC
-DUNICODE
-D_UNICODE
-DBF_NO_FBX
-DFT2_BUILD_LIBRARY
-DBFSYSLIB_DYNAMIC
)
include_directories(
.
../BeefySysLib/
../BeefySysLib/platform/linux
../BeefySysLib/third_party
../BeefySysLib/third_party/freetype/include
../
../extern/llvm-project_8_0_0/llvm/include
../extern/llvm-project_8_0_0/llvm/lib/Target
../IDEHelper
)
############## Artefacts Output #################
# Defines outputs , depending Debug or Release. #
#################################################
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(
-D_DEBUG
)
include_directories(
../extern/llvm_linux_8_0_0/include
../extern/llvm_linux_8_0_0/lib/Target/X86
)
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/${OUTPUT_DEBUG}")
set(LLVM_LIB "${CMAKE_CURRENT_SOURCE_DIR}/../extern/llvm_linux_8_0_0/lib")
else()
include_directories(
../extern/llvm_linux_rel_8_0_0/include
../extern/llvm_linux_rel_8_0_0/lib/Target/X86
)
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/${OUTPUT_RELEASE}")
set(LLVM_LIB "${CMAKE_CURRENT_SOURCE_DIR}/../extern/llvm_linux_rel_8_0_0/lib")
endif()
################### Dependencies ##################
# Add Dependencies to project. #
###################################################
option(BUILD_DEPENDS
"Build other CMake project."
ON
)
# Dependencies : disable BUILD_DEPENDS to link with lib already build.
if(BUILD_DEPENDS)
else()
endif()
################# Flags ################
# Defines Flags for Windows and Linux. #
########################################
if(MSVC)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W3 /MD /MDd /Od /EHsc")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /W3 /GL /Od /Oi /Gy /EHsc")
endif(MSVC)
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-multichar -Wno-invalid-offsetof")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
endif()
endif(NOT MSVC)
################ Files ################
# -- Add files to project. -- #
#######################################
file(GLOB SRC_FILES
BeefBoot.cpp
BootApp.cpp
)
# Add executable to build.
add_executable(${PROJECT_NAME}
${SRC_FILES}
)
# Link with other dependencies.
if(MSVC)
target_link_libraries(${PROJECT_NAME} BeefySysLib IDEHelper kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib)
else()
target_link_libraries(${PROJECT_NAME} BeefySysLib IDEHelper tinfo
#${LLVM_LIB}/libLLVMMC.a
)
endif()

92
BeefBuild/BeefProj.toml Normal file
View file

@ -0,0 +1,92 @@
FileVersion = 1
Dependencies = {Beefy2D = "*", corlib = "*"}
[Project]
Name = "BeefBuild"
StartupObject = "BeefBuild.Program"
[Configs.Debug.Win32]
TargetName = ""
OtherLinkFlags = ""
OptimizationLevel = "O0"
[Configs.Debug.Win64]
TargetDirectory = "$(WorkspaceDir)/../IDE/dist"
TargetName = "$(ProjectName)_d"
OtherLinkFlags = "$(LinkFlags) Comdlg32.lib kernel32.lib user32.lib advapi32.lib shell32.lib IDEHelper64_d.lib BeefySysLib64_d.lib curl.lib git2.lib libssh2.lib Winhttp.lib Rpcrt4.lib Ole32.lib"
CLibType = "Dynamic"
BeefLibType = "DynamicDebug"
DebugCommandArguments = "-workspace=."
DebugWorkingDirectory = "$(WorkspaceDir)/../IDE/dist"
EnvironmentVars = ["_NO_DEBUG_HEAP=1"]
PreprocessorMacros = ["DEBUG", "CLI"]
[Configs.Debug.Linux64]
TargetDirectory = "$(WorkspaceDir)/../IDE/dist"
TargetName = "$(ProjectName)_d"
OtherLinkFlags = "./libBeefRT_d.so ./libIDEHelper_d.so ./libBeefySysLib_d.so ../../extern/llvm_linux_8_0_0/lib/libLLVMCore.a ../../extern/llvm_linux_8_0_0/lib/libLLVMMC.a ../../extern/llvm_linux_8_0_0/lib/libLLVMMCParser.a ../../extern/llvm_linux_8_0_0/lib/libLLVMCodeGen.a ../../extern/llvm_linux_8_0_0/lib/libLLVMX86Disassembler.a ../../extern/llvm_linux_8_0_0/lib/libLLVMMCDisassembler.a ../../extern/llvm_linux_8_0_0/lib/libLLVMSupport.a ../../extern/llvm_linux_8_0_0/lib/libLLVMX86Info.a ../../extern/llvm_linux_8_0_0/lib/libLLVMX86Utils.a ../../extern/llvm_linux_8_0_0/lib/libLLVMX86AsmPrinter.a ../../extern/llvm_linux_8_0_0/lib/libLLVMX86Desc.a ../../extern/llvm_linux_8_0_0/lib/libLLVMObject.a ../../extern/llvm_linux_8_0_0/lib/libLLVMBitReader.a ../../extern/llvm_linux_8_0_0/lib/libLLVMAsmParser.a ../../extern/llvm_linux_8_0_0/lib/libLLVMTarget.a ../../extern/llvm_linux_8_0_0/lib/libLLVMX86CodeGen.a ../../extern/llvm_linux_8_0_0/lib/libLLVMScalarOpts.a ../../extern/llvm_linux_8_0_0/lib/libLLVMInstCombine.a ../../extern/llvm_linux_8_0_0/lib/libLLVMSelectionDAG.a ../../extern/llvm_linux_8_0_0/lib/libLLVMProfileData.a ../../extern/llvm_linux_8_0_0/lib/libLLVMTransformUtils.a ../../extern/llvm_linux_8_0_0/lib/libLLVMAnalysis.a ../../extern/llvm_linux_8_0_0/lib/libLLVMX86AsmParser.a ../../extern/llvm_linux_8_0_0/lib/libLLVMAsmPrinter.a ../../extern/llvm_linux_8_0_0/lib/libLLVMBitWriter.a ../../extern/llvm_linux_8_0_0/lib/libLLVMVectorize.a ../../extern/llvm_linux_8_0_0/lib/libLLVMipo.a ../../extern/llvm_linux_8_0_0/lib/libLLVMInstrumentation.a ../../extern/llvm_linux_8_0_0/lib/libLLVMDebugInfoDWARF.a ../../extern/llvm_linux_8_0_0/lib/libLLVMDebugInfoPDB.a ../../extern/llvm_linux_8_0_0/lib/libLLVMDebugInfoCodeView.a ../../extern/llvm_linux_8_0_0/lib/libLLVMGlobalISel.a ../../extern/llvm_linux_8_0_0/lib/libLLVMBinaryFormat.a ../../extern/llvm_linux_8_0_0/lib/libLLVMDemangle.a -ltinfo -Wl,-rpath -Wl,."
CLibType = "Dynamic"
DebugCommandArguments = "-proddir=..\\ -config=Debug -platform=Win64"
DebugWorkingDirectory = "$(WorkspaceDir)/../IDE/dist"
PreprocessorMacros = ["DEBUG", "CLI"]
[Configs.Release.Linux64]
TargetDirectory = "$(WorkspaceDir)/../IDE/dist"
OtherLinkFlags = "./libBeefRT.so ./libIDEHelper.so ./libBeefySysLib.so ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMCore.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMMC.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMMCParser.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMCodeGen.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMX86Disassembler.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMMCDisassembler.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMSupport.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMX86Info.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMX86Utils.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMX86AsmPrinter.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMX86Desc.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMObject.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMBitReader.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMAsmParser.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMTarget.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMX86CodeGen.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMScalarOpts.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMInstCombine.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMSelectionDAG.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMProfileData.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMTransformUtils.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMAnalysis.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMX86AsmParser.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMAsmPrinter.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMBitWriter.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMVectorize.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMipo.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMInstrumentation.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMDebugInfoDWARF.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMDebugInfoPDB.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMDebugInfoCodeView.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMGlobalISel.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMBinaryFormat.a ../../extern/llvm_linux_rel_8_0_0/lib/libLLVMDemangle.a -ltinfo -Wl,-rpath -Wl,."
CLibType = "Dynamic"
DebugCommandArguments = "-proddir=..\\ -config=Debug -platform=Win64"
DebugWorkingDirectory = "$(WorkspaceDir)/../IDE/dist"
PreprocessorMacros = ["CLI"]
[Configs.Release.Win32]
TargetName = ""
OtherLinkFlags = ""
OptimizationLevel = "O0"
[Configs.Release.Win64]
TargetDirectory = "$(WorkspaceDir)/../IDE/dist"
OtherLinkFlags = "$(LinkFlags) Comdlg32.lib kernel32.lib user32.lib advapi32.lib shell32.lib IDEHelper64.lib BeefySysLib64.lib"
CLibType = "Dynamic"
DebugCommandArguments = "-proddir=..\\..\\BeefPerf -config=Release"
DebugWorkingDirectory = "$(ProjectDir)\\dist"
EnvironmentVars = ["_NO_DEBUG_HEAP=1"]
PreprocessorMacros = ["RELEASE", "CLI"]
OptimizationLevel = "O0"
[Configs.Debug2.Win32]
TargetName = ""
OtherLinkFlags = ""
OptimizationLevel = "O0"
[Configs.Debug2.Win64]
TargetDirectory = "$(WorkspaceDir)/dist"
TargetName = "$(ProjectName)_d2"
OtherLinkFlags = "Comdlg32.lib kernel32.lib user32.lib advapi32.lib shell32.lib Beef042RT64_d.lib IDEHelper64_d.lib BeefySysLib64_d.lib"
CLibType = "Dynamic"
DebugCommandArguments = "-proddir=c:\\beef\\IDEHelper\\Tests -test"
DebugWorkingDirectory = "c:\\beef\\IDE\\dist"
EnvironmentVars = ["_NO_DEBUG_HEAP=1"]
PreprocessorMacros = ["DEBUG", "CLI"]
OptimizationLevel = "OgPlus"
[Configs.Test.Win32]
OtherLinkFlags = "BeefRT32_d.lib"
[Configs.Test.Win64]
OtherLinkFlags = "Beef042RT64_d.lib"
[Configs.Paranoid.Win32]
CLibType = "Static"
BeefLibType = "Static"
[Configs.Paranoid.Win64]
CLibType = "Static"
BeefLibType = "Static"
[ProjectFolder]
[[ProjectFolder.Items]]
Type = "Folder"
Path = "../IDE/src"
Name = "ide"
AutoInclude = true

92
BeefBuild/BeefSpace.toml Normal file
View file

@ -0,0 +1,92 @@
FileVersion = 1
Projects = {BeefBuild = {Path = "."}, corlib = {Path = "../IDE\\corlib"}, Beefy2D = {Path = "../BeefLibs/Beefy2D"}, IDEHelper = {Path = "../IDEHelper"}, Debugger64 = {Path = "../Debugger64"}, BeefySysLib = {Path = "../BeefySysLib"}}
[Workspace]
StartupProject = "BeefBuild"
[Configs.Debug.Win32]
Toolset = "GNU"
BfOptimizationLevel = "O0"
InitLocalVariables = true
EmitObjectAccessCheck = false
EnableCustodian = false
EnableRealtimeLeakCheck = false
AllocStackTraceDepth = 0
ConfigSelections = {IDEHelper = {Enabled = false}}
[Configs.Debug.Win64]
EnableSideStack = true
ConfigSelections = {IDEHelper = {Enabled = false}, Debugger64 = {Enabled = false}, BeefySysLib = {Enabled = false}}
[Configs.Release.Win32]
Toolset = "GNU"
BfOptimizationLevel = "OgPlus"
EmitDebugInfo = "No"
AllocStackTraceDepth = 0
ConfigSelections = {IDEHelper = {Enabled = false}}
[Configs.Release.Win64]
[Configs.Release.Win64z]
EnableObjectDebugFlags = true
EmitObjectAccessCheck = true
EnableCustodian = true
EnableRealtimeLeakCheck = true
AllocStackTraceDepth = 0
[Configs.Debug-IDE.Win32]
Toolset = "GNU"
BfOptimizationLevel = "O0"
EmitDebugInfo = "No"
ArrayBoundsCheck = false
EmitDynamicCastCheck = false
EnableObjectDebugFlags = false
EmitObjectAccessCheck = false
EnableCustodian = false
EnableRealtimeLeakCheck = false
AllocStackTraceDepth = 0
ConfigSelections = {corlib = {Config = "Debug"}, Beefy2D = {Config = "Debug"}, IDEHelper = {Config = "Debug"}, Debugger64 = {Config = "Debug"}, BeefySysLib = {Config = "Debug"}}
[Configs.Debug-IDE.Win64]
Toolset = "GNU"
BfOptimizationLevel = "O0"
EmitDebugInfo = "No"
ArrayBoundsCheck = false
EmitDynamicCastCheck = false
EnableObjectDebugFlags = false
EmitObjectAccessCheck = false
EnableCustodian = false
EnableRealtimeLeakCheck = false
ConfigSelections = {corlib = {Config = "Debug"}, Beefy2D = {Config = "Debug"}, IDEHelper = {Config = "Debug"}, Debugger64 = {Config = "Debug"}, BeefySysLib = {Config = "Debug"}}
[Configs.Debug2.Win32]
Toolset = "GNU"
BfOptimizationLevel = "O0"
EmitDebugInfo = "No"
ArrayBoundsCheck = false
EmitDynamicCastCheck = false
EnableObjectDebugFlags = false
EmitObjectAccessCheck = false
EnableCustodian = false
EnableRealtimeLeakCheck = false
AllocStackTraceDepth = 0
ConfigSelections = {corlib = {Config = "Debug"}, Beefy2D = {Config = "Debug"}, IDEHelper = {Config = "Debug"}, Debugger64 = {Config = "Debug"}, BeefySysLib = {Config = "Debug"}}
[Configs.Debug2.Win64]
PreprocessorMacros = ["NEWFONT"]
IntermediateType = "ObjectAndIRCode"
ConfigSelections = {corlib = {Config = "Debug"}, Beefy2D = {Config = "Debug"}, IDEHelper = {Config = "Debug"}, Debugger64 = {Config = "Debug"}, BeefySysLib = {Config = "Debug"}}
[Configs.Paranoid.Win32]
Toolset = "GNU"
COptimizationLevel = "O2"
[Configs.Paranoid.Win64]
Toolset = "GNU"
COptimizationLevel = "O2"
[Configs.Test.Win32]
COptimizationLevel = "O2"
[Configs.Test.Win64]
COptimizationLevel = "O2"

250
BeefBuild/src/BuildApp.bf Normal file
View file

@ -0,0 +1,250 @@
using IDE;
using System;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;
using IDE.Util;
namespace BeefBuild
{
class BuildApp : IDEApp
{
const int cProgressSize = 30;
int mProgressIdx = 0;
public bool mIsTest;
public bool mIsFailTest;
/*void Test()
{
/*CURL.Easy easy = new CURL.Easy();
easy.SetOpt(.URL, "http://raw.githubusercontent.com/alexcrichton/curl-rust/master/Cargo.toml");
easy.SetOpt(.Verbose, true);
easy.Perform();*/
Transfer transfer = new Transfer();
//transfer.Setup("https://curl.haxx.se/download/curl-7.57.0.zip");
transfer.Setup("https://secure-appldnld.apple.com/itunes12/091-56359-20171213-EDF2198A-E039-11E7-9A9F-D21A1E4B8CED/iTunes64Setup.exe");
transfer.PerformBackground();
while (transfer.IsRunning)
{
Thread.Sleep(100);
Console.WriteLine("{0}/{1} @{2}Kps", transfer.BytesReceived, transfer.TotalBytes, transfer.BytesPerSecond / 1024);
}
#unwarn
let result = transfer.GetResult();
}*/
public this()
{
//mConfigName.Clear();
//mPlatformName.Clear();
mVerbosity = .Normal;
//Test();
}
public override void Init()
{
if (mConfigName.IsEmpty)
{
mConfigName.Set(mIsTest ? "Test" : "Debug");
}
if (mPlatformName.IsEmpty)
{
mPlatformName.Set(sPlatform64Name);
}
mMainThread = Thread.CurrentThread;
if (mConfigName.IsEmpty)
Fail("Config not specified");
if (mPlatformName.IsEmpty)
Fail("Platform not specified");
base.Init();
mInitialized = true;
CreateBfSystems();
if (mWantsClean)
{
mBfBuildCompiler.ClearBuildCache();
mWantsClean = false;
}
if (mWorkspace.mDir == null)
{
mWorkspace.mDir = new String();
Directory.GetCurrentDirectory(mWorkspace.mDir);
}
if (mWorkspace.mDir != null)
{
mWorkspace.mName = new String();
Path.GetFileName(mWorkspace.mDir, mWorkspace.mName);
LoadWorkspace();
}
else
Fail("Workspace not specified");
if (mFailed)
return;
WorkspaceLoaded();
if (mIsTest)
{
RunTests(false);
}
else
Compile(.Normal, null);
}
public override bool HandleCommandLineParam(String key, String value)
{
if (value == null)
{
switch (key)
{
case "-test":
mIsTest = true;
return true;
case "-testfail":
mIsFailTest = true;
return true;
case "-clean":
mWantsClean = true;
return true;
case "-noir":
mConfig_NoIR = true;
return true;
}
}
else
{
if ((key == "-proddir") || (key == "-workspace"))
{
var relDir = scope String(value);
if ((relDir.EndsWith("\\")) || relDir.EndsWith("\""))
relDir.RemoveToEnd(relDir.Length - 1); //...
IDEUtils.FixFilePath(relDir);
String fullDir = new String();
Path.GetFullPath(relDir, fullDir);
mWorkspace.mDir = fullDir;
return true;
}
switch (key)
{
case "-config":
mConfigName.Set(value);
return true;
case "-platform":
mPlatformName.Set(value);
return true;
case "-verbosity":
if (value == "quiet")
mVerbosity = .Quiet;
else if (value == "minimal")
mVerbosity = .Minimal;
else if (value == "normal")
mVerbosity = .Normal;
else if (value == "detailed")
mVerbosity = .Detailed;
//else if (value == "diagnostic")
//mVerbosity = .Diagnostic;
return true;
}
}
#if BF_PLATFORM_WINDOWS
if (key == "-wait")
{
Windows.MessageBoxA((Windows.HWnd)0, "Wait2", "Wait", 0);
return true;
}
#endif //BF_PLATFORM_WINDOWS
return false;
}
protected override void BeefCompileStarted()
{
base.BeefCompileStarted();
if (mVerbosity >= .Normal)
{
if (cProgressSize > 0)
{
String str = scope String();
str.Append("[");
str.Append(' ', cProgressSize);
str.Append("]");
str.Append('\b', cProgressSize + 1);
Console.Write(str);
}
}
}
void WriteProgress(float pct)
{
if (mVerbosity >= .Normal)
{
int progressIdx = (int)Math.Round(pct * cProgressSize);
while (progressIdx > mProgressIdx)
{
mProgressIdx++;
Console.Write("*");
}
}
}
protected override void BeefCompileDone()
{
base.BeefCompileDone();
WriteProgress(1.0f);
Console.WriteLine("");
}
public override void LoadFailed()
{
mFailed = true;
}
public override void TestFailed()
{
mFailed = true;
}
protected override void CompileFailed()
{
base.CompileFailed();
mFailed = true;
}
protected override void CompileDone(bool succeeded)
{
if (!succeeded)
mFailed = true;
}
public override void Update(bool batchStart)
{
base.Update(batchStart);
if (mCompilingBeef)
{
WriteProgress(mBfBuildCompiler.GetCompletionPercentage());
}
if ((!IsCompiling) && (!AreTestsRunning()))
{
Stop();
}
}
}
}

147
BeefBuild/src/Program.bf Normal file
View file

@ -0,0 +1,147 @@
using System;
using IDE.Util;
using System.Diagnostics;
namespace BeefBuild
{
class Program
{
static void TestZip()
{
String str = "Good morning Dr. Chandra. This is Hal. I am ready for my first lesson.Good morning Dr. Chandra. This is Hal. I am ready for my first lesson.Good morning Dr. Chandra. This is Hal. I am ready for my first lesson.Good morning Dr. Chandra. This is Hal. I am ready for my first lesson.Good morning Dr. Chandra. This is Hal. I am ready for my first lesson.Good morning Dr. Chandra. This is Hal. I am ready for my first lesson.Good morning Dr. Chandra. This is Hal. I am ready for my first lesson.";
int src_len = str.Length;
int uncomp_len = (uint32)src_len;
int cmp_len = MiniZ.CompressBound(src_len);
var pCmp = new uint8[cmp_len]*;
#unwarn
var pUncomp = new uint8[src_len]*;
#unwarn
//var cmp_status = MiniZ.compress(pCmp, ref cmp_len, (uint8*)(char8*)str, src_len);
var cmp_status = MiniZ.Compress(pCmp, ref cmp_len, (uint8*)(char8*)str, src_len, .BEST_COMPRESSION);
cmp_status = MiniZ.Uncompress(pUncomp, ref uncomp_len, pCmp, cmp_len);
}
static void TestZip2()
{
MiniZ.ZipArchive zipArchive = default;
if (!MiniZ.ZipReaderInitFile(&zipArchive, "c:\\temp\\zip\\test.zip", default))
return;
for (int32 i = 0; i < (int)MiniZ.ZipReaderGetNumFiles(&zipArchive); i++)
{
MiniZ.ZipArchiveFileStat file_stat;
if (!MiniZ.ZipReaderFileStat(&zipArchive, i, &file_stat))
{
MiniZ.ZipReaderEnd(&zipArchive);
return;
}
//printf("Filename: \"%s\", Comment: \"%s\", Uncompressed size: %u, Compressed size: %u, Is Dir: %u\n", file_stat.m_filename, file_stat.m_comment,
//(uint)file_stat.m_uncomp_size, (uint)file_stat.m_comp_size, mz_zip_reader_is_file_a_directory(&zipArchive, i));
/*if (!strcmp(file_stat.m_filename, "directory/"))
{
if (!mz_zip_reader_is_file_a_directory(&zipArchive, i))
{
printf("mz_zip_reader_is_file_a_directory() didn't return the expected results!\n");
mz_zip_reader_end(&zipArchive);
}
}*/
var str = scope String();
str.AppendF("c:\\temp\\file.{0}", i);
MiniZ.ZipReaderExtractToFile(&zipArchive, i, str, default);
}
// Close the archive, freeing any resources it was using
MiniZ.ZipReaderEnd(&zipArchive);
}
/*[StdCall]
static int32 fetch_progress(Git.git_transfer_progress* stats, void* payload)
{
return 0;
}
[StdCall]
static void checkout_progress(char8* path, int cur, int tot, void* payload)
{
}
static void TestGit()
{
Git.git_libgit2_init();
Git.git_repository* repo = null;
Git.git_clone_options cloneOptions = default;
cloneOptions.version = 1;
cloneOptions.checkout_opts.version = 1;
cloneOptions.checkout_opts.checkout_strategy = 1;
//cloneOptions.checkout_opts.perfdata_cb = => checkout_progress;
cloneOptions.checkout_opts.progress_cb = => checkout_progress;
cloneOptions.fetch_opts.version = 1;
cloneOptions.fetch_opts.callbacks.version = 1;
cloneOptions.fetch_opts.update_fetchhead = 1;
cloneOptions.fetch_opts.proxy_opts.version = 1;
cloneOptions.fetch_opts.callbacks.transfer_progress = => fetch_progress;
//cloneOptions.
var result = Git.git_clone(&repo, "https://github.com/ponylang/pony-stable.git", "c:/temp/pony-stable", &cloneOptions);
Git.git_repository_free(repo);
Git.git_libgit2_shutdown();
}*/
public static int32 Main(String[] args)
{
//TestGit();
for (let arg in args)
{
if (arg != "-help")
continue;
Console.WriteLine(
"""
BeefBuild [args]
If no arguments are specified, a build will occur using current working directory as the workspace.
-config=<config> Sets the config (defaults to Debug)
-minidump=<path> Opens windows minidup file
-new Creates a new workspace and project
-platform=<platform> Sets the platform (defaults to system platform)
-test=<path> Executes test script
-verbosity=<verbosity> Set verbosity level to: quiet/minimal/normal/detailed/diagnostics
-workspace=<path> Sets workspace path (defaults to current working directory)
""");
return 0;
}
//TestZip2();
String commandLine = scope String();
commandLine.Join(" ", params args);
BuildApp mApp = new BuildApp();
mApp.ParseCommandLine(commandLine);
if (mApp.mFailed)
{
Console.Error.WriteLine(" Run with \"-help\" for a list of command-line arguments");
}
else
{
mApp.Init();
mApp.Run();
}
mApp.Shutdown();
int32 result = mApp.mFailed ? 1 : 0;
delete mApp;
return result;
}
}
}

View file

@ -0,0 +1,36 @@
FileVersion = 1
[Project]
Name = "Beefy2D"
TargetType = "BeefLib"
DefaultNamespace = ""
[Configs.Debug.Win32]
OtherLinkFlags = ""
PreprocessorMacros = ["DEBUG", "BF32"]
OptimizationLevel = "O0"
[Configs.Debug.Win64]
CLibType = "Static"
BeefLibType = "Static"
[Configs.Release.Win32]
OtherLinkFlags = ""
PreprocessorMacros = ["RELEASE", "BF32"]
OptimizationLevel = "O0"
[Configs.Paranoid.Win32]
CLibType = "Static"
BeefLibType = "Static"
[Configs.Paranoid.Win64]
CLibType = "Static"
BeefLibType = "Static"
[Configs.Test.Win32]
CLibType = "Static"
BeefLibType = "Static"
[Configs.Test.Win64]
CLibType = "Static"
BeefLibType = "Static"

View file

@ -0,0 +1,787 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using Beefy.gfx;
using Beefy.widgets;
using Beefy.theme;
using Beefy.theme.dark;
using Beefy.utils;
using Beefy.res;
using Beefy.geom;
using System.Threading;
#if MONOTOUCH
using MonoTouch;
#endif
#if STUDIO_CLIENT || STUDIO_HOST
using Beefy.ipc;
#endif
namespace Beefy
{
public enum Cursor
{
Pointer,
Hand,
Dragging,
Text,
CircleSlash,
Sizeall,
SizeNESW,
SizeNS,
SizeNWSE,
SizeWE,
Wait,
None,
COUNT
}
public class BFApp
#if STUDIO_CLIENT
: IStudioClient
#endif
{
public delegate void UpdateDelegate(bool batchStart);
public delegate void DrawDelegate();
public static BFApp sApp;
public int32 mUpdateCnt;
public bool mIsUpdateBatchStart;
public bool mAutoDirty = true;
public Graphics mGraphics ~ delete _;
int32 mRefreshRate = 60;
public String mInstallDir ~ delete _;
public String mUserDataDir ~ delete _;
public List<BFWindow> mWindows = new List<BFWindow>() ~ delete _;
List<Object> mDeferredDeletes = new List<Object>() ~ delete _;
public bool mShuttingDown = false;
public bool mStopping;
public bool mStarted;
public ResourceManager mResourceManager ~ delete _;
public int32 mFPSDrawCount;
public int32 mFPSUpdateCount;
public int32 mLastFPS;
public uint32 mLastFPSUpdateCnt;
public Matrix4? mColorMatrix;
public ConstantDataDefinition mColorMatrixDataDef = new ConstantDataDefinition(16, new ConstantDataDefinition.DataType[] { ConstantDataDefinition.DataType.Matrix | ConstantDataDefinition.DataType.PixelShaderUsage }) ~ delete _;
[StdCall, CLink]
static extern void Lib_Startup(int32 argc, char8** argv, void* startupCallback);
[StdCall, CLink]
static extern void BFApp_GetDesktopResolution(out int32 width, out int32 height);
[StdCall, CLink]
static extern void BFApp_GetWorkspaceRect(out int32 x, out int32 y, out int32 width, out int32 height);
[StdCall, CLink]
static extern void BFApp_Create();
[StdCall, CLink]
static extern void BFApp_Delete();
[StdCall, CLink]
static extern void BFApp_SetRefreshRate(int32 rate);
[StdCall, CLink]
public static extern void BFApp_SetDrawEnabled(int32 enabled);
[StdCall, CLink]
static extern void BFApp_Init();
[StdCall, CLink]
static extern void BFApp_Run();
[StdCall, CLink]
static extern void BFApp_Shutdown();
[StdCall, CLink]
static extern void BFApp_SetCallbacks(void* updateDelegate, void* drawDelegate);
[StdCall, CLink]
static extern char8* BFApp_GetInstallDir();
[StdCall, CLink]
static extern void BFApp_SetCursor(int32 cursor);
[StdCall, CLink]
static extern void* BFApp_GetClipboardData(char8* format, out int32 size);
[StdCall, CLink]
static extern void BFApp_ReleaseClipboardData(void* ptr);
[StdCall, CLink]
static extern void BFApp_SetClipboardData(char8* format, void* ptr, int32 size, int32 resetClipboard);
[StdCall, CLink]
public static extern void BFApp_CheckMemory();
[StdCall, CLink]
public static extern void BFApp_RehupMouse();
UpdateDelegate mUpdateDelegate ~ delete _;
DrawDelegate mDrawDelegate ~ delete _;
#if STUDIO_CLIENT
public bool mTrackingDraw = false;
public IPCClientManager mIPCClientManager;
public IPCProxy<IStudioHost> mStudioHost;
public static IStudioHost StudioHostProxy
{
get
{
return sApp.mStudioHost.Proxy;
}
}
#endif
#if STUDIO_CLIENT
public IPCEndpoint<IStudioClient> mStudioClient;
#endif
#if MONOTOUCH
[MonoPInvokeCallback(typeof(DrawDelegate))]
static void Static_Draw()
{
sApp.Draw();
}
[MonoPInvokeCallback(typeof(UpdateDelegate))]
static void Static_Update()
{
sApp.Update();
}
#endif
static void Static_Draw()
{
sApp.Draw();
}
static void Static_Update(bool batchStart)
{
sApp.Update(batchStart);
}
float mLastUpdateDelta; // In seconds
public this()
{
Utils.GetTickCountMicro();
//mColorMatrix = Matrix4.Identity;
/*mColorMatrix = Matrix4(
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1);*/
sApp = this;
BFApp_Create();
#if STUDIO_CLIENT
BFApp_SetRefreshRate(0); // Let studio dictate updating/drawing
mUpdateDelegate = LocalUpdate;
mDrawDelegate = LocalDraw;
#else
BFApp_SetRefreshRate(mRefreshRate);
mUpdateDelegate = new => Static_Update;
mDrawDelegate = new => Static_Draw;
#endif
BFApp_SetCallbacks(mUpdateDelegate.GetFuncPtr(), mDrawDelegate.GetFuncPtr());
}
#if STUDIO_CLIENT
int mStudioUpdateCnt = 0;
int mCount = 0;
uint mLocalUpdateTick;
public virtual void LocalUpdate()
{
mLocalUpdateTick = Utils.GetTickCount();
if (mHostIsPerfRecording)
{
PerfTimer.Log("HostPerfRecording Done at: {0}", Utils.GetTickCount());
PerfTimer.StopRecording();
PerfTimer.DbgPrint();
mHostIsPerfRecording = false;
}
IPCClientManager.sIPCClientManager.Update();
if (mHostIsPerfRecording)
PerfTimer.Log("Update Done at: {0}", Utils.GetTickCount());
IPCClientManager.sIPCClientManager.RemoteSyncToRead();
if (mHostIsPerfRecording)
PerfTimer.Log("RemoteSyncToRead Done at: {0}", Utils.GetTickCount());
mStudioUpdateCnt++;
mStudioHost.Proxy.ClientUpdated(mStudioUpdateCnt);
if (mHostIsPerfRecording)
PerfTimer.Log("ClientUpdated Done at: {0}", Utils.GetTickCount());
mCount++;
}
public virtual void LocalDraw()
{
}
public void TrackDraw()
{
if (!mTrackingDraw)
return;
StackTrace st = new StackTrace(true);
StringBuilder sb = new StringBuilder();
var frames = st.GetFrames();
for (int frameNum = 0; frameNum < frames.Length; frameNum++)
{
var frame = frames[frameNum];
sb.Append(frame.GetMethod().DeclaringType.ToString());
sb.Append(".");
sb.Append(frame.GetMethod().Name);
sb.Append("(");
int paramIdx = 0;
for (var param in frame.GetMethod().GetParameters())
{
if (paramIdx > 0)
sb.Append(", ");
sb.Append(param.ParameterType.ToString());
sb.Append(" ");
sb.Append(param.Name);
paramIdx++;
}
sb.Append(")");
sb.Append("|");
sb.Append(frame.GetFileName());
sb.Append("|");
sb.Append(frame.GetFileLineNumber());
sb.AppendLine();
}
}
#endif
public int32 RefreshRate
{
get
{
return mRefreshRate;
}
set
{
mRefreshRate = value;
BFApp_SetRefreshRate(mRefreshRate);
}
}
// Simulation seconds since last update
public float UpdateDelta
{
get
{
if (mRefreshRate != 0)
return 1.0f / mRefreshRate;
return mLastUpdateDelta;
}
}
public static void Startup(String[] args, Action startupCallback)
{
/*string[] newArgs = new string[args.Length + 1];
Array.Copy(args, 0, newArgs, 1, args.Length);
newArgs[0] = System.Reflection.Assembly.GetEntryAssembly().Location;
Lib_Startup(newArgs.Length, newArgs, startupCallback);*/
char8*[] char8PtrArr = scope char8*[args.Count];
for (int32 i = 0; i < args.Count; i++)
char8PtrArr[i] = args[i];
Lib_Startup((int32)args.Count, char8PtrArr.CArray(), startupCallback.GetFuncPtr());
}
public virtual bool HandleCommandLineParam(String key, String value)
{
return false;
}
public virtual void UnhandledCommandLine(String key, String value)
{
}
public virtual void ParseCommandLine(String[] args)
{
for (var str in args)
{
int eqPos = str.IndexOf('=');
if (eqPos == -1)
{
if (!HandleCommandLineParam(str, null))
UnhandledCommandLine(str, null);
}
else
{
var cmd = scope String(str, 0, eqPos);
var param = scope String(str, eqPos + 1);
if (!HandleCommandLineParam(cmd, param))
UnhandledCommandLine(cmd, param);
}
}
}
public virtual void ParseCommandLine(String theString)
{
List<String> stringList = scope List<String>();
String curString = null;
bool hadSpace = false;
bool inQuote = false;
for (int32 i = 0; i < theString.Length; i++)
{
char8 c = theString[i];
if ((theString[i] == ' ') && (!inQuote))
{
hadSpace = true;
}
else
{
if (hadSpace)
{
if (!inQuote)
{
if (c == '=')
{
}
else
{
if (curString != null)
{
stringList.Add(curString);
curString = null;
}
}
}
hadSpace = false;
}
if (curString == null)
curString = scope:: String();
if (c == '"')
{
inQuote = !inQuote;
}
else
{
curString.Append(theString[i]);
}
}
}
if (curString != null)
stringList.Add(curString);
for (String param in stringList)
{
int32 eqPos = (int32)param.IndexOf('=');
if (eqPos != -1)
{
String key = scope String(param, 0, eqPos);
String value = scope String(param, eqPos + 1);
if (!HandleCommandLineParam(key, value))
UnhandledCommandLine(key, value);
}
else
if (!HandleCommandLineParam(param, null))
UnhandledCommandLine(param, null);
}
}
public void GetDesktopResolution(out int width, out int height)
{
int32 widthOut;
int32 heightOut;
BFApp_GetDesktopResolution(out widthOut, out heightOut);
width = widthOut;
height = heightOut;
}
public void GetWorkspaceRect(out int x, out int y, out int width, out int height)
{
int32 xOut;
int32 yOut;
int32 widthOut;
int32 heightOut;
BFApp_GetWorkspaceRect(out xOut, out yOut, out widthOut, out heightOut);
x = xOut;
y = yOut;
width = widthOut;
height = heightOut;
}
public bool HasModalDialogs()
{
for (var window in mWindows)
{
if (window.mWindowFlags.HasFlag(BFWindowBase.Flags.Modal))
return true;
}
return false;
}
public bool HasPopupMenus()
{
for (var window in mWindows)
{
var widgetWindow = window as WidgetWindow;
if ((widgetWindow != null) && (widgetWindow.mRootWidget is MenuContainer))
return true;
}
return false;
}
public virtual void Init()
{
scope AutoBeefPerf("BFApp.Init");
#if STUDIO_CLIENT
mIPCClientManager = IPCClientManager.sIPCClientManager = new IPCClientManager();
mIPCClientManager.Init();
mStudioClient = IPCEndpoint<IStudioClient>.CreateNamed(this);
mStudioHost = IPCProxy<IStudioHost>.CreateNamed();
mIPCClientManager.mRemoteProcessId = mStudioHost.Proxy.ClientConnected(mStudioClient.ObjId, Process.GetCurrentProcess().Id);
mIPCClientManager.mConnecting = false;
#endif
BFApp_Init();
Interlocked.Fence();
mInstallDir = new String(BFApp_GetInstallDir());
mUserDataDir = new String(mInstallDir);
mResourceManager = new ResourceManager();
String resFileName = scope String();
resFileName.Append(mInstallDir, "Resources.json");
if (File.Exists(resFileName))
{
StructuredData structuredData = scope StructuredData();
structuredData.Load(resFileName);
mResourceManager.ParseConfigData(structuredData);
}
}
public void InitGraphics()
{
DefaultVertex.Init();
ModelDef.VertexDef.Init();
mGraphics = new Graphics();
String filePath = scope String();
filePath.Append(mInstallDir, "shaders/Std");
if (mColorMatrix != null)
filePath.Append("_hue");
Shader shader = Shader.CreateFromFile(filePath, DefaultVertex.sVertexDefinition);
//shader.SetTechnique("Standard");
mGraphics.mDefaultShader = shader;
mGraphics.mDefaultRenderState = RenderState.Create();
mGraphics.mDefaultRenderState.mIsFromDefaultRenderState = true;
mGraphics.mDefaultRenderState.Shader = shader;
filePath.Append("_font");
Shader textShader = Shader.CreateFromFile(filePath, DefaultVertex.sVertexDefinition);
mGraphics.mTextShader = textShader;
//shader.SetTechnique("Standard");
//mGraphics.mDefaultShader = textShader;
//mGraphics.mDefaultRenderState = RenderState.Create();
//mGraphics.mDefaultRenderState.mIsFromDefaultRenderState = true;
//mGraphics.mDefaultRenderState.Shader = shader;
//mGraphics.mDefaultShader = textShader;
//mGraphics.mDefaultRenderState.Shader = textShader;
}
public ~this()
{
#if STUDIO_HOST || STUDIO_CLIENT
if (IPCManager.sIPCManager != null)
IPCManager.sIPCManager.Dispose();
#endif
Debug.Assert(mShuttingDown, "Shutdown must be called before deleting the app");
ProcessDeferredDeletes();
BFApp_Delete();
ShutdownCompleted();
}
public void DeferDelete(Object obj)
{
//Slow, paranoid check.
//Debug.Assert(!mDeferredDeletes.Contains(obj));
mDeferredDeletes.Add(obj);
}
public void ProcessDeferredDeletes()
{
for (int32 i = 0; i < mDeferredDeletes.Count; i++)
delete mDeferredDeletes[i];
mDeferredDeletes.Clear();
}
public virtual void ShutdownCompleted()
{
}
public virtual void Shutdown()
{
Debug.Assert(!mShuttingDown, "Shutdown can only be called once");
/*if (!mStarted)
Debug.Assert(mStopping, "Shutdown can only be called after the app is stopped");*/
mShuttingDown = true;
//Dispose();
}
public virtual void Run()
{
if (mStopping)
return;
BFApp_Run();
}
public virtual void Stop()
{
mStopping = true;
while (mWindows.Count > 0)
mWindows[0].Close();
BFApp_Shutdown();
}
uint32 mPrevUpdateTickCount;
uint32 mUpdateTickCount;
uint32 mLastEndedTickCount;
public virtual void Update(bool batchStart)
{
//Utils.BFRT_CPP("gBFGC.MutatorSectionEntry()");
mIsUpdateBatchStart = batchStart;
mUpdateCnt++;
mPrevUpdateTickCount = mUpdateTickCount;
mUpdateTickCount = Utils.GetTickCount();
if (mPrevUpdateTickCount != 0)
mLastUpdateDelta = (mUpdateTickCount - mPrevUpdateTickCount) / 1000.0f;
using (PerfTimer.ZoneStart("BFApp.Update"))
{
mFPSUpdateCount++;
if (mRefreshRate == 0)
{
int32 elapsed = (int32)(mUpdateTickCount - mLastFPSUpdateCnt);
if (elapsed > 1000)
{
mLastFPS = mFPSDrawCount;
mLastFPSUpdateCnt = mUpdateTickCount;
mFPSUpdateCount = 0;
mFPSDrawCount = 0;
}
}
else
{
if (mFPSUpdateCount == mRefreshRate)
{
mLastFPS = mFPSDrawCount;
//Debug.WriteLine("FPS: " + mLastFPS);
mFPSUpdateCount = 0;
mFPSDrawCount = 0;
}
}
//GC.Collect();
using (PerfTimer.ZoneStart("BFApp.Update mWindows updates"))
{
for (int32 windowIdx = 0; windowIdx < mWindows.Count; windowIdx++)
{
mWindows[windowIdx].Update();
}
}
}
mLastEndedTickCount = Utils.GetTickCount();
ProcessDeferredDeletes();
//Utils.BFRT_CPP("gBFGC.MutatorSectionExit()");
}
public virtual void DoDraw()
{
}
#if STUDIO_CLIENT
bool mHostIsPerfRecording;
public virtual void HostIsPerfRecording(bool isPerfRecording, int drawCount)
{
mHostIsPerfRecording = isPerfRecording;
if (mHostIsPerfRecording)
{
PerfTimer.StartRecording();
PerfTimer.Log("HostIsPerfRecording {0}", drawCount);
PerfTimer.Log("PrevUpdateTickCount: {0}", mPrevUpdateTickCount);
PerfTimer.Log("UpdateTickCount: {0}", mUpdateTickCount);
PerfTimer.Log("LocalUpdateTick: {0}", mLocalUpdateTick);
//using (PerfTimer.ZoneStart("HostIsPerfRecording"))
//PerfTimer.Log("Got HostIsPerfRecording");
}
}
#endif
public virtual void Draw()
{
#if STUDIO_CLIENT
#endif
PerfTimer.ZoneStart("BFApp.Draw");
PerfTimer.Message("Client Draw Start");
mFPSDrawCount++;
#if STUDIO_CLIENT
mStudioHost.Proxy.FrameStarted(mUpdateCnt);
#endif
if (mGraphics == null)
InitGraphics();
mGraphics.StartDraw();
for (BFWindow window in mWindows)
{
if ((window.mVisible) && ((window.mIsDirty) || (mAutoDirty)))
{
window.PreDraw(mGraphics);
if (mColorMatrix != null)
{
#if DEBUG
mColorMatrix = Matrix4(
0.90f, 0.10f, 0.00f, 0,
0.00f, 0.90f, 0.10f, 0,
0.10f, 0.00f, 1.05f, 0,
0, 0, 0, 1);
#else
mColorMatrix = Matrix4(
0.90f, 0.10f, 0.00f, 0,
0.00f, 1.05f, 0.10f, 0,
0.10f, 0.00f, 0.90f, 0,
0, 0, 0, 1);
#endif
mGraphics.SetShaderConstantData(0, &mColorMatrix.ValueRef, mColorMatrixDataDef);
}
window.Draw(mGraphics);
window.PostDraw(mGraphics);
window.mIsDirty = false;
}
}
mGraphics.EndDraw();
#if STUDIO_CLIENT
PerfTimer.Log("Sending FrameDone");
mStudioHost.Proxy.FrameDone();
//mFrameDonesSent++;
#endif
PerfTimer.ZoneEnd();
}
public void MarkDirty()
{
for (var window in mWindows)
{
if (var widgetWindow = window as WidgetWindow)
{
widgetWindow.mIsDirty = true;
}
}
}
Cursor curCursor;
public virtual void SetCursor(Cursor cursor)
{
if (curCursor == cursor)
return;
curCursor = cursor;
BFApp_SetCursor((int32)cursor);
}
public virtual void* GetClipboardData(String format, out int32 size)
{
return BFApp_GetClipboardData(format, out size);
}
public virtual void ReleaseClipboardData(void* ptr)
{
BFApp_ReleaseClipboardData(ptr);
}
public virtual bool GetClipboardText(String outStr)
{
int32 aSize;
void* clipboardData = GetClipboardData("text", out aSize);
if (clipboardData == null)
return false;
outStr.Append((char8*)clipboardData);
ReleaseClipboardData(clipboardData);
return true;
}
public virtual void SetClipboardData(String format, void* ptr, int32 size, bool resetClipboard)
{
BFApp_SetClipboardData(format, ptr, size, resetClipboard ? 1 : 0);
}
public virtual void SetClipboardText(String text)
{
//IntPtr aPtr = Marshal.StringToCoTaskMemUni(text);
SetClipboardData("text", text.CStr(), (int32)text.Length + 1, true);
}
#if STUDIO_CLIENT
public int GetProcessId()
{
return Process.GetCurrentProcess().Id;
}
#endif
public void RehupMouse()
{
BFApp_RehupMouse();
}
}
}

View file

@ -0,0 +1,772 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Beefy.gfx;
using Beefy.sys;
using System.IO;
#if MONOTOUCH
using MonoTouch;
#endif
#if STUDIO_CLIENT
using Beefy.ipc;
#endif
namespace Beefy
{
public class BFWindowBase
{
public enum Flags
{
Border = 0x000001,
ThickFrame = 0x000002,
Resizable = 0x000004,
SysMenu = 0x000008,
Caption = 0x000010,
Minimize = 0x000020,
Maximize = 0x000040,
ClientSized = 0x000080,
QuitOnClose = 0x000100,
VSync = 0x000200,
PopupPosition = 0x000400,
DestAlpha = 0x000800,
AlphaMask = 0x001000,
Child = 0x002000,
TopMost = 0x004000,
ToolWindow = 0x008000,
NoActivate = 0x01'0000,
NoMouseActivate = 0x02'0000,
Menu = 0x04'0000,
Modal = 0x08'0000,
ScaleContent = 0x10'0000,
UseParentMenu = 0x20'0000,
CaptureMediaKeys = 0x40'0000,
Fullscreen = 0x80'0000,
FakeFocus = 0x0100'0000
};
public enum HitTestResult
{
NotHandled = -3,
Border = 18,
Bottom = 15,
BottomLeft = 16,
BottomRight = 17,
Caption = 2,
Client = 1,
Close = 20,
Error = -2,
GrowBox = 4,
Help = 21,
HScroll = 6,
Left = 10,
Menu = 5,
MaxButton = 9,
MinButton = 8,
NoWhere = 0,
Reduce = 8,
Right = 11,
Size = 4,
SysMenu = 3,
Top = 12,
TopLeft = 13,
TopRight = 14,
Transparent = -1,
VScroll = 7,
Zoom = 9
}
public SysMenu mSysMenu ~ delete _;
public Dictionary<int, SysMenu> mSysMenuMap = new Dictionary<int, SysMenu>() ~ delete _;
public DrawLayer mDefaultDrawLayer ~ delete _;
public virtual void Draw(Graphics g)
{
}
public virtual void PreDraw(Graphics g)
{
g.PushDrawLayer(mDefaultDrawLayer);
}
public virtual void PostDraw(Graphics g)
{
g.PopDrawLayer();
}
}
#if !STUDIO_CLIENT
public class BFWindow : BFWindowBase, INativeWindow
{
delegate void NativeMovedDelegate(void* window);
delegate int32 NativeCloseQueryDelegate(void* window);
delegate void NativeClosedDelegate(void* window);
delegate void NativeGotFocusDelegate(void* window);
delegate void NativeLostFocusDelegate(void* window);
delegate void NativeKeyCharDelegate(void* window, char32 theChar);
delegate bool NativeKeyDownDelegate(void* window, int32 keyCode, int32 isRepeat);
delegate void NativeKeyUpDelegate(void* window, int32 keyCode);
delegate int32 NativeHitTestDelegate(void* window, int32 x, int32 y);
delegate void NativeMouseMoveDelegate(void* window, int32 x, int32 y);
delegate void NativeMouseProxyMoveDelegate(void* window, int32 x, int32 y);
delegate void NativeMouseDownDelegate(void* window, int32 x, int32 y, int32 btn, int32 btnCount);
delegate void NativeMouseUpDelegate(void* window, int32 x, int32 y, int32 btn);
delegate void NativeMouseWheelDelegate(void* window, int32 x, int32 y, int32 delta);
delegate void NativeMouseLeaveDelegate(void* window);
delegate void NativeMenuItemSelectedDelegate(void* window, void* menu);
public void* mNativeWindow;
public bool mNativeWindowClosed;
static int32 sId;
protected int32 mId = ++sId;
public String mName ~ delete _;
public String mTitle ~ delete _;
public int32 mX;
public int32 mY;
public int32 mWindowWidth;
public int32 mWindowHeight;
public int32 mClientX;
public int32 mClientY;
public int32 mClientWidth;
public int32 mClientHeight;
public float mAlpha = 1.0f;
public Flags mWindowFlags;
public bool mVisible = true;
private bool mMouseVisible;
public bool mHasFocus = false;
public bool mHasClosed;
public bool mIsDirty = true;
public BFWindow mParent;
public List<BFWindow> mChildWindows = new List<BFWindow>() ~ delete _;
static protected Dictionary<int, BFWindow> sWindowDictionary = new Dictionary<int, BFWindow>() ~ delete _;
static NativeMovedDelegate sNativeMovedDelegate ~ delete _;
static NativeCloseQueryDelegate sNativeCloseQueryDelegate ~ delete _;
static NativeClosedDelegate sNativeClosedDelegate ~ delete _;
static NativeGotFocusDelegate sNativeGotFocusDelegate ~ delete _;
static NativeLostFocusDelegate sNativeLostFocusDelegate ~ delete _;
static NativeKeyCharDelegate sNativeKeyCharDelegate ~ delete _;
static NativeKeyDownDelegate sNativeKeyDownDelegate ~ delete _;
static NativeKeyUpDelegate sNativeKeyUpDelegate ~ delete _;
static NativeHitTestDelegate sNativeHitTestDelegate ~ delete _;
static NativeMouseMoveDelegate sNativeMouseMoveDelegate ~ delete _;
static NativeMouseProxyMoveDelegate sNativeMouseProxyMoveDelegate ~ delete _;
static NativeMouseDownDelegate sNativeMouseDownDelegate ~ delete _;
static NativeMouseUpDelegate sNativeMouseUpDelegate ~ delete _;
static NativeMouseWheelDelegate sNativeMouseWheelDelegate ~ delete _;
static NativeMouseLeaveDelegate sNativeMouseLeaveDelegate ~ delete _;
static NativeMenuItemSelectedDelegate sNativeMenuItemSelectedDelegate ~ delete _;
[StdCall, CLink]
static extern void* BFApp_CreateWindow(void* parent, char8* title, int32 x, int32 y, int32 width, int32 height, int32 windowFlags);
[StdCall, CLink]
static extern void* BFWindow_GetNativeUnderlying(void* window);
[StdCall, CLink]
static extern void BFWindow_SetCallbacks(void* window, void* movedDelegate, void* closeQueryDelegate, void* closedDelegate,
void* gotFocusDelegate, void* lostFocusDelegate,
void* keyCharDelegate, void* keyDownDelegate, void* keyUpDelegate, void* hitTestDelegate,
void* mouseMoveDelegate, void* mouseProxyMoveDelegate, void* mouseDownDelegate, void* mouseUpDelegate, void* mouseWheelDelegate, void* mouseLeaveDelegate,
void* menuItemSelectedDelegate);
[StdCall, CLink]
static extern void BFWindow_SetTitle(void* window, char8* title);
[StdCall, CLink]
static extern void BFWindow_SetMinimumSize(void* window, int32 minWidth, int32 minHeight, bool clientSized);
[StdCall, CLink]
static extern void BFWindow_GetPosition(void* window, out int32 x, out int32 y, out int32 width, out int32 height, out int32 clientX, out int32 clientY, out int32 clientWidth, out int32 clientHeight);
[StdCall, CLink]
static extern void BFWindow_Resize(void* window, int32 x, int32 y, int32 width, int32 height);
[StdCall, CLink]
static extern void BFWindow_Close(void* window, int32 force);
[StdCall, CLink]
static extern void BFWindow_SetForeground(void* window);
[StdCall, CLink]
static extern void BFWindow_LostFocus(void* window, void* newFocus);
[StdCall, CLink]
static extern void BFWindow_SetNonExclusiveMouseCapture(void* window);
[StdCall, CLink]
static extern void BFWindow_SetClientPosition(void* window, int32 x, int32 y);
[StdCall, CLink]
static extern void BFWindow_SetAlpha(void* window, float alpha, uint32 destAlphaSrcMask, int32 mouseVisible);
[StdCall, CLink]
static extern void BFWindow_SetMouseVisible(void* window, bool mouseVisible);
[StdCall, CLink]
static extern void BFWindow_CaptureMouse(void* window);
[StdCall, CLink]
static extern bool BFWindow_IsMouseCaptured(void* window);
[StdCall, CLink]
static extern void* BFWindow_AddMenuItem(void* window, void* parent, int32 insertIdx, char8* text, char8* hotKey, void* bitmap, int32 enabled, int32 checkState, int32 radioCheck);
[StdCall, CLink]
static extern void* BFWindow_ModifyMenuItem(void* window, void* item, char8* text, char8* hotKey, void* bitmap, int32 enabled, int32 checkState, int32 radioCheck);
[StdCall, CLink]
static extern void* BFWindow_DeleteMenuItem(void* window, void* item);
public static BFWindow GetBFWindow(void* window)
{
return sWindowDictionary[(int)window];
}
#if MONOTOUCH
[MonoPInvokeCallback(typeof(NativeMovedDelegate))]
static void Static_NativeMovedDelegate(void* window) { GetBFWindow(window).Moved(); }
[MonoPInvokeCallback(typeof(NativeClosedDelegate))]
static void Static_NativeClosedDelegate(void* window) { GetBFWindow(window).Closed(); }
[MonoPInvokeCallback(typeof(NativeCloseQueryDelegate))]
static int Static_NativeCloseQueryDelegate(void* window) { return GetBFWindow(window).CloseQuery(); }
[MonoPInvokeCallback(typeof(NativeGotFocusDelegate))]
static void Static_NativeGotFocusDelegate(void* window) { GetBFWindow(window).GotFocus(); }
[MonoPInvokeCallback(typeof(NativeLostFocusDelegate))]
static void Static_NativeLostFocusDelegate(void* window) { GetBFWindow(window).LostFocus(); }
[MonoPInvokeCallback(typeof(NativeKeyCharDelegate))]
static void Static_NativeKeyCharDelegate(void* window, char8 c) { GetBFWindow(window).KeyChar(c); }
[MonoPInvokeCallback(typeof(NativeKeyDownDelegate))]
static bool Static_NativeKeyDownDelegate(void* window, int key, int isRepeat) { return GetBFWindow(window).KeyDown(key, isRepeat); }
[MonoPInvokeCallback(typeof(NativeKeyUpDelegate))]
static void Static_NativeKeyUpDelegate(void* window, int key) { GetBFWindow(window).KeyUp(key); }
[MonoPInvokeCallback(typeof(NativeMouseMoveDelegate))]
static void Static_NativeMouseMoveDelegate(void* window, int mouseX, int mouseY) { GetBFWindow(window).MouseMove(mouseX, mouseY); }
[MonoPInvokeCallback(typeof(NativeMouseProxyMoveDelegate))]
static void Static_NativeMouseProxyMoveDelegate(void* window, int mouseX, int mouseY) { GetBFWindow(window).MouseProxyMove(mouseX, mouseY); }
[MonoPInvokeCallback(typeof(NativeMouseDownDelegate))]
static void Static_NativeMouseDownDelegate(void* window, int mouseX, int mouseY, int btnNum, int btnCount) { GetBFWindow(window).MouseDown(mouseX, mouseY, btnNum, btnCount); }
[MonoPInvokeCallback(typeof(NativeMouseUpDelegate))]
static void Static_NativeMouseUpDelegate(void* window, int mouseX, int mouseY, int btnNum) { GetBFWindow(window).MouseUp(mouseX, mouseY, btnNum); }
[MonoPInvokeCallback(typeof(NativeMouseWheelDelegate))]
static void Static_NativeMouseWheelDelegate(void* window, int mouseX, int mouseY, int delta) { GetBFWindow(window).MouseWheel(mouseX, mouseY, delta); }
[MonoPInvokeCallback(typeof(NativeMouseLeaveDelegate))]
static void Static_NativeMouseLeaveDelegate(void* window) { GetBFWindow(window).MouseLeave(); }
[MonoPInvokeCallback(typeof(NativeMenuItemSelectedDelegate))]
static void Static_NativeMenuItemSelectedDelegate(void* window, void* item) { GetBFWindow(window).NativeMenuItemSelected(item); }
#else
static void Static_NativeMovedDelegate(void* window) { GetBFWindow(window).Moved(); }
static void Static_NativeClosedDelegate(void* window) { GetBFWindow(window).Closed(); }
static int32 Static_NativeCloseQueryDelegate(void* window) { return GetBFWindow(window).CloseQuery(); }
static void Static_NativeGotFocusDelegate(void* window) { GetBFWindow(window).GotFocus(); }
static void Static_NativeLostFocusDelegate(void* window) { GetBFWindow(window).LostFocus(null); }
static void Static_NativeKeyCharDelegate(void* window, char32 c) { GetBFWindow(window).KeyChar(c); }
static bool Static_NativeKeyDownDelegate(void* window, int32 key, int32 isRepeat) { return GetBFWindow(window).KeyDown(key, isRepeat); }
static void Static_NativeKeyUpDelegate(void* window, int32 key) { GetBFWindow(window).KeyUp(key); }
static int32 Static_NativeHitTestDelegate(void* window, int32 x, int32 y) { return (int32)GetBFWindow(window).HitTest(x, y); }
static void Static_NativeMouseMoveDelegate(void* window, int32 mouseX, int32 mouseY) { GetBFWindow(window).MouseMove(mouseX, mouseY); }
static void Static_NativeMouseProxyMoveDelegate(void* window, int32 mouseX, int32 mouseY) { GetBFWindow(window).MouseProxyMove(mouseX, mouseY); }
static void Static_NativeMouseDownDelegate(void* window, int32 mouseX, int32 mouseY, int32 btnNum, int32 btnCount) { GetBFWindow(window).MouseDown(mouseX, mouseY, btnNum, btnCount); }
static void Static_NativeMouseUpDelegate(void* window, int32 mouseX, int32 mouseY, int32 btnNum) { GetBFWindow(window).MouseUp(mouseX, mouseY, btnNum); }
static void Static_NativeMouseWheelDelegate(void* window, int32 mouseX, int32 mouseY, int32 delta) { GetBFWindow(window).MouseWheel(mouseX, mouseY, delta); }
static void Static_NativeMouseLeaveDelegate(void* window) { GetBFWindow(window).MouseLeave(); }
static void Static_NativeMenuItemSelectedDelegate(void* window, void* item) { GetBFWindow(window).NativeMenuItemSelected(item); }
#endif
public this()
{
}
public this(BFWindow parent, String title, int x, int y, int width, int height, BFWindow.Flags windowFlags)
{
Init(parent, title, x, y, width, height, windowFlags);
}
public ~this()
{
bool worked = sWindowDictionary.Remove((int)mNativeWindow);
Debug.Assert(worked);
}
void Init(BFWindow parent, String title, int x, int y, int width, int height, BFWindow.Flags windowFlags)
{
mTitle = new String(title);
mParent = parent;
if (mParent != null)
mParent.mChildWindows.Add(this);
var useFlags = windowFlags;
/*if (useFlags.HasFlag(.FakeFocus))
{
useFlags |= .NoActivate;
useFlags |= .NoMouseActivate;
}*/
mNativeWindow = BFApp_CreateWindow((parent != null) ? (parent.mNativeWindow) : null, title, (int32)x, (int32)y, (int32)width, (int32)height, (int32)useFlags);
sWindowDictionary[(int)mNativeWindow] = this;
if (sNativeMovedDelegate == null)
{
sNativeMovedDelegate = new => Static_NativeMovedDelegate;
sNativeClosedDelegate = new => Static_NativeClosedDelegate;
sNativeCloseQueryDelegate = new => Static_NativeCloseQueryDelegate;
sNativeGotFocusDelegate = new => Static_NativeGotFocusDelegate;
sNativeLostFocusDelegate = new => Static_NativeLostFocusDelegate;
sNativeKeyCharDelegate = new => Static_NativeKeyCharDelegate;
sNativeKeyDownDelegate = new => Static_NativeKeyDownDelegate;
sNativeKeyUpDelegate = new => Static_NativeKeyUpDelegate;
sNativeHitTestDelegate = new => Static_NativeHitTestDelegate;
sNativeMouseMoveDelegate = new => Static_NativeMouseMoveDelegate;
sNativeMouseProxyMoveDelegate = new => Static_NativeMouseProxyMoveDelegate;
sNativeMouseDownDelegate = new => Static_NativeMouseDownDelegate;
sNativeMouseUpDelegate = new => Static_NativeMouseUpDelegate;
sNativeMouseWheelDelegate = new => Static_NativeMouseWheelDelegate;
sNativeMouseLeaveDelegate = new => Static_NativeMouseLeaveDelegate;
sNativeMenuItemSelectedDelegate = new => Static_NativeMenuItemSelectedDelegate;
}
BFWindow_SetCallbacks(mNativeWindow, sNativeMovedDelegate.GetFuncPtr(), sNativeCloseQueryDelegate.GetFuncPtr(), sNativeClosedDelegate.GetFuncPtr(), sNativeGotFocusDelegate.GetFuncPtr(), sNativeLostFocusDelegate.GetFuncPtr(),
sNativeKeyCharDelegate.GetFuncPtr(), sNativeKeyDownDelegate.GetFuncPtr(), sNativeKeyUpDelegate.GetFuncPtr(), sNativeHitTestDelegate.GetFuncPtr(),
sNativeMouseMoveDelegate.GetFuncPtr(), sNativeMouseProxyMoveDelegate.GetFuncPtr(), sNativeMouseDownDelegate.GetFuncPtr(), sNativeMouseUpDelegate.GetFuncPtr(), sNativeMouseWheelDelegate.GetFuncPtr(), sNativeMouseLeaveDelegate.GetFuncPtr(),
sNativeMenuItemSelectedDelegate.GetFuncPtr());
BFApp.sApp.mWindows.Add(this);
mDefaultDrawLayer = new DrawLayer(this);
if (windowFlags.HasFlag(Flags.Menu))
{
mSysMenu = new SysMenu();
mSysMenu.mWindow = this;
}
mWindowFlags = windowFlags;
if ((parent != null) && (!mWindowFlags.HasFlag(Flags.NoActivate)))
parent.LostFocus(this);
if ((parent != null) && (mWindowFlags.HasFlag(Flags.Modal)))
parent.PreModalChild();
if ((mWindowFlags.HasFlag(.FakeFocus)) && (!mWindowFlags.HasFlag(.NoActivate)))
GotFocus();
BFApp.sApp.RehupMouse();
}
public void SetTitle(String title)
{
mTitle.Set(title);
BFWindow_SetTitle(mNativeWindow, mTitle);
}
public int Handle
{
get
{
return (int)BFWindow_GetNativeUnderlying(mNativeWindow);
}
}
#if BF_PLATFORM_WINDOWS
public Windows.HWnd HWND
{
get
{
return (.)(int)BFWindow_GetNativeUnderlying(mNativeWindow);
}
}
#endif
public void PreModalChild()
{
//MouseLeave();
}
public virtual void Dispose()
{
Close(true);
}
public virtual int32 CloseQuery()
{
return 1;
}
public virtual void Close(bool force = false)
{
// This doesn't play properly with CloseQuery. We may do a force close in CloseQuery, but that fails
// if we do this following logic:
/*if (mNativeWindowClosed)
return;
mNativeWindowClosed = true;*/
while (mChildWindows.Count > 0)
mChildWindows[mChildWindows.Count - 1].Close(force);
//for (var childWindow in mChildWindows)
//childWindow.Close(force);
//mChildWindows[mChildWindows.Count - 1].Close(force);
if (mNativeWindow != null)
{
BFWindow_Close(mNativeWindow, force ? 1 : 0);
}
else
{
Closed();
}
}
public virtual void Resize(int x, int y, int width, int height)
{
Debug.Assert(mNativeWindow != null);
BFWindow_Resize(mNativeWindow, (int32)x, (int32)y, (int32)width, (int32)height);
}
public void SetForeground()
{
BFWindow_SetForeground(mNativeWindow);
GotFocus();
}
public void SetNonExclusiveMouseCapture()
{
// Does checking of mouse coords against all window even when this window has mouse capture,
// helps some dragging scenarios. Gets turned off automatically on mouse up.
BFWindow_SetNonExclusiveMouseCapture(mNativeWindow);
}
public virtual void Closed()
{
if (mHasClosed)
return;
mHasClosed = true;
bool hadFocus = mHasFocus;
BFApp.sApp.mWindows.Remove(this);
if (mWindowFlags.HasFlag(Flags.QuitOnClose))
BFApp.sApp.Stop();
if (mParent != null)
{
mParent.mChildWindows.Remove(this);
if ((hadFocus) && (mWindowFlags.HasFlag(Flags.Modal)))
mParent.GotFocus();
}
DeleteAndNullify!(mDefaultDrawLayer);
BFApp.sApp.DeferDelete(this);
}
public void SetMinimumSize(int32 minWidth, int32 minHeight, bool clientSized = false)
{
BFWindow_SetMinimumSize(mNativeWindow, minWidth, minHeight, clientSized);
}
public virtual void Moved()
{
BFWindow_GetPosition(mNativeWindow, out mX, out mY, out mWindowWidth, out mWindowHeight, out mClientX, out mClientY, out mClientWidth, out mClientHeight);
mIsDirty = true;
}
public virtual void SetClientPosition(float x, float y)
{
mClientX = (int32)x;
mClientY = (int32)y;
BFWindow_SetClientPosition(mNativeWindow, (int32)x, (int32)y);
}
public virtual void SetAlpha(float alpha, uint32 destAlphaSrcMask, bool mouseVisible)
{
mAlpha = alpha;
BFWindow_SetAlpha(mNativeWindow, alpha, destAlphaSrcMask, mouseVisible ? 1 : 0);
}
public virtual void SetMouseVisible(bool mouseVisible)
{
mMouseVisible = mouseVisible;
BFWindow_SetMouseVisible(mNativeWindow, mouseVisible);
}
public virtual void CaptureMouse()
{
BFWindow_CaptureMouse(mNativeWindow);
}
public bool IsMouseCaptured()
{
return BFWindow_IsMouseCaptured(mNativeWindow);
}
public virtual void* AddMenuItem(void* parent, int insertIdx, String text, String hotKey, void* bitmap, bool enabled, int checkState, bool radioCheck)
{
return BFWindow_AddMenuItem(mNativeWindow, parent, (int32)insertIdx, text, hotKey, bitmap, enabled ? 1 : 0, (int32)checkState, radioCheck ? 1 : 0);
}
public virtual void ModifyMenuItem(void* item, String text, String hotKey, void* bitmap, bool enabled, int checkState, bool radioCheck)
{
BFWindow_ModifyMenuItem(mNativeWindow, item, text, hotKey, bitmap, enabled ? 1 : 0, (int32)checkState, radioCheck ? 1 : 0);
}
public virtual void DeleteMenuItem(void* menuItem)
{
BFWindow_DeleteMenuItem(mNativeWindow, menuItem);
}
public virtual void MenuItemSelected(SysMenu sysMenu)
{
sysMenu.Selected();
}
public virtual void NativeMenuItemSelected(void* menu)
{
SysMenu aSysMenu = mSysMenuMap[(int)menu];
MenuItemSelected(aSysMenu);
}
public virtual SysBitmap LoadSysBitmap(String path)
{
return null;
}
public virtual void GotFocus()
{
if (mHasFocus)
return;
mHasFocus = true;
//Console.WriteLine("GotFocus {0}", mTitle);
}
public virtual void LostFocus(BFWindow newFocus)
{
if (!mHasFocus)
return;
mHasFocus = false;
if (mNativeWindow != null)
BFWindow_LostFocus(mNativeWindow, (newFocus != null) ? newFocus.mNativeWindow : null);
//TODO: REMOVE
//Debug.WriteLine("LostFocus {0}", mTitle);
}
public virtual void KeyChar(char32 theChar)
{
}
public virtual bool KeyDown(int32 keyCode, int32 isRepeat)
{
return false;
}
public virtual void KeyUp(int32 keyCode)
{
}
public virtual HitTestResult HitTest(int32 x, int32 y)
{
return HitTestResult.NotHandled;
}
public virtual void MouseMove(int32 x, int32 y)
{
}
public virtual void MouseProxyMove(int32 x, int32 y)
{
}
public virtual void MouseDown(int32 x, int32 y, int32 btn, int32 btnCount)
{
}
public virtual void MouseUp(int32 x, int32 y, int32 btn)
{
}
public virtual void MouseWheel(int32 x, int32 y, int32 delta)
{
}
public virtual void MouseLeave()
{
}
public override void Draw(Graphics g)
{
}
public virtual void Update()
{
}
}
#else
public class BFWindow : BFWindowBase, IStudioClientWindow
{
//IStudioWidgetWindow mProxy;
public int mClientWidth;
public int mClientHeight;
public int mClientX;
public int mClientY;
public float mAlpha = 1.0f;
public bool mVisible = true;
public Flags mWindowFlags;
public IPCProxy<IStudioHostWindow> mRemoteWindow;
public IPCEndpoint<IStudioClientWindow> mStudioClientWindow;
public BFWindow(BFWindow parent, string title, int x, int y, int width, int height, BFWindow.Flags windowFlags)
{
mStudioClientWindow = IPCEndpoint<IStudioClientWindow>.Create(this);
IStudioHost studioInstance = BFApp.sApp.mStudioHost.Proxy;
IPCObjectId remoteWindowId = studioInstance.CreateWindow(mStudioClientWindow.ObjId, 0, title, x, y, width, height, (int)windowFlags);
mRemoteWindow = IPCProxy<IStudioHostWindow>.Create(remoteWindowId);
mDefaultDrawLayer = new DrawLayer(this);
BFApp.sApp.mWindows.Add(this);
mClientX = 0;
mClientY = 0;
mClientWidth = width;
mClientHeight = height;
mWindowFlags = windowFlags;
}
public void Dispose()
{
Close();
}
public virtual int CloseQuery()
{
return 1;
}
public virtual void Close(bool force = false)
{
//if (mNativeWindow != null)
//BFWindow_Close(mNativeWindow, force ? 1 : 0);
}
public virtual void Closed()
{
//mNativeWindow = null;
BFApp.sApp.mWindows.Remove(this);
}
public virtual void Moved()
{
//BFWindow_GetPosition(mNativeWindow, out mX, out mY, out mWindowWidth, out mWindowHeight, out mClientX, out mClientY, out mClientWidth, out mClientHeight);
}
public virtual void SetClientPosition(float x, float y)
{
//BFWindow_SetClientPosition(mNativeWindow, (int)x, (int)y);
}
public virtual void SetAlpha(float alpha, uint destAlphaSrcMask, bool mouseVisible)
{
//mAlpha = alpha;
//BFWindow_SetAlpha(mNativeWindow, alpha, destAlphaSrcMask, mouseVisible ? 1 : 0);
}
public virtual void* AddMenuItem(void* parent, string text, string hotKey, void* bitmap, bool enabled, int checkState, bool radioCheck)
{
//return BFWindow_AddMenuItem(mNativeWindow, parent, text, hotKey, bitmap, enabled ? 1 : 0, checkState, radioCheck ? 1 : 0);
return null;
}
public virtual void MenuItemSelected(SysMenu sysMenu)
{
sysMenu.Selected();
}
public virtual void NativeMenuItemSelected(void* menu)
{
//SysMenu aSysMenu = mSysMenuMap[menu];
//MenuItemSelected(aSysMenu);
}
public virtual SysBitmap LoadSysBitmap(string path)
{
return null;
}
public virtual void GotFocus()
{
}
public virtual void LostFocus()
{
}
public virtual void KeyChar(char32 theChar)
{
}
public virtual void KeyDown(int keyCode, int isRepeat)
{
}
public virtual void KeyUp(int keyCode)
{
}
public virtual void MouseMove(int x, int y)
{
}
public virtual void MouseProxyMove(int x, int y)
{
}
public virtual void MouseDown(int x, int y, int btn, int btnCount)
{
}
public virtual void MouseUp(int x, int y, int btn)
{
}
public virtual void MouseWheel(int x, int y, int delta)
{
}
public virtual void MouseLeave()
{
}
public virtual void Update()
{
}
public override void PreDraw(Graphics g)
{
base.PreDraw(g);
mRemoteWindow.Proxy.RemoteDrawingStarted();
}
public override void PostDraw(Graphics g)
{
base.PostDraw(g);
mRemoteWindow.Proxy.RemoteDrawingDone();
}
public void SetIsVisible(bool visible)
{
mVisible = visible;
}
}
#endif
}

View file

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Beefy
{
public class Rand
{
static Random sRand = new Random() ~ delete _;
public static int32 Int()
{
return sRand.NextI32();
}
public static int32 SInt()
{
return sRand.Next(int32.MinValue, int32.MaxValue);
}
public static float Float()
{
return (float)sRand.NextDouble();
}
public static float SFloat()
{
return (float)(sRand.NextDouble() * 2) - 1.0f;
}
}
}

View file

@ -0,0 +1,447 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Security.Cryptography;
namespace Beefy
{
public static class Utils
{
static Random mRandom = new Random() ~ delete _;
[StdCall, CLink]
static extern int32 BF_TickCount();
[StdCall, CLink]
static extern int32 BF_TickCountMicroFast();
public static float Deg2Rad = Math.PI_f / 180.0f;
public static int32 Rand()
{
return mRandom.NextI32();
}
public static float RandFloat()
{
return (Rand() & 0xFFFFFF) / (float)0xFFFFFF;
}
public static float Interpolate(float left, float right, float pct)
{
return left + (right - left) * pct;
}
public static float Clamp(float val, float min, float max)
{
return Math.Max(min, Math.Min(max, val));
}
public static float Lerp(float val1, float val2, float pct)
{
return val1 + (val2 - val1) * pct;
}
public static float EaseInAndOut(float pct)
{
return ((-Math.Cos(pct * Math.PI_f) + 1.0f) / 2.0f);
}
public static float Distance(float dX, float dY)
{
return Math.Sqrt(dX * dX + dY * dY);
}
public static char8 CtrlKeyChar(char32 theChar)
{
char8 aChar = (char8)(theChar + (int)'A' - (char8)1);
if (aChar < (char8)0)
return (char8)0;
return aChar;
}
public static uint32 GetTickCount()
{
return (uint32)BF_TickCount();
}
public static uint64 GetTickCountMicro()
{
return (uint32)BF_TickCountMicroFast();
}
public static Object DefaultConstruct(Type theType)
{
ThrowUnimplemented();
/*ConstructorInfo constructor = theType.GetConstructors()[0];
ParameterInfo[] paramInfos = constructor.GetParameters();
object[] aParams = new object[paramInfos.Length];
for (int paramIdx = 0; paramIdx < aParams.Length; paramIdx++)
aParams[paramIdx] = paramInfos[paramIdx].DefaultValue;
object newObject = constructor.Invoke(aParams);
return newObject;*/
}
/*public static int StrToInt(string theString)
{
if (theString.StartsWith("0X", StringComparison.OrdinalIgnoreCase))
return Convert.ToInt32(theString.Substring(2), 16);
return Convert.ToInt32(theString);
}
// WaitForEvent differs from theEvent.WaitOne in that it doesn't pump the Windows
// message loop under STAThread
public static bool WaitForEvent(EventWaitHandle theEvent, int timeMS)
{
return WaitForSingleObject(theEvent.SafeWaitHandle, timeMS) == 0;
}*/
public static void GetDirWithSlash(String dir)
{
if (dir.IsEmpty)
return;
char8 endChar = dir[dir.Length - 1];
if ((endChar != Path.DirectorySeparatorChar) && (endChar != Path.AltDirectorySeparatorChar))
dir.Append(Path.DirectorySeparatorChar);
}
public static Result<void> DelTree(String path, Predicate<String> fileFilter = null)
{
if (path.Length <= 2)
return .Err;
if ((path[0] != '/') && (path[0] != '\\'))
{
if (path[1] == ':')
{
if (path.Length < 3)
return .Err;
}
else
return .Err;
}
for (var fileEntry in Directory.EnumerateDirectories(path))
{
let fileName = scope String();
fileEntry.GetFilePath(fileName);
Try!(DelTree(fileName, fileFilter));
}
for (var fileEntry in Directory.EnumerateFiles(path))
{
let fileName = scope String();
fileEntry.GetFilePath(fileName);
if (fileFilter != null)
if (!fileFilter(fileName))
continue;
Try!(File.SetAttributes(fileName, FileAttributes.Archive));
Try!(File.Delete(fileName));
}
// Allow failure for the directory, this can often be locked for various reasons
// but we only consider a file failure to be an "actual" failure
Directory.Delete(path).IgnoreError();
return .Ok;
}
public static Result<void, FileError> LoadTextFile(String fileName, String outBuffer, bool autoRetry = true, delegate void() onPreFilter = null)
{
// Retry for a while if the other side is still writing out the file
for (int i = 0; i < 100; i++)
{
if (File.ReadAllText(fileName, outBuffer, true) case .Err(let err))
{
bool retry = false;
if ((autoRetry) && (err case .FileOpenError(let fileOpenErr)))
{
if (fileOpenErr == .SharingViolation)
retry = true;
}
if (!retry)
return .Err(err);
}
else
break;
Thread.Sleep(20);
}
if (onPreFilter != null)
onPreFilter();
/*if (hashPtr != null)
*hashPtr = MD5.Hash(Span<uint8>((uint8*)outBuffer.Ptr, outBuffer.Length));*/
bool isAscii = false;
int outIdx = 0;
for (int32 i = 0; i < outBuffer.Length; i++)
{
char8 c = outBuffer[i];
if (c >= '\x80')
{
switch (UTF8.TryDecode(outBuffer.Ptr + i, outBuffer.Length - i))
{
case .Ok((?, let len)):
if (len > 1)
{
for (int cnt < len)
{
char8 cPart = outBuffer[i++];
outBuffer[outIdx++] = cPart;
}
i--;
continue;
}
case .Err: isAscii = true;
}
}
if (c != '\r')
{
if (outIdx == i)
{
outIdx++;
continue;
}
outBuffer[outIdx++] = c;
}
}
outBuffer.RemoveToEnd(outIdx);
if (isAscii)
{
String prevBuffer = scope String();
outBuffer.MoveTo(prevBuffer);
for (var c in prevBuffer.RawChars)
{
outBuffer.Append((char32)c, 1);
}
}
return .Ok;
}
public static bool FileTextEquals(String textA, String textB)
{
int32 posA = 0;
int32 posB = 0;
while (true)
{
char8 char8A = (char8)0;
char8 char8B = (char8)0;
while (posA < textA.Length)
{
char8A = textA[posA++];
if (char8A != '\r')
break;
char8A = (char8)0;
}
while (posB < textB.Length)
{
char8B = textB[posB++];
if (char8B != '\r')
break;
char8B = (char8)0;
}
if ((char8A == (char8)0) && (char8B == (char8)0))
return true;
if (char8A != char8B)
return false;
}
}
public static Result<void> WriteTextFile(StringView path, StringView text)
{
var stream = scope FileStream();
if (stream.Create(path) case .Err)
{
return .Err;
}
if (stream.WriteStrUnsized(text) case .Err)
return .Err;
return .Ok;
}
public static int LevenshteinDistance(String s, String t)
{
int n = s.Length;
int m = t.Length;
int32[,] d = new int32[n + 1, m + 1];
defer delete d;
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
for (int32 i = 0; i <= n; d[i, 0] = i++)
{}
for (int32 j = 0; j <= m; d[0, j] = j++)
{}
for (int32 i = 1; i <= n; i++)
{
for (int32 j = 1; j <= m; j++)
{
int32 cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
return d[n, m];
}
/*public static List<TSource> ToSortedList<TSource>(this IEnumerable<TSource> source)
{
var list = source.ToList();
list.Sort();
return list;
}*/
public static int64 DecodeInt64(ref uint8* ptr)
{
int64 value = 0;
int32 shift = 0;
int64 curByte;
repeat
{
curByte = *(ptr++);
value |= ((curByte & 0x7f) << shift);
shift += 7;
} while (curByte >= 128);
// Sign extend negative numbers.
if (((curByte & 0x40) != 0) && (shift < 64))
value |= -1 << shift;
return value;
}
public static int32 DecodeInt(uint8[] buf, ref int idx)
{
int32 value = 0;
int32 Shift = 0;
int32 curByte;
repeat
{
curByte = buf[idx++];
value |= ((curByte & 0x7f) << Shift);
Shift += 7;
} while (curByte >= 128);
// Sign extend negative numbers.
if ((curByte & 0x40) != 0)
value |= -1 << Shift;
return value;
}
public static void EncodeInt(uint8[] buf, ref int idx, int value)
{
int curValue = value;
bool hasMore;
repeat
{
uint8 curByte = (uint8)(curValue & 0x7f);
curValue >>= 7;
hasMore = !((((curValue == 0) && ((curByte & 0x40) == 0)) ||
((curValue == -1) && ((curByte & 0x40) != 0))));
if (hasMore)
curByte |= 0x80;
buf[idx++] = curByte;
}
while (hasMore);
}
public static bool Contains<T>(IEnumerator<T> itr, T value)
{
for (var check in itr)
if (check == value)
return true;
return false;
}
public static void QuoteString(String str, String strOut)
{
strOut.Append('"');
for (int i < str.Length)
{
char8 c = str[i];
strOut.Append(c);
}
strOut.Append('"');
}
public static void ParseSpaceSep(String str, ref int idx, String subStr)
{
while (idx < str.Length)
{
char8 c = str[idx];
if (c != ' ')
break;
idx++;
}
if (idx >= str.Length)
return;
// Quoted
if (str[idx] == '"')
{
idx++;
while (idx < str.Length)
{
char8 c = str[idx++];
if (c == '"')
break;
subStr.Append(c);
}
return;
}
// Unquoted
while (idx < str.Length)
{
char8 c = str[idx++];
if (c == ' ')
break;
subStr.Append(c);
}
}
public static void SnapScale(ref float val, float scale)
{
val *= scale;
float frac = val - (int)val;
if ((frac <= 0.001f) || (frac >= 0.999f))
val = (float)Math.Round(val);
}
public static void RoundScale(ref float val, float scale)
{
val = (float)Math.Round(val * scale);
}
}
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
namespace Beefy.events
{
public class DialogEvent : Event
{
public bool mCloseDialog;
public ButtonWidget mButton;
public String mResult;
}
}

View file

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.events
{
public class DragEvent : Event
{
public float mX;
public float mY;
public Object mDragTarget;
public int32 mDragTargetDir;
public bool mDragAllowed = true;
}
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.events
{
public class EditEvent : Event
{
//string mText;
}
}

View file

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.events
{
public class Event
{
public Object mSender;
public bool mHandled;
}
}

View file

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
namespace Beefy.widgets
{
public enum KeyFlags
{
None = 0,
Alt = 1,
Ctrl = 2,
Shift = 4
}
}
namespace Beefy.events
{
/*[Flags]
public enum KeyFlags
{
Alt = 1,
Ctrl = 2,
Shift = 4
}*/
public class KeyDownEvent : Event
{
public KeyFlags mKeyFlags;
public KeyCode mKeyCode;
public bool mIsRepeat;
}
public class KeyCharEvent : Event
{
public char32 mChar;
}
}

View file

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
namespace Beefy.events
{
public class MouseEvent : Event
{
public float mX;
public float mY;
public int32 mBtn;
public int32 mBtnCount;
public int32 mWheelDelta;
public void GetRootCoords(out float x, out float y)
{
Widget widget = (Widget)mSender;
widget.SelfToRootTranslate(mX, mY, out x, out y);
}
}
}

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.events
{
public class ScrollEvent : Event
{
public double mOldPos;
public double mNewPos;
public bool mIsFromUser;
}
}

View file

@ -0,0 +1,9 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
namespace Beefy.events
{
}

View file

@ -0,0 +1,493 @@
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Beefy.geom;
namespace Beefy.geom
{
public struct Matrix4
{
public float m00;
public float m01;
public float m02;
public float m03;
public float m10;
public float m11;
public float m12;
public float m13;
public float m20;
public float m21;
public float m22;
public float m23;
public float m30;
public float m31;
public float m32;
public float m33;
public static readonly Matrix4 Identity = Matrix4(1f, 0f, 0f, 0f,
0f, 1f, 0f, 0f,
0f, 0f, 1f, 0f,
0f, 0f, 0f, 1f);
public this(
float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33)
{
this.m00 = m00;
this.m01 = m01;
this.m02 = m02;
this.m03 = m03;
this.m10 = m10;
this.m11 = m11;
this.m12 = m12;
this.m13 = m13;
this.m20 = m20;
this.m21 = m21;
this.m22 = m22;
this.m23 = m23;
this.m30 = m30;
this.m31 = m31;
this.m32 = m32;
this.m33 = m33;
}
public static Matrix4 CreatePerspective(float width, float height, float nearPlaneDistance, float farPlaneDistance)
{
Matrix4 matrix;
if (nearPlaneDistance <= 0f)
{
Runtime.FatalError("nearPlaneDistance <= 0");
}
if (farPlaneDistance <= 0f)
{
Runtime.FatalError("farPlaneDistance <= 0");
}
if (nearPlaneDistance >= farPlaneDistance)
{
Runtime.FatalError("nearPlaneDistance >= farPlaneDistance");
}
/*matrix.M11 = (2f * nearPlaneDistance) / width;
matrix.M12 = matrix.M13 = matrix.M14 = 0f;
matrix.M22 = (2f * nearPlaneDistance) / height;
matrix.M21 = matrix.M23 = matrix.M24 = 0f;
matrix.M33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
matrix.M31 = matrix.M32 = 0f;
matrix.M34 = -1f;
matrix.M41 = matrix.M42 = matrix.M44 = 0f;
matrix.M43 = (nearPlaneDistance * farPlaneDistance) / (nearPlaneDistance - farPlaneDistance);*/
/*matrix.m00 = (2f * nearPlaneDistance) / width;
matrix.m01 = 0f;
matrix.m02 = 0f;
matrix.m03 = 0f;
matrix.m10 = 0f;
matrix.m11 = (2f * nearPlaneDistance) / height;
matrix.m12 = 0f;
matrix.m13 = 0f;
matrix.m20 = 0f;
matrix.m21 = 0f;
matrix.m22 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
matrix.m23 = (nearPlaneDistance * farPlaneDistance) / (nearPlaneDistance - farPlaneDistance);
matrix.m30 = 0f;
matrix.m31 = 0f;
matrix.m32 = -1f;
matrix.m33 = 0f; */
matrix.m00 = (2f * nearPlaneDistance) / width;
matrix.m10 = matrix.m20 = matrix.m30 = 0f;
matrix.m11 = (2f * nearPlaneDistance) / height;
matrix.m01 = matrix.m21 = matrix.m31 = 0f;
matrix.m22 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
matrix.m02 = matrix.m12 = 0f;
matrix.m32 = -1f;
matrix.m03 = matrix.m13 = matrix.m33 = 0f;
matrix.m23 = (nearPlaneDistance * farPlaneDistance) / (nearPlaneDistance - farPlaneDistance);
return matrix;
}
public static Matrix4 CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance)
{
Matrix4 result;
CreatePerspectiveFieldOfView(fieldOfView, aspectRatio, nearPlaneDistance, farPlaneDistance, out result);
return result;
}
public static void CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance, out Matrix4 result)
{
if ((fieldOfView <= 0f) || (fieldOfView >= 3.141593f))
{
Runtime.FatalError("fieldOfView <= 0 or >= PI");
}
if (nearPlaneDistance <= 0f)
{
Runtime.FatalError("nearPlaneDistance <= 0");
}
if (farPlaneDistance <= 0f)
{
Runtime.FatalError("farPlaneDistance <= 0");
}
if (nearPlaneDistance >= farPlaneDistance)
{
Runtime.FatalError("nearPlaneDistance >= farPlaneDistance");
}
float num = 1f / ((float)Math.Tan((double)(fieldOfView * 0.5f)));
float num9 = num / aspectRatio;
result.m00 = num9;
result.m10 = result.m20 = result.m30 = 0;
result.m11 = num;
result.m01 = result.m21 = result.m31 = 0;
result.m02 = result.m12 = 0f;
result.m22 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
result.m32 = -1;
result.m03 = result.m13 = result.m33 = 0;
result.m23 = (nearPlaneDistance * farPlaneDistance) / (nearPlaneDistance - farPlaneDistance);
}
public static Matrix4 CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float nearPlaneDistance, float farPlaneDistance)
{
Matrix4 result;
CreatePerspectiveOffCenter(left, right, bottom, top, nearPlaneDistance, farPlaneDistance, out result);
return result;
}
public static void CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float nearPlaneDistance, float farPlaneDistance, out Matrix4 result)
{
if (nearPlaneDistance <= 0f)
{
Runtime.FatalError("nearPlaneDistance <= 0");
}
if (farPlaneDistance <= 0f)
{
Runtime.FatalError("farPlaneDistance <= 0");
}
if (nearPlaneDistance >= farPlaneDistance)
{
Runtime.FatalError("nearPlaneDistance >= farPlaneDistance");
}
result.m00 = (2f * nearPlaneDistance) / (right - left);
result.m10 = result.m20 = result.m30 = 0;
result.m11 = (2f * nearPlaneDistance) / (top - bottom);
result.m01 = result.m21 = result.m31 = 0;
result.m02 = (left + right) / (right - left);
result.m12 = (top + bottom) / (top - bottom);
result.m22 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
result.m32 = -1;
result.m23 = (nearPlaneDistance * farPlaneDistance) / (nearPlaneDistance - farPlaneDistance);
result.m03 = result.m13 = result.m33 = 0;
}
public static Matrix4 Multiply(Matrix4 m1, Matrix4 m2)
{
Matrix4 r;
r.m00 = m1.m00 * m2.m00 + m1.m01 * m2.m10 + m1.m02 * m2.m20 + m1.m03 * m2.m30;
r.m01 = m1.m00 * m2.m01 + m1.m01 * m2.m11 + m1.m02 * m2.m21 + m1.m03 * m2.m31;
r.m02 = m1.m00 * m2.m02 + m1.m01 * m2.m12 + m1.m02 * m2.m22 + m1.m03 * m2.m32;
r.m03 = m1.m00 * m2.m03 + m1.m01 * m2.m13 + m1.m02 * m2.m23 + m1.m03 * m2.m33;
r.m10 = m1.m10 * m2.m00 + m1.m11 * m2.m10 + m1.m12 * m2.m20 + m1.m13 * m2.m30;
r.m11 = m1.m10 * m2.m01 + m1.m11 * m2.m11 + m1.m12 * m2.m21 + m1.m13 * m2.m31;
r.m12 = m1.m10 * m2.m02 + m1.m11 * m2.m12 + m1.m12 * m2.m22 + m1.m13 * m2.m32;
r.m13 = m1.m10 * m2.m03 + m1.m11 * m2.m13 + m1.m12 * m2.m23 + m1.m13 * m2.m33;
r.m20 = m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20 + m1.m23 * m2.m30;
r.m21 = m1.m20 * m2.m01 + m1.m21 * m2.m11 + m1.m22 * m2.m21 + m1.m23 * m2.m31;
r.m22 = m1.m20 * m2.m02 + m1.m21 * m2.m12 + m1.m22 * m2.m22 + m1.m23 * m2.m32;
r.m23 = m1.m20 * m2.m03 + m1.m21 * m2.m13 + m1.m22 * m2.m23 + m1.m23 * m2.m33;
r.m30 = m1.m30 * m2.m00 + m1.m31 * m2.m10 + m1.m32 * m2.m20 + m1.m33 * m2.m30;
r.m31 = m1.m30 * m2.m01 + m1.m31 * m2.m11 + m1.m32 * m2.m21 + m1.m33 * m2.m31;
r.m32 = m1.m30 * m2.m02 + m1.m31 * m2.m12 + m1.m32 * m2.m22 + m1.m33 * m2.m32;
r.m33 = m1.m30 * m2.m03 + m1.m31 * m2.m13 + m1.m32 * m2.m23 + m1.m33 * m2.m33;
return r;
}
public static Matrix4 Transpose(Matrix4 m)
{
return Matrix4(
m.m00, m.m10, m.m20, m.m30,
m.m01, m.m11, m.m21, m.m31,
m.m02, m.m12, m.m22, m.m32,
m.m03, m.m13, m.m23, m.m33);
}
public static Matrix4 CreateTranslation(float x, float y, float z)
{
return Matrix4(
1, 0, 0, x,
0, 1, 0, y,
0, 0, 1, z,
0, 0, 0, 1);
}
public static Matrix4 CreateTransform(Vector3 position, Vector3 scale, Quaternion orientation)
{
// Ordering:
// 1. Scale
// 2. Rotate
// 3. Translate
Matrix4 rot = orientation.ToMatrix();
return Matrix4(
scale.mX * rot.m00, scale.mY * rot.m01, scale.mZ * rot.m02, position.mX,
scale.mX * rot.m10, scale.mY * rot.m11, scale.mZ * rot.m12, position.mY,
scale.mX * rot.m20, scale.mY * rot.m21, scale.mZ * rot.m22, position.mZ,
0, 0, 0, 1);
}
public static Matrix4 CreateRotationX(float radians)
{
Matrix4 result = Matrix4.Identity;
var val1 = (float)Math.Cos(radians);
var val2 = (float)Math.Sin(radians);
result.m11 = val1;
result.m21 = val2;
result.m12 = -val2;
result.m22 = val1;
return result;
}
public static Matrix4 CreateRotationY(float radians)
{
Matrix4 returnMatrix = Matrix4.Identity;
var val1 = (float)Math.Cos(radians);
var val2 = (float)Math.Sin(radians);
returnMatrix.m00 = val1;
returnMatrix.m20 = -val2;
returnMatrix.m02 = val2;
returnMatrix.m22 = val1;
return returnMatrix;
}
public static Matrix4 CreateRotationZ(float radians)
{
Matrix4 returnMatrix = Matrix4.Identity;
var val1 = (float)Math.Cos(radians);
var val2 = (float)Math.Sin(radians);
returnMatrix.m00 = val1;
returnMatrix.m10 = val2;
returnMatrix.m01 = -val2;
returnMatrix.m11 = val1;
return returnMatrix;
}
public static Matrix4 CreateScale(float scale)
{
Matrix4 result;
result.m00 = scale;
result.m10 = 0;
result.m20 = 0;
result.m30 = 0;
result.m01 = 0;
result.m11 = scale;
result.m21 = 0;
result.m31 = 0;
result.m02 = 0;
result.m12 = 0;
result.m22 = scale;
result.m32 = 0;
result.m03 = 0;
result.m13 = 0;
result.m23 = 0;
result.m33 = 1;
return result;
}
public static Matrix4 CreateScale(float xScale, float yScale, float zScale)
{
Matrix4 result;
result.m00 = xScale;
result.m10 = 0;
result.m20 = 0;
result.m30 = 0;
result.m01 = 0;
result.m11 = yScale;
result.m21 = 0;
result.m31 = 0;
result.m02 = 0;
result.m12 = 0;
result.m22 = zScale;
result.m32 = 0;
result.m03 = 0;
result.m13 = 0;
result.m23 = 0;
result.m33 = 1;
return result;
}
public static Matrix4 CreateScale(Vector3 scales)
{
Matrix4 result;
result.m00 = scales.mX;
result.m10 = 0;
result.m20 = 0;
result.m30 = 0;
result.m01 = 0;
result.m11 = scales.mY;
result.m21 = 0;
result.m31 = 0;
result.m02 = 0;
result.m12 = 0;
result.m22 = scales.mZ;
result.m32 = 0;
result.m03 = 0;
result.m13 = 0;
result.m23 = 0;
result.m33 = 1;
return result;
}
public static Matrix4 CreateTranslation(Vector3 position)
{
Matrix4 result;
result.m00 = 1;
result.m10 = 0;
result.m20 = 0;
result.m30 = 0;
result.m01 = 0;
result.m11 = 1;
result.m21 = 0;
result.m31 = 0;
result.m02 = 0;
result.m12 = 0;
result.m22 = 1;
result.m32 = 0;
result.m03 = position.mX;
result.m13 = position.mY;
result.m23 = position.mZ;
result.m33 = 1;
return result;
}
/*public static Matrix4 Inverse()
{
Real m00 = m[0][0], m01 = m[0][1], m02 = m[0][2], m03 = m[0][3];
Real m10 = m[1][0], m11 = m[1][1], m12 = m[1][2], m13 = m[1][3];
Real m20 = m[2][0], m21 = m[2][1], m22 = m[2][2], m23 = m[2][3];
Real m30 = m[3][0], m31 = m[3][1], m32 = m[3][2], m33 = m[3][3];
Real v0 = m20 * m31 - m21 * m30;
Real v1 = m20 * m32 - m22 * m30;
Real v2 = m20 * m33 - m23 * m30;
Real v3 = m21 * m32 - m22 * m31;
Real v4 = m21 * m33 - m23 * m31;
Real v5 = m22 * m33 - m23 * m32;
Real t00 = + (v5 * m11 - v4 * m12 + v3 * m13);
Real t10 = - (v5 * m10 - v2 * m12 + v1 * m13);
Real t20 = + (v4 * m10 - v2 * m11 + v0 * m13);
Real t30 = - (v3 * m10 - v1 * m11 + v0 * m12);
Real invDet = 1 / (t00 * m00 + t10 * m01 + t20 * m02 + t30 * m03);
Real d00 = t00 * invDet;
Real d10 = t10 * invDet;
Real d20 = t20 * invDet;
Real d30 = t30 * invDet;
Real d01 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
Real d11 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
Real d21 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
Real d31 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
v0 = m10 * m31 - m11 * m30;
v1 = m10 * m32 - m12 * m30;
v2 = m10 * m33 - m13 * m30;
v3 = m11 * m32 - m12 * m31;
v4 = m11 * m33 - m13 * m31;
v5 = m12 * m33 - m13 * m32;
Real d02 = + (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
Real d12 = - (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
Real d22 = + (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
Real d32 = - (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
v0 = m21 * m10 - m20 * m11;
v1 = m22 * m10 - m20 * m12;
v2 = m23 * m10 - m20 * m13;
v3 = m22 * m11 - m21 * m12;
v4 = m23 * m11 - m21 * m13;
v5 = m23 * m12 - m22 * m13;
Real d03 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
Real d13 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
Real d23 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
Real d33 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
return Matrix4(
d00, d01, d02, d03,
d10, d11, d12, d13,
d20, d21, d22, d23,
d30, d31, d32, d33);
}*/
bool IsAffine()
{
return m30 == 0 && m31 == 0 && m32 == 0 && m33 == 1;
}
public static Matrix4 InverseAffine(Matrix4 mtx)
{
Debug.Assert(mtx.IsAffine());
float m10 = mtx.m10, m11 = mtx.m11, m12 = mtx.m12;
float m20 = mtx.m20, m21 = mtx.m21, m22 = mtx.m22;
float t00 = m22 * m11 - m21 * m12;
float t10 = m20 * m12 - m22 * m10;
float t20 = m21 * m10 - m20 * m11;
float m00 = mtx.m00, m01 = mtx.m01, m02 = mtx.m02;
float invDet = 1 / (m00 * t00 + m01 * t10 + m02 * t20);
t00 *= invDet; t10 *= invDet; t20 *= invDet;
m00 *= invDet; m01 *= invDet; m02 *= invDet;
float r00 = t00;
float r01 = m02 * m21 - m01 * m22;
float r02 = m01 * m12 - m02 * m11;
float r10 = t10;
float r11 = m00 * m22 - m02 * m20;
float r12 = m02 * m10 - m00 * m12;
float r20 = t20;
float r21 = m01 * m20 - m00 * m21;
float r22 = m00 * m11 - m01 * m10;
float m03 = mtx.m03, m13 = mtx.m13, m23 = mtx.m23;
float r03 = -(r00 * m03 + r01 * m13 + r02 * m23);
float r13 = -(r10 * m03 + r11 * m13 + r12 * m23);
float r23 = -(r20 * m03 + r21 * m13 + r22 * m23);
return Matrix4(
r00, r01, r02, r03,
r10, r11, r12, r13,
r20, r21, r22, r23,
0, 0, 0, 1);
}
}
}

View file

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.geom
{
public struct Point
{
public float x;
public float y;
public this(float x, float y)
{
this.x = x;
this.y = y;
}
}
}

View file

@ -0,0 +1,775 @@
using System;
using Beefy.gfx;
namespace Beefy.geom
{
public struct Quaternion : IHashable, IEquatable<Quaternion>
{
public float mX;
public float mY;
public float mZ;
public float mW;
public static readonly Quaternion Identity = Quaternion(0, 0, 0, 1);
public this(float x, float y, float z, float w)
{
mX = x;
mY = y;
mZ = z;
mW = w;
}
public this(Vector3 vectorPart, float scalarPart)
{
mX = vectorPart.mX;
mY = vectorPart.mY;
mZ = vectorPart.mZ;
mW = scalarPart;
}
public static Quaternion Add(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion quaternion;
quaternion.mX = quaternion1.mX + quaternion2.mX;
quaternion.mY = quaternion1.mY + quaternion2.mY;
quaternion.mZ = quaternion1.mZ + quaternion2.mZ;
quaternion.mW = quaternion1.mW + quaternion2.mW;
return quaternion;
}
public static void Add(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
{
result.mX = quaternion1.mX + quaternion2.mX;
result.mY = quaternion1.mY + quaternion2.mY;
result.mZ = quaternion1.mZ + quaternion2.mZ;
result.mW = quaternion1.mW + quaternion2.mW;
}
public static Quaternion Concatenate(Quaternion value1, Quaternion value2)
{
Quaternion quaternion;
float x = value2.mX;
float y = value2.mY;
float z = value2.mZ;
float w = value2.mW;
float num4 = value1.mX;
float num3 = value1.mY;
float num2 = value1.mZ;
float num = value1.mW;
float num12 = (y * num2) - (z * num3);
float num11 = (z * num4) - (x * num2);
float num10 = (x * num3) - (y * num4);
float num9 = ((x * num4) + (y * num3)) + (z * num2);
quaternion.mX = ((x * num) + (num4 * w)) + num12;
quaternion.mY = ((y * num) + (num3 * w)) + num11;
quaternion.mZ = ((z * num) + (num2 * w)) + num10;
quaternion.mW = (w * num) - num9;
return quaternion;
}
public static void Concatenate(ref Quaternion value1, ref Quaternion value2, out Quaternion result)
{
float x = value2.mX;
float y = value2.mY;
float z = value2.mZ;
float w = value2.mW;
float num4 = value1.mX;
float num3 = value1.mY;
float num2 = value1.mZ;
float num = value1.mW;
float num12 = (y * num2) - (z * num3);
float num11 = (z * num4) - (x * num2);
float num10 = (x * num3) - (y * num4);
float num9 = ((x * num4) + (y * num3)) + (z * num2);
result.mX = ((x * num) + (num4 * w)) + num12;
result.mY = ((y * num) + (num3 * w)) + num11;
result.mZ = ((z * num) + (num2 * w)) + num10;
result.mW = (w * num) - num9;
}
public void Conjugate() mut
{
mX = -mX;
mY = -mY;
mZ = -mZ;
}
public static Quaternion Conjugate(Quaternion value)
{
Quaternion quaternion;
quaternion.mX = -value.mX;
quaternion.mY = -value.mY;
quaternion.mZ = -value.mZ;
quaternion.mW = value.mW;
return quaternion;
}
public static void Conjugate(ref Quaternion value, out Quaternion result)
{
result.mX = -value.mX;
result.mY = -value.mY;
result.mZ = -value.mZ;
result.mW = value.mW;
}
public static Quaternion CreateFromAxisAngle(Vector3 axis, float angle)
{
Quaternion quaternion;
float num2 = angle * 0.5f;
float num = (float)Math.Sin((double)num2);
float num3 = (float)Math.Cos((double)num2);
quaternion.mX = axis.mX * num;
quaternion.mY = axis.mY * num;
quaternion.mZ = axis.mZ * num;
quaternion.mW = num3;
return quaternion;
}
public static void CreateFromAxisAngle(ref Vector3 axis, float angle, out Quaternion result)
{
float num2 = angle * 0.5f;
float num = (float)Math.Sin((double)num2);
float num3 = (float)Math.Cos((double)num2);
result.mX = axis.mX * num;
result.mY = axis.mY * num;
result.mZ = axis.mZ * num;
result.mW = num3;
}
public static Quaternion CreateFromRotationMatrix(Matrix4 matrix)
{
float num8 = (matrix.m11 + matrix.m22) + matrix.m33;
Quaternion quaternion = Quaternion();
if (num8 > 0f)
{
float num = (float)Math.Sqrt((double)(num8 + 1f));
quaternion.mW = num * 0.5f;
num = 0.5f / num;
quaternion.mX = (matrix.m23 - matrix.m32) * num;
quaternion.mY = (matrix.m31 - matrix.m13) * num;
quaternion.mZ = (matrix.m12 - matrix.m21) * num;
return quaternion;
}
if ((matrix.m11 >= matrix.m22) && (matrix.m11 >= matrix.m33))
{
float num7 = (float)Math.Sqrt((double)(((1f + matrix.m11) - matrix.m22) - matrix.m33));
float num4 = 0.5f / num7;
quaternion.mX = 0.5f * num7;
quaternion.mY = (matrix.m12 + matrix.m21) * num4;
quaternion.mZ = (matrix.m13 + matrix.m31) * num4;
quaternion.mW = (matrix.m23 - matrix.m32) * num4;
return quaternion;
}
if (matrix.m22 > matrix.m33)
{
float num6 = (float)Math.Sqrt((double)(((1f + matrix.m22) - matrix.m11) - matrix.m33));
float num3 = 0.5f / num6;
quaternion.mX = (matrix.m21 + matrix.m12) * num3;
quaternion.mY = 0.5f * num6;
quaternion.mZ = (matrix.m32 + matrix.m23) * num3;
quaternion.mW = (matrix.m31 - matrix.m13) * num3;
return quaternion;
}
float num5 = (float)Math.Sqrt((double)(((1f + matrix.m33) - matrix.m11) - matrix.m22));
float num2 = 0.5f / num5;
quaternion.mX = (matrix.m31 + matrix.m13) * num2;
quaternion.mY = (matrix.m32 + matrix.m23) * num2;
quaternion.mZ = 0.5f * num5;
quaternion.mW = (matrix.m12 - matrix.m21) * num2;
return quaternion;
}
public static void CreateFromRotationMatrix(ref Matrix4 matrix, out Quaternion result)
{
float num8 = (matrix.m11 + matrix.m22) + matrix.m33;
if (num8 > 0f)
{
float num = (float)Math.Sqrt((double)(num8 + 1f));
result.mW = num * 0.5f;
num = 0.5f / num;
result.mX = (matrix.m23 - matrix.m32) * num;
result.mY = (matrix.m31 - matrix.m13) * num;
result.mZ = (matrix.m12 - matrix.m21) * num;
}
else if ((matrix.m11 >= matrix.m22) && (matrix.m11 >= matrix.m33))
{
float num7 = (float)Math.Sqrt((double)(((1f + matrix.m11) - matrix.m22) - matrix.m33));
float num4 = 0.5f / num7;
result.mX = 0.5f * num7;
result.mY = (matrix.m12 + matrix.m21) * num4;
result.mZ = (matrix.m13 + matrix.m31) * num4;
result.mW = (matrix.m23 - matrix.m32) * num4;
}
else if (matrix.m22 > matrix.m33)
{
float num6 = (float)Math.Sqrt((double)(((1f + matrix.m22) - matrix.m11) - matrix.m33));
float num3 = 0.5f / num6;
result.mX = (matrix.m21 + matrix.m12) * num3;
result.mY = 0.5f * num6;
result.mZ = (matrix.m32 + matrix.m23) * num3;
result.mW = (matrix.m31 - matrix.m13) * num3;
}
else
{
float num5 = (float)Math.Sqrt((double)(((1f + matrix.m33) - matrix.m11) - matrix.m22));
float num2 = 0.5f / num5;
result.mX = (matrix.m31 + matrix.m13) * num2;
result.mY = (matrix.m32 + matrix.m23) * num2;
result.mZ = 0.5f * num5;
result.mW = (matrix.m12 - matrix.m21) * num2;
}
}
public static Quaternion CreateFromYawPitchRoll(float yaw, float pitch, float roll)
{
Quaternion quaternion;
float num9 = roll * 0.5f;
float num6 = (float)Math.Sin((double)num9);
float num5 = (float)Math.Cos((double)num9);
float num8 = pitch * 0.5f;
float num4 = (float)Math.Sin((double)num8);
float num3 = (float)Math.Cos((double)num8);
float num7 = yaw * 0.5f;
float num2 = (float)Math.Sin((double)num7);
float num = (float)Math.Cos((double)num7);
quaternion.mX = ((num * num4) * num5) + ((num2 * num3) * num6);
quaternion.mY = ((num2 * num3) * num5) - ((num * num4) * num6);
quaternion.mZ = ((num * num3) * num6) - ((num2 * num4) * num5);
quaternion.mW = ((num * num3) * num5) + ((num2 * num4) * num6);
return quaternion;
}
public static void CreateFromYawPitchRoll(float yaw, float pitch, float roll, out Quaternion result)
{
float num9 = roll * 0.5f;
float num6 = (float)Math.Sin((double)num9);
float num5 = (float)Math.Cos((double)num9);
float num8 = pitch * 0.5f;
float num4 = (float)Math.Sin((double)num8);
float num3 = (float)Math.Cos((double)num8);
float num7 = yaw * 0.5f;
float num2 = (float)Math.Sin((double)num7);
float num = (float)Math.Cos((double)num7);
result.mX = ((num * num4) * num5) + ((num2 * num3) * num6);
result.mY = ((num2 * num3) * num5) - ((num * num4) * num6);
result.mZ = ((num * num3) * num6) - ((num2 * num4) * num5);
result.mW = ((num * num3) * num5) + ((num2 * num4) * num6);
}
public static Quaternion Divide(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion quaternion;
float x = quaternion1.mX;
float y = quaternion1.mY;
float z = quaternion1.mZ;
float w = quaternion1.mW;
float num14 = (((quaternion2.mX * quaternion2.mX) + (quaternion2.mY * quaternion2.mY)) + (quaternion2.mZ * quaternion2.mZ)) + (quaternion2.mW * quaternion2.mW);
float num5 = 1f / num14;
float num4 = -quaternion2.mX * num5;
float num3 = -quaternion2.mY * num5;
float num2 = -quaternion2.mZ * num5;
float num = quaternion2.mW * num5;
float num13 = (y * num2) - (z * num3);
float num12 = (z * num4) - (x * num2);
float num11 = (x * num3) - (y * num4);
float num10 = ((x * num4) + (y * num3)) + (z * num2);
quaternion.mX = ((x * num) + (num4 * w)) + num13;
quaternion.mY = ((y * num) + (num3 * w)) + num12;
quaternion.mZ = ((z * num) + (num2 * w)) + num11;
quaternion.mW = (w * num) - num10;
return quaternion;
}
public static void Divide(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
{
float x = quaternion1.mX;
float y = quaternion1.mY;
float z = quaternion1.mZ;
float w = quaternion1.mW;
float num14 = (((quaternion2.mX * quaternion2.mX) + (quaternion2.mY * quaternion2.mY)) + (quaternion2.mZ * quaternion2.mZ)) + (quaternion2.mW * quaternion2.mW);
float num5 = 1f / num14;
float num4 = -quaternion2.mX * num5;
float num3 = -quaternion2.mY * num5;
float num2 = -quaternion2.mZ * num5;
float num = quaternion2.mW * num5;
float num13 = (y * num2) - (z * num3);
float num12 = (z * num4) - (x * num2);
float num11 = (x * num3) - (y * num4);
float num10 = ((x * num4) + (y * num3)) + (z * num2);
result.mX = ((x * num) + (num4 * w)) + num13;
result.mY = ((y * num) + (num3 * w)) + num12;
result.mZ = ((z * num) + (num2 * w)) + num11;
result.mW = (w * num) - num10;
}
public static float Dot(Quaternion quaternion1, Quaternion quaternion2)
{
return ((((quaternion1.mX * quaternion2.mX) + (quaternion1.mY * quaternion2.mY)) + (quaternion1.mZ * quaternion2.mZ)) + (quaternion1.mW * quaternion2.mW));
}
public static void Dot(ref Quaternion quaternion1, ref Quaternion quaternion2, out float result)
{
result = (((quaternion1.mX * quaternion2.mX) + (quaternion1.mY * quaternion2.mY)) + (quaternion1.mZ * quaternion2.mZ)) + (quaternion1.mW * quaternion2.mW);
}
public bool Equals(Quaternion other)
{
return (mX == other.mX) && (mY == other.mY) && (mZ == other.mZ) && (mW == other.mW);
}
public int GetHashCode()
{
//return ((mX.GetHashCode() + mY.GetHashCode()) + mZ.GetHashCode()) + mW.GetHashCode();
ThrowUnimplemented();
}
public static Quaternion Inverse(Quaternion quaternion)
{
Quaternion quaternion2;
float num2 = (((quaternion.mX * quaternion.mX) + (quaternion.mY * quaternion.mY)) + (quaternion.mZ * quaternion.mZ)) + (quaternion.mW * quaternion.mW);
float num = 1f / num2;
quaternion2.mX = -quaternion.mX * num;
quaternion2.mY = -quaternion.mY * num;
quaternion2.mZ = -quaternion.mZ * num;
quaternion2.mW = quaternion.mW * num;
return quaternion2;
}
public static void Inverse(ref Quaternion quaternion, out Quaternion result)
{
float num2 = (((quaternion.mX * quaternion.mX) + (quaternion.mY * quaternion.mY)) + (quaternion.mZ * quaternion.mZ)) + (quaternion.mW * quaternion.mW);
float num = 1f / num2;
result.mX = -quaternion.mX * num;
result.mY = -quaternion.mY * num;
result.mZ = -quaternion.mZ * num;
result.mW = quaternion.mW * num;
}
public float Length()
{
float num = (((mX * mX) + (mY * mY)) + (mZ * mZ)) + (mW * mW);
return (float)Math.Sqrt((double)num);
}
public float LengthSquared()
{
return ((((mX * mX) + (mY * mY)) + (mZ * mZ)) + (mW * mW));
}
public static Quaternion Lerp(Quaternion quaternion1, Quaternion quaternion2, float amount)
{
float num = amount;
float num2 = 1f - num;
Quaternion quaternion = Quaternion();
float num5 = (((quaternion1.mX * quaternion2.mX) + (quaternion1.mY * quaternion2.mY)) + (quaternion1.mZ * quaternion2.mZ)) + (quaternion1.mW * quaternion2.mW);
if (num5 >= 0f)
{
quaternion.mX = (num2 * quaternion1.mX) + (num * quaternion2.mX);
quaternion.mY = (num2 * quaternion1.mY) + (num * quaternion2.mY);
quaternion.mZ = (num2 * quaternion1.mZ) + (num * quaternion2.mZ);
quaternion.mW = (num2 * quaternion1.mW) + (num * quaternion2.mW);
}
else
{
quaternion.mX = (num2 * quaternion1.mX) - (num * quaternion2.mX);
quaternion.mY = (num2 * quaternion1.mY) - (num * quaternion2.mY);
quaternion.mZ = (num2 * quaternion1.mZ) - (num * quaternion2.mZ);
quaternion.mW = (num2 * quaternion1.mW) - (num * quaternion2.mW);
}
float num4 = (((quaternion.mX * quaternion.mX) + (quaternion.mY * quaternion.mY)) + (quaternion.mZ * quaternion.mZ)) + (quaternion.mW * quaternion.mW);
float num3 = 1f / ((float)Math.Sqrt((double)num4));
quaternion.mX *= num3;
quaternion.mY *= num3;
quaternion.mZ *= num3;
quaternion.mW *= num3;
return quaternion;
}
public static void Lerp(ref Quaternion quaternion1, ref Quaternion quaternion2, float amount, out Quaternion result)
{
float num = amount;
float num2 = 1f - num;
float num5 = (((quaternion1.mX * quaternion2.mX) + (quaternion1.mY * quaternion2.mY)) + (quaternion1.mZ * quaternion2.mZ)) + (quaternion1.mW * quaternion2.mW);
if (num5 >= 0f)
{
result.mX = (num2 * quaternion1.mX) + (num * quaternion2.mX);
result.mY = (num2 * quaternion1.mY) + (num * quaternion2.mY);
result.mZ = (num2 * quaternion1.mZ) + (num * quaternion2.mZ);
result.mW = (num2 * quaternion1.mW) + (num * quaternion2.mW);
}
else
{
result.mX = (num2 * quaternion1.mX) - (num * quaternion2.mX);
result.mY = (num2 * quaternion1.mY) - (num * quaternion2.mY);
result.mZ = (num2 * quaternion1.mZ) - (num * quaternion2.mZ);
result.mW = (num2 * quaternion1.mW) - (num * quaternion2.mW);
}
float num4 = (((result.mX * result.mX) + (result.mY * result.mY)) + (result.mZ * result.mZ)) + (result.mW * result.mW);
float num3 = 1f / ((float)Math.Sqrt((double)num4));
result.mX *= num3;
result.mY *= num3;
result.mZ *= num3;
result.mW *= num3;
}
public static Quaternion Slerp(Quaternion quaternion1, Quaternion quaternion2, float amount)
{
float num2;
float num3;
Quaternion quaternion;
float num = amount;
float num4 = (((quaternion1.mX * quaternion2.mX) + (quaternion1.mY * quaternion2.mY)) + (quaternion1.mZ * quaternion2.mZ)) + (quaternion1.mW * quaternion2.mW);
bool flag = false;
if (num4 < 0f)
{
flag = true;
num4 = -num4;
}
if (num4 > 0.999999f)
{
num3 = 1f - num;
num2 = flag ? -num : num;
}
else
{
float num5 = (float)Math.Acos((double)num4);
float num6 = (float)(1.0 / Math.Sin((double)num5));
num3 = ((float)Math.Sin((double)((1f - num) * num5))) * num6;
num2 = flag ? (((float)(-Math.Sin((double)(num * num5))) * num6)) : (((float)Math.Sin((double)(num * num5))) * num6);
}
quaternion.mX = (num3 * quaternion1.mX) + (num2 * quaternion2.mX);
quaternion.mY = (num3 * quaternion1.mY) + (num2 * quaternion2.mY);
quaternion.mZ = (num3 * quaternion1.mZ) + (num2 * quaternion2.mZ);
quaternion.mW = (num3 * quaternion1.mW) + (num2 * quaternion2.mW);
return quaternion;
}
public static void Slerp(ref Quaternion quaternion1, ref Quaternion quaternion2, float amount, out Quaternion result)
{
float num2;
float num3;
float num = amount;
float num4 = (((quaternion1.mX * quaternion2.mX) + (quaternion1.mY * quaternion2.mY)) + (quaternion1.mZ * quaternion2.mZ)) + (quaternion1.mW * quaternion2.mW);
bool flag = false;
if (num4 < 0f)
{
flag = true;
num4 = -num4;
}
if (num4 > 0.999999f)
{
num3 = 1f - num;
num2 = flag ? -num : num;
}
else
{
float num5 = (float)Math.Acos((double)num4);
float num6 = (float)(1.0 / Math.Sin((double)num5));
num3 = ((float)Math.Sin((double)((1f - num) * num5))) * num6;
num2 = flag ? (((float)(-Math.Sin((double)(num * num5))) * num6)) : (((float)Math.Sin((double)(num * num5))) * num6);
}
result.mX = (num3 * quaternion1.mX) + (num2 * quaternion2.mX);
result.mY = (num3 * quaternion1.mY) + (num2 * quaternion2.mY);
result.mZ = (num3 * quaternion1.mZ) + (num2 * quaternion2.mZ);
result.mW = (num3 * quaternion1.mW) + (num2 * quaternion2.mW);
}
public static Quaternion Subtract(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion quaternion;
quaternion.mX = quaternion1.mX - quaternion2.mX;
quaternion.mY = quaternion1.mY - quaternion2.mY;
quaternion.mZ = quaternion1.mZ - quaternion2.mZ;
quaternion.mW = quaternion1.mW - quaternion2.mW;
return quaternion;
}
public static void Subtract(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
{
result.mX = quaternion1.mX - quaternion2.mX;
result.mY = quaternion1.mY - quaternion2.mY;
result.mZ = quaternion1.mZ - quaternion2.mZ;
result.mW = quaternion1.mW - quaternion2.mW;
}
public static Quaternion Multiply(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion quaternion;
float x = quaternion1.mX;
float y = quaternion1.mY;
float z = quaternion1.mZ;
float w = quaternion1.mW;
float num4 = quaternion2.mX;
float num3 = quaternion2.mY;
float num2 = quaternion2.mZ;
float num = quaternion2.mW;
float num12 = (y * num2) - (z * num3);
float num11 = (z * num4) - (x * num2);
float num10 = (x * num3) - (y * num4);
float num9 = ((x * num4) + (y * num3)) + (z * num2);
quaternion.mX = ((x * num) + (num4 * w)) + num12;
quaternion.mY = ((y * num) + (num3 * w)) + num11;
quaternion.mZ = ((z * num) + (num2 * w)) + num10;
quaternion.mW = (w * num) - num9;
return quaternion;
}
public static Quaternion Multiply(Quaternion quaternion1, float scaleFactor)
{
Quaternion quaternion;
quaternion.mX = quaternion1.mX * scaleFactor;
quaternion.mY = quaternion1.mY * scaleFactor;
quaternion.mZ = quaternion1.mZ * scaleFactor;
quaternion.mW = quaternion1.mW * scaleFactor;
return quaternion;
}
public static void Multiply(ref Quaternion quaternion1, float scaleFactor, out Quaternion result)
{
result.mX = quaternion1.mX * scaleFactor;
result.mY = quaternion1.mY * scaleFactor;
result.mZ = quaternion1.mZ * scaleFactor;
result.mW = quaternion1.mW * scaleFactor;
}
public static void Multiply(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result)
{
float x = quaternion1.mX;
float y = quaternion1.mY;
float z = quaternion1.mZ;
float w = quaternion1.mW;
float num4 = quaternion2.mX;
float num3 = quaternion2.mY;
float num2 = quaternion2.mZ;
float num = quaternion2.mW;
float num12 = (y * num2) - (z * num3);
float num11 = (z * num4) - (x * num2);
float num10 = (x * num3) - (y * num4);
float num9 = ((x * num4) + (y * num3)) + (z * num2);
result.mX = ((x * num) + (num4 * w)) + num12;
result.mY = ((y * num) + (num3 * w)) + num11;
result.mZ = ((z * num) + (num2 * w)) + num10;
result.mW = (w * num) - num9;
}
public static Quaternion Negate(Quaternion quaternion)
{
Quaternion quaternion2;
quaternion2.mX = -quaternion.mX;
quaternion2.mY = -quaternion.mY;
quaternion2.mZ = -quaternion.mZ;
quaternion2.mW = -quaternion.mW;
return quaternion2;
}
public static void Negate(ref Quaternion quaternion, out Quaternion result)
{
result.mX = -quaternion.mX;
result.mY = -quaternion.mY;
result.mZ = -quaternion.mZ;
result.mW = -quaternion.mW;
}
public void Normalize() mut
{
float num2 = (((mX * mX) + (mY * mY)) + (mZ * mZ)) + (mW * mW);
float num = 1f / ((float)Math.Sqrt((double)num2));
mX *= num;
mY *= num;
mZ *= num;
mW *= num;
}
public static Quaternion Normalize(Quaternion quaternion)
{
Quaternion quaternion2;
float num2 = (((quaternion.mX * quaternion.mX) + (quaternion.mY * quaternion.mY)) + (quaternion.mZ * quaternion.mZ)) + (quaternion.mW * quaternion.mW);
float num = 1f / ((float)Math.Sqrt((double)num2));
quaternion2.mX = quaternion.mX * num;
quaternion2.mY = quaternion.mY * num;
quaternion2.mZ = quaternion.mZ * num;
quaternion2.mW = quaternion.mW * num;
return quaternion2;
}
public static void Normalize(ref Quaternion quaternion, out Quaternion result)
{
float num2 = (((quaternion.mX * quaternion.mX) + (quaternion.mY * quaternion.mY)) + (quaternion.mZ * quaternion.mZ)) + (quaternion.mW * quaternion.mW);
float num = 1f / ((float)Math.Sqrt((double)num2));
result.mX = quaternion.mX * num;
result.mY = quaternion.mY * num;
result.mZ = quaternion.mZ * num;
result.mW = quaternion.mW * num;
}
public static Quaternion operator +(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion quaternion;
quaternion.mX = quaternion1.mX + quaternion2.mX;
quaternion.mY = quaternion1.mY + quaternion2.mY;
quaternion.mZ = quaternion1.mZ + quaternion2.mZ;
quaternion.mW = quaternion1.mW + quaternion2.mW;
return quaternion;
}
public static Quaternion operator /(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion quaternion;
float x = quaternion1.mX;
float y = quaternion1.mY;
float z = quaternion1.mZ;
float w = quaternion1.mW;
float num14 = (((quaternion2.mX * quaternion2.mX) + (quaternion2.mY * quaternion2.mY)) + (quaternion2.mZ * quaternion2.mZ)) + (quaternion2.mW * quaternion2.mW);
float num5 = 1f / num14;
float num4 = -quaternion2.mX * num5;
float num3 = -quaternion2.mY * num5;
float num2 = -quaternion2.mZ * num5;
float num = quaternion2.mW * num5;
float num13 = (y * num2) - (z * num3);
float num12 = (z * num4) - (x * num2);
float num11 = (x * num3) - (y * num4);
float num10 = ((x * num4) + (y * num3)) + (z * num2);
quaternion.mX = ((x * num) + (num4 * w)) + num13;
quaternion.mY = ((y * num) + (num3 * w)) + num12;
quaternion.mZ = ((z * num) + (num2 * w)) + num11;
quaternion.mW = (w * num) - num10;
return quaternion;
}
public static bool operator ==(Quaternion quaternion1, Quaternion quaternion2)
{
return ((((quaternion1.mX == quaternion2.mX) && (quaternion1.mY == quaternion2.mY)) && (quaternion1.mZ == quaternion2.mZ)) && (quaternion1.mW == quaternion2.mW));
}
public static bool operator !=(Quaternion quaternion1, Quaternion quaternion2)
{
if (((quaternion1.mX == quaternion2.mX) && (quaternion1.mY == quaternion2.mY)) && (quaternion1.mZ == quaternion2.mZ))
return (quaternion1.mW != quaternion2.mW);
return true;
}
public static Quaternion operator *(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion quaternion;
float x = quaternion1.mX;
float y = quaternion1.mY;
float z = quaternion1.mZ;
float w = quaternion1.mW;
float num4 = quaternion2.mX;
float num3 = quaternion2.mY;
float num2 = quaternion2.mZ;
float num = quaternion2.mW;
float num12 = (y * num2) - (z * num3);
float num11 = (z * num4) - (x * num2);
float num10 = (x * num3) - (y * num4);
float num9 = ((x * num4) + (y * num3)) + (z * num2);
quaternion.mX = ((x * num) + (num4 * w)) + num12;
quaternion.mY = ((y * num) + (num3 * w)) + num11;
quaternion.mZ = ((z * num) + (num2 * w)) + num10;
quaternion.mW = (w * num) - num9;
return quaternion;
}
public static Quaternion operator *(Quaternion quaternion1, float scaleFactor)
{
Quaternion quaternion;
quaternion.mX = quaternion1.mX * scaleFactor;
quaternion.mY = quaternion1.mY * scaleFactor;
quaternion.mZ = quaternion1.mZ * scaleFactor;
quaternion.mW = quaternion1.mW * scaleFactor;
return quaternion;
}
public static Quaternion operator -(Quaternion quaternion1, Quaternion quaternion2)
{
Quaternion quaternion;
quaternion.mX = quaternion1.mX - quaternion2.mX;
quaternion.mY = quaternion1.mY - quaternion2.mY;
quaternion.mZ = quaternion1.mZ - quaternion2.mZ;
quaternion.mW = quaternion1.mW - quaternion2.mW;
return quaternion;
}
public static Quaternion operator -(Quaternion quaternion)
{
Quaternion quaternion2;
quaternion2.mX = -quaternion.mX;
quaternion2.mY = -quaternion.mY;
quaternion2.mZ = -quaternion.mZ;
quaternion2.mW = -quaternion.mW;
return quaternion2;
}
public override void ToString(String outStr)
{
ThrowUnimplemented();
}
internal Matrix4 ToMatrix()
{
Matrix4 matrix = Matrix4.Identity;
ToMatrix(out matrix);
return matrix;
}
/*internal void ToMatrix(out Matrix4 matrix)
{
Quaternion.ToMatrix(this, out matrix);
}*/
public void ToMatrix(out Matrix4 matrix)
{
float fTx = mX + mX;
float fTy = mY + mY;
float fTz = mZ + mZ;
float fTwx = fTx * mW;
float fTwy = fTy * mW;
float fTwz = fTz * mW;
float fTxx = fTx * mX;
float fTxy = fTy * mX;
float fTxz = fTz * mX;
float fTyy = fTy * mY;
float fTyz = fTz * mY;
float fTzz = fTz * mZ;
matrix.m00 = 1.0f - (fTyy + fTzz);
matrix.m01 = fTxy - fTwz;
matrix.m02 = fTxz + fTwy;
matrix.m03 = 0;
matrix.m10 = fTxy + fTwz;
matrix.m11 = 1.0f - (fTxx + fTzz);
matrix.m12 = fTyz - fTwx;
matrix.m13 = 0;
matrix.m20 = fTxz - fTwy;
matrix.m21 = fTyz + fTwx;
matrix.m22 = 1.0f - (fTxx + fTyy);
matrix.m23 = 0;
matrix.m30 = 0;
matrix.m31 = 0;
matrix.m32 = 0;
matrix.m33 = 1.0f;
}
internal Vector3 XYZ
{
get
{
return Vector3(mX, mY, mZ);
}
set mut
{
mX = value.mX;
mY = value.mY;
mZ = value.mZ;
}
}
}
}

View file

@ -0,0 +1,197 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.gfx;
namespace Beefy.geom
{
public struct Rect
{
public float mX;
public float mY;
public float mWidth;
public float mHeight;
public float Left
{
get
{
return mX;
}
}
public float Top
{
get
{
return mY;
}
}
public float Right
{
get
{
return mX + mWidth;
}
}
public float Bottom
{
get
{
return mY + mHeight;
}
}
public float Width
{
get
{
return mWidth;
}
}
public float Height
{
get
{
return mHeight;
}
}
public this(float x = 0, float y = 0, float width = 0, float height = 0)
{
mX = x;
mY = y;
mWidth = width;
mHeight = height;
}
public void Set(float x = 0, float y = 0, float width = 0, float height = 0) mut
{
mX = x;
mY = y;
mWidth = width;
mHeight = height;
}
public bool Intersects(Rect rect)
{
return !((rect.mX + rect.mWidth <= mX) ||
(rect.mY + rect.mHeight <= mY) ||
(rect.mX >= mX + mWidth) ||
(rect.mY >= mY + mHeight));
}
public void SetIntersectionOf(Rect rect1, Rect rect2) mut
{
float x1 = Math.Max(rect1.mX, rect2.mX);
float x2 = Math.Min(rect1.mX + rect1.mWidth, rect2.mX + rect2.mWidth);
float y1 = Math.Max(rect1.mY, rect2.mY);
float y2 = Math.Min(rect1.mY + rect1.mHeight, rect2.mY + rect2.mHeight);
if (((x2 - x1) < 0) || ((y2 - y1) < 0))
{
mX = 0;
mY = 0;
mWidth = 0;
mHeight = 0;
}
else
{
mX = x1;
mY = y1;
mWidth = x2 - x1;
mHeight = y2 - y1;
}
}
public void SetIntersectionOf(Rect rect1, float x, float y, float width, float height) mut
{
float x1 = Math.Max(rect1.mX, x);
float x2 = Math.Min(rect1.mX + rect1.mWidth, x + width);
float y1 = Math.Max(rect1.mY, y);
float y2 = Math.Min(rect1.mY + rect1.mHeight, y + height);
if (((x2 - x1) < 0) || ((y2 - y1) < 0))
{
mX = 0;
mY = 0;
mWidth = 0;
mHeight = 0;
}
else
{
mX = x1;
mY = y1;
mWidth = x2 - x1;
mHeight = y2 - y1;
}
}
public Rect Intersection(Rect rect)
{
float x1 = Math.Max(mX, rect.mX);
float x2 = Math.Min(mX + mWidth, rect.mX + rect.mWidth);
float y1 = Math.Max(mY, rect.mY);
float y2 = Math.Min(mY + mHeight, rect.mY + rect.mHeight);
if (((x2 - x1) < 0) || ((y2 - y1) < 0))
return Rect(0, 0, 0, 0);
else
return Rect(x1, y1, x2 - x1, y2 - y1);
}
public Rect Union(Rect rect)
{
float x1 = Math.Min(mX, rect.mX);
float x2 = Math.Max(mX + mWidth, rect.mX + rect.mWidth);
float y1 = Math.Min(mY, rect.mY);
float y2 = Math.Max(mY + mHeight, rect.mY + rect.mHeight);
return Rect(x1, y1, x2 - x1, y2 - y1);
}
public bool Contains(float x, float y)
{
return ((x >= mX) && (x < mX + mWidth) &&
(y >= mY) && (y < mY + mHeight));
}
public bool Contains(Point pt)
{
return Contains(pt.x, pt.y);
}
public bool Contains(Rect rect)
{
return Contains(rect.mX, rect.mY) && Contains(rect.mX + rect.mWidth, rect.mY + rect.mHeight);
}
public void Offset(float x, float y) mut
{
mX += x;
mY += y;
}
public void Inflate(float x, float y) mut
{
mX -= x;
mWidth += x * 2;
mY -= y;
mHeight += y * 2;
}
public void Scale(float scaleX, float scaleY) mut
{
mX *= scaleX;
mY *= scaleY;
mWidth *= scaleX;
mHeight *= scaleY;
}
public void ScaleFrom(float scaleX, float scaleY, float centerX, float centerY) mut
{
Offset(-centerX, -centerY);
Scale(scaleX, scaleY);
Offset(centerX, centerY);
}
}
}

View file

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.geom
{
public struct Vector2
{
public float mX;
public float mY;
public float Length
{
get
{
return (float)Math.Sqrt(mX * mX + mY * mY);
}
}
public float LengthSquared
{
get
{
return mX * mX + mY * mY;
}
}
public this(float x, float y)
{
mX = x;
mY = y;
}
public static void DistanceSquared(Vector2 value1, Vector2 value2, out float result)
{
result = (value1.mX - value2.mX) * (value1.mX - value2.mX) +
(value1.mY - value2.mY) * (value1.mY - value2.mY);
}
public static float Distance(Vector2 vector1, Vector2 vector2)
{
float result;
DistanceSquared(vector1, vector2, out result);
return (float)Math.Sqrt(result);
}
public static Vector2 Add(Vector2 vec1, Vector2 vec2)
{
return Vector2(vec1.mX + vec2.mX, vec1.mY + vec2.mY);
}
public static Vector2 Subtract(Vector2 vec1, Vector2 vec2)
{
return Vector2(vec1.mX - vec2.mX, vec1.mY - vec2.mY);
}
public static float Dot(Vector2 vec1, Vector2 vec2)
{
return vec1.mX * vec2.mX + vec1.mY * vec2.mY;
}
public static Vector2 FromAngle(float angle, float length = 1.0f)
{
return Vector2((float)Math.Cos(angle) * length, (float)Math.Sin(angle) * length);
}
public static Vector2 operator +(Vector2 vec1, Vector2 vec2)
{
return Vector2(vec1.mX + vec2.mX, vec1.mY + vec2.mY);
}
public static Vector2 operator -(Vector2 vec1, Vector2 vec2)
{
return Vector2(vec1.mX - vec2.mX, vec1.mY - vec2.mY);
}
public static Vector2 operator *(Vector2 vec1, float factor)
{
return Vector2(vec1.mX * factor, vec1.mY * factor);
}
public static Vector2 operator /(Vector2 vec1, float factor)
{
return Vector2(vec1.mX / factor, vec1.mY / factor);
}
}
}

View file

@ -0,0 +1,247 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Beefy.gfx;
namespace Beefy.geom
{
public struct Vector3 : IHashable, IEquatable<Vector3>
{
[Reflect]
public float mX;
[Reflect]
public float mY;
[Reflect]
public float mZ;
private static Vector3 sZero = Vector3(0f, 0f, 0f);
private static Vector3 sOne = Vector3(1f, 1f, 1f);
private static Vector3 sUnitX = Vector3(1f, 0f, 0f);
private static Vector3 sUnitY = Vector3(0f, 1f, 0f);
private static Vector3 sUnitZ = Vector3(0f, 0f, 1f);
private static Vector3 sUp = Vector3(0f, 1f, 0f);
private static Vector3 sDown = Vector3(0f, -1f, 0f);
private static Vector3 sRight = Vector3(1f, 0f, 0f);
private static Vector3 sLeft = Vector3(-1f, 0f, 0f);
private static Vector3 sForward = Vector3(0f, 0f, -1f);
private static Vector3 sBackward = Vector3(0f, 0f, 1f);
public static Vector3 Zero
{
get { return sZero; }
}
public static Vector3 One
{
get { return sOne; }
}
public static Vector3 UnitX
{
get { return sUnitX; }
}
public static Vector3 UnitY
{
get { return sUnitY; }
}
public static Vector3 UnitZ
{
get { return sUnitZ; }
}
public static Vector3 Up
{
get { return sUp; }
}
public static Vector3 Down
{
get { return sDown; }
}
public static Vector3 Right
{
get { return sRight; }
}
public static Vector3 Left
{
get { return sLeft; }
}
public static Vector3 Forward
{
get { return sForward; }
}
public static Vector3 Backward
{
get { return sBackward; }
}
public float Length
{
get
{
return (float)Math.Sqrt(mX * mX + mY * mY + mZ * mZ);
}
}
public float LengthSquared
{
get
{
return mX * mX + mY * mY + mZ * mZ;
}
}
public this(float x, float y, float z)
{
mX = x;
mY = y;
mZ = z;
}
public bool Equals(Vector3 other)
{
return this == other;
}
public int GetHashCode()
{
return (int)(this.mX + this.mY + this.mZ);
}
/*public static Vector2D Add(Vector2D vec1, Vector2D vec2)
{
return new Vector2D(vec1.mX + vec2.mX, vec1.mY + vec2.mY);
}
public static Vector2D Subtract(Vector2D vec1, Vector2D vec2)
{
return new Vector2D(vec1.mX - vec2.mX, vec1.mY - vec2.mY);
}*/
public static Vector3 Normalize(Vector3 vector)
{
Vector3 newVec;
Normalize(vector, out newVec);
return vector;
}
public static void Normalize(Vector3 value, out Vector3 result)
{
float factor= Distance(value, sZero);
factor = 1f / factor;
result.mX = value.mX * factor;
result.mY = value.mY * factor;
result.mZ = value.mZ * factor;
}
public static float Dot(Vector3 vec1, Vector3 vec2)
{
return vec1.mX * vec2.mX + vec1.mY * vec2.mY + vec1.mZ * vec2.mZ;
}
public static Vector3 Cross(Vector3 vector1, Vector3 vector2)
{
return Vector3(vector1.mY * vector2.mZ - vector2.mY * vector1.mZ,
-(vector1.mX * vector2.mZ - vector2.mX * vector1.mZ),
vector1.mX * vector2.mY - vector2.mX * vector1.mY);
}
public static float DistanceSquared(Vector3 value1, Vector3 value2)
{
return (value1.mX - value2.mX) * (value1.mX - value2.mX) +
(value1.mY - value2.mY) * (value1.mY - value2.mY) +
(value1.mZ - value2.mZ) * (value1.mZ - value2.mZ);
}
public static float Distance(Vector3 vector1, Vector3 vector2)
{
float result = DistanceSquared(vector1, vector2);
return (float)Math.Sqrt(result);
}
/*public static Vector2D FromAngle(float angle, float length = 1.0f)
{
return new Vector2D((float)Math.Cos(angle) * length, (float)Math.Sin(angle) * length);
}*/
public static Vector3 Transform(Vector3 vec, Matrix4 matrix)
{
Vector3 result;
float fInvW = 1.0f / (matrix.m30 * vec.mX + matrix.m31 * vec.mY + matrix.m32 * vec.mZ + matrix.m33);
result.mX = (matrix.m00 * vec.mX + matrix.m01 * vec.mY + matrix.m02 * vec.mZ + matrix.m03) * fInvW;
result.mY = (matrix.m10 * vec.mX + matrix.m11 * vec.mY + matrix.m12 * vec.mZ + matrix.m13) * fInvW;
result.mZ = (matrix.m20 * vec.mX + matrix.m21 * vec.mY + matrix.m22 * vec.mZ + matrix.m23) * fInvW;
return result;
}
/*public static void Transform(Vector3[] sourceArray, ref Matrix4 matrix, Vector3[] destinationArray)
{
//Debug.Assert(destinationArray.Length >= sourceArray.Length, "The destination array is smaller than the source array.");
for (var i = 0; i < sourceArray.Length; i++)
{
var position = sourceArray[i];
destinationArray[i] =
new Vector3(
(position.mX * matrix.m11) + (position.mY * matrix.m21) + (position.mZ * matrix.m31) + matrix.m41,
(position.mX * matrix.m12) + (position.mY * matrix.m22) + (position.mZ * matrix.m32) + matrix.m42,
(position.mX * matrix.m13) + (position.mY * matrix.m23) + (position.mZ * matrix.m33) + matrix.m43);
}
}*/
public static Vector3 Transform(Vector3 vec, Quaternion quat)
{
Matrix4 matrix = quat.ToMatrix();
return Transform(vec, matrix);
}
public static Vector3 TransformNormal(Vector3 normal, Matrix4 matrix)
{
return Vector3((normal.mX * matrix.m11) + (normal.mY * matrix.m21) + (normal.mZ * matrix.m31),
(normal.mX * matrix.m12) + (normal.mY * matrix.m22) + (normal.mZ * matrix.m32),
(normal.mX * matrix.m13) + (normal.mY * matrix.m23) + (normal.mZ * matrix.m33));
}
public static bool operator ==(Vector3 value1, Vector3 value2)
{
return (value1.mX == value2.mX) &&
(value1.mY == value2.mY) &&
(value1.mZ == value2.mZ);
}
public static bool operator !=(Vector3 value1, Vector3 value2)
{
return !(value1 == value2);
}
public static Vector3 operator +(Vector3 vec1, Vector3 vec2)
{
return Vector3(vec1.mX + vec2.mX, vec1.mY + vec2.mY, vec1.mZ + vec2.mZ);
}
public static Vector3 operator -(Vector3 vec1, Vector3 vec2)
{
return Vector3(vec1.mX - vec2.mX, vec1.mY - vec2.mY, vec1.mZ - vec2.mZ);
}
public static Vector3 operator *(Vector3 vec, float scale)
{
return Vector3(vec.mX * scale, vec.mY * scale, vec.mZ * scale);
}
public override void ToString(String str)
{
str.AppendF("{0:0.0#}, {1:0.0#}, {2:0.0#}", mX, mY, mZ);
}
}
}

View file

@ -0,0 +1,158 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.gfx
{
public struct Color : uint32
{
public const Color White = 0xFFFFFFFF;
public const Color Black = 0xFF000000;
public const Color Red = 0xFFFF0000;
public const Color Green = 0xFF00FF00;
public const Color Blue = 0xFF0000FF;
public const Color Yellow = 0xFFFFFF00;
public static implicit operator uint32(Color color);
public static implicit operator Color(uint32 color);
public this(int32 r, int32 g, int32 b)
{
this = 0xFF000000 | (uint32)((r << 16) | (g << 8) | (b));
}
public this(int32 r, int32 g, int32 b, int32 a)
{
this = (uint32)((a << 24) | (r << 16) | (g << 8) | (b));
}
public static Color Get(float a)
{
return 0x00FFFFFF | (((uint32)(255.0f * a)) << 24);
}
public static Color Get(uint32 rgb, float a)
{
return (uint32)(((uint32)(a * 255) << 24) | (rgb & 0xffffff));
}
public static Color Get(int32 r, int32 g, int32 b)
{
return 0xFF000000 | (uint32)((r << 16) | (g << 8) | (b));
}
public static Color Get(int32 r, int32 g, int32 b, int32 a)
{
return (uint32)((a << 24) | (r << 16) | (g << 8) | (b));
}
public static float GetAlpha(uint32 color)
{
return ((float)(0xff & (color >> 24))) / 255.0f;
}
public static Color Mult(Color color, Color colorMult)
{
if (color == 0xFFFFFFFF)
return colorMult;
if (colorMult == 0xFFFFFFFF)
return color;
uint32 result =
(((((color >> 24) & 0xFF) * ((colorMult >> 24) & 0xFF)) / 255) << 24) |
(((((color >> 16) & 0xFF) * ((colorMult >> 16) & 0xFF)) / 255) << 16) |
(((((color >> 8) & 0xFF) * ((colorMult >> 8) & 0xFF)) / 255) << 8) |
(((color & 0xFF) * (colorMult & 0xFF)) / 255);
return result;
}
public static Color Lerp(Color color1, Color color2, float pct)
{
if (color1 == color2)
return color1;
uint32 a = (uint32)(pct * 256.0f);
uint32 oma = 256 - a;
uint32 aColor =
(((((color1 & 0x000000FF) * oma) + ((color2 & 0x000000FF) * a)) >> 8) & 0x000000FF) |
(((((color1 & 0x0000FF00) * oma) + ((color2 & 0x0000FF00) * a)) >> 8) & 0x0000FF00) |
(((((color1 & 0x00FF0000) * oma) + ((color2 & 0x00FF0000) * a)) >> 8) & 0x00FF0000) |
(((((color1 >> 24) & 0xFF) * oma) + (((color2 >> 24) & 0xFF) * a) & 0x0000FF00) << 16);
return aColor;
}
public static void ToHSV(uint32 color, out float h, out float s, out float v)
{
float r = ((color >> 16) & 0xFF) / 255.0f;
float g = ((color >> 8) & 0xFF) / 255.0f;
float b = ((color >> 0) & 0xFF) / 255.0f;
float min, max, delta;
min = Math.Min(r, Math.Min(g, b));
max = Math.Max(r, Math.Max(g, b));
v = max; // v
delta = max - min;
if (max != 0)
s = delta / max; // s
else
{
// r = g = b = 0 // s = 0, v is undefined
s = 0;
h = -1;
return;
}
if (r == max)
h = (g - b) / delta; // between yellow & magenta
else if (g == max)
h = 2 + (b - r) / delta; // between cyan & yellow
else
h = 4 + (r - g) / delta; // between magenta & cyan
h /= 6; // degrees
if (h < 0)
h += 1.0f;
}
public static Color FromHSV(float h, float s, float v, int32 a)
{
float r, g, b;
if (s == 0.0f)
{
r = g = b = v;
}
else
{
float useH = h * 6.0f;
int32 i = (int32)useH;
float f = useH - i;
if ((i & 1) == 0)
f = 1 - f;
float m = v * (1 - s);
float n = v * (1 - s*f);
switch(i)
{
case 0: fallthrough;
case 6: r = v; g = n; b = m; break;
case 1: r = n; g = v; b = m; break;
case 2: r = m; g = v; b = n; break;
case 3: r = m; g = n; b = v; break;
case 4: r = n; g = m; b = v; break;
case 5: r = v; g = m; b = n; break;
default: r = 0; g = 0; b = 0; break;
}
}
return Get((int32)(r * 255.0f), (int32)(g * 255.0f), (int32)(b * 255.0f), a);
}
public static Color FromHSV(float h, float s, float v)
{
return FromHSV(h, s, v, 0xFF);
}
public static uint32 ToNative(Color color)
{
return (color & 0xFF00FF00) | ((color & 0x00FF0000) >> 16) | ((color & 0x000000FF) << 16);
}
}
}

View file

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
namespace Beefy.gfx
{
public class ConstantDataDefinition
{
public enum DataType
{
Float,
Vector2,
Vector3,
Vector4,
Matrix,
VertexShaderUsage = 0x100,
PixelShaderUsage = 0x200
}
public int32 mDataSize;
public DataType[] mDataTypes ~ delete _;
public this(int32 dataSize, DataType[] dataTypes)
{
mDataSize = dataSize;
mDataTypes = dataTypes;
}
public this(Type type)
{
ThrowUnimplemented();
/*var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
int memberCount = fields.Length;
mDataTypes = new int[memberCount];
mDataSize = Marshal.SizeOf(type);
List<Type> primitives = new List<Type>();
int fieldIdx = 0;
foreach (var field in fields)
{
var memberAttribute = field.GetCustomAttribute<VertexMemberAttribute>();
primitives.Clear();
VertexDefinition.FindPrimitives(field.FieldType, primitives);
int floats = 0;
int shorts = 0;
int colors = 0;
foreach (var prim in primitives)
{
if (prim == typeof(float))
floats++;
else if (prim == typeof(ushort))
shorts++;
else if (prim == typeof(uint))
colors++;
}
DataType dataType = DataType.Single;
int usageType = 1;
if (floats != 0)
{
Debug.Assert(floats == primitives.Count);
if (floats == 16)
dataType = DataType.Matrix;
else
{
Debug.Assert(floats <= 4);
dataType = DataType.Single + floats - 1;
}
}
else if (shorts != 0)
{
/*if (shorts == 2)
dataType = DataType.Short2;
else if (shorts == 4)
dataType = DataType.Short4;
else*/
Debug.Fail("Invalid short count");
}
else if (colors != 0)
{
/*if (colors == 1)
vertexDefData.mFormat = VertexElementFormat.Color;
else*/
Debug.Fail("Invalid color count");
}
mDataTypes[fieldIdx++] = (int)dataType | (usageType << 8);
} */
}
}
}

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Beefy.gfx
{
public struct ConstantDataMemberAttribute : Attribute
{
public bool mVertexShaderWants;
public bool mPixelShaderWants;
public this(bool vertexShaderWants, bool pixelShaderWants)
{
mVertexShaderWants = vertexShaderWants;
mPixelShaderWants = pixelShaderWants;
}
}
}

View file

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Beefy.geom;
namespace Beefy.gfx
{
public struct DefaultVertex
{
[VertexMember(VertexElementUsage.Position2D)]
public Vector3 mPos;
[VertexMember(VertexElementUsage.TextureCoordinate)]
public TexCoords mTexCoords;
[VertexMember(VertexElementUsage.Color)]
public uint32 mColor;
public static VertexDefinition sVertexDefinition ~ delete _;
public static void Init()
{
sVertexDefinition = new VertexDefinition(typeof(DefaultVertex));
}
}
}

View file

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Beefy.widgets;
using Beefy;
#if STUDIO_CLIENT
using Beefy.ipc;
#endif
namespace Beefy.gfx
{
#if !STUDIO_CLIENT
public class DrawLayer
{
[StdCall, CLink]
static extern void* DrawLayer_Create(void* window);
[StdCall, CLink]
static extern void DrawLayer_Delete(void* drawLayer);
[StdCall, CLink]
static extern void DrawLayer_Clear(void* drawLayer);
[StdCall, CLink]
static extern void DrawLayer_Activate(void* drawLayer);
[StdCall, CLink]
static extern void DrawLayer_DrawToRenderTarget(void* drawLayer, void* texture);
public void* mNativeDrawLayer;
public this(BFWindow window)
{
mNativeDrawLayer = DrawLayer_Create((window != null) ? (window.mNativeWindow) : null);
}
public ~this()
{
DrawLayer_Delete(mNativeDrawLayer);
}
public void Activate()
{
DrawLayer_Activate(mNativeDrawLayer);
}
public void Clear()
{
DrawLayer_Clear(mNativeDrawLayer);
}
public void DrawToRenderTarget(Image texture)
{
DrawLayer_DrawToRenderTarget(mNativeDrawLayer, texture.mNativeTextureSegment);
}
}
#else
public class DrawLayer
{
IPCProxy<IStudioDrawLayer> mDrawLayer;
public DrawLayer(BFWindow window)
{
IPCObjectId drawLayerObjId = BFApp.sApp.mStudioHost.Proxy.CreateDrawLayer((window != null) ? window.mRemoteWindow.ObjId : IPCObjectId.Null);
mDrawLayer = IPCProxy<IStudioDrawLayer>.Create(drawLayerObjId);
}
public void Dispose()
{
}
public void Activate()
{
mDrawLayer.Proxy.Activate();
}
public void Clear()
{
}
public void DrawToRenderTarget(Image texture)
{
}
}
#endif
}

View file

@ -0,0 +1,881 @@
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Beefy.geom;
using Beefy.utils;
using System.Diagnostics;
using System.Threading;
namespace Beefy.gfx
{
public enum FontOverflowMode
{
Overflow,
Clip,
Truncate,
Wrap,
Ellipsis
}
public enum FontAlign
{
Left = -1,
Centered,
Right
}
public struct FontMetrics
{
public int32 mLineCount;
public float mMinX;
public float mMinY;
public float mMaxX;
public float mMaxY;
public float mMaxWidth;
}
public class Font
{
[StdCall, CLink]
static extern FTFont* FTFont_Load(char8* fileName, float pointSize);
[StdCall, CLink]
static extern void FTFont_Delete(FTFont* ftFont, bool cacheRetain);
[StdCall, CLink]
static extern void FTFont_ClearCache();
[StdCall, CLink]
static extern FTGlyph* FTFont_AllocGlyph(FTFont* ftFont, int32 char8Code, bool allowDefault);
[StdCall, CLink]
static extern int32 FTFont_GetKerning(FTFont* font, int32 char8CodeA, int32 char8CodeB);
static Dictionary<String, String> sFontNameMap ~ DeleteDictionyAndKeysAndItems!(_);
static Monitor sMonitor = new .() ~ delete _;
struct FTFont
{
public int32 mHeight;
public int32 mAscent;
public int32 mDescent;
public int32 mMaxAdvance;
}
struct FTGlyph
{
public void* mPage;
public void* mTextureSegment;
public int32 mX;
public int32 mY;
public int32 mWidth;
public int32 mHeight;
public int32 mXOffset;
public int32 mYOffset;
public int32 mXAdvance;
}
public class CharData
{
public Image mImageSegment ~ delete _;
public int32 mX;
public int32 mY;
public int32 mWidth;
public int32 mHeight;
public int32 mXOffset;
public int32 mYOffset;
public int32 mXAdvance;
public bool mIsCombiningMark;
}
public class Page
{
public Image mImage ~ delete _;
public bool mIsCorrectedImage = true;
}
public struct AltFont
{
public Font mFont;
public bool mOwned;
}
class MarkRefData
{
public float mTop;
public float mBottom;
}
enum MarkPosition
{
AboveC, // Center
AboveR, // Left edge of mark aligned on center of char8
AboveE, // Center of mark aligned on right edge of char8
BelowC,
BelowR,
OverC,
OverE,
TopR, // Center of edge aligned to top of char8
}
const int32 LOW_CHAR_COUNT = 128;
Dictionary<char32, CharData> mCharData;
CharData[] mLowCharData;
FTFont* mFTFont;
String mPath;
List<AltFont> mAlternates;
MarkRefData mMarkRefData ~ delete _;
float[] mLoKerningTable;
public this()
{
}
public ~this()
{
Dispose();
}
public static ~this()
{
FTFont_ClearCache();
}
static void BuildFontNameCache()
{
#if BF_PLATFORM_WINDOWS
using (sMonitor.Enter())
{
sFontNameMap = new .();
Windows.HKey hkey;
if (Windows.RegOpenKeyExA(Windows.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts", 0,
Windows.KEY_QUERY_VALUE | Windows.KEY_WOW64_32KEY | Windows.KEY_ENUMERATE_SUB_KEYS, out hkey) == Windows.S_OK)
{
defer Windows.RegCloseKey(hkey);
for (int32 i = 0; true; i++)
{
char16[256] fontNameArr;
uint32 nameLen = 255;
uint32 valType = 0;
char16[256] data;
uint32 dataLen = 256 * 2;
int32 result = Windows.RegEnumValueW(hkey, i, &fontNameArr, &nameLen, null, &valType, &data, &dataLen);
if (result == 0)
{
if (valType == 1)
{
String fontName = new String(&fontNameArr);
int parenPos = fontName.IndexOf(" (");
if (parenPos != -1)
fontName.RemoveToEnd(parenPos);
fontName.ToUpper();
String fontPath = new String(&data);
if ((!fontPath.EndsWith(".TTF", .OrdinalIgnoreCase)) || (!sFontNameMap.TryAdd(fontName, fontPath)))
{
delete fontName;
delete fontPath;
}
}
}
else
{
if (result == Windows.ERROR_MORE_DATA)
continue;
break;
}
}
}
}
#endif
}
public static void ClearFontNameCache()
{
using (sMonitor.Enter())
{
DeleteDictionyAndKeysAndItems!(sFontNameMap);
sFontNameMap = null;
}
}
public void Dispose(bool cacheRetain)
{
if (mFTFont != null)
{
FTFont_Delete(mFTFont, cacheRetain);
mFTFont = null;
}
if (mLowCharData != null)
{
for (var charData in mLowCharData)
delete charData;
DeleteAndNullify!(mLowCharData);
}
if (mCharData != null)
{
for (var charData in mCharData.Values)
delete charData;
DeleteAndNullify!(mCharData);
}
if (mAlternates != null)
{
for (var altFont in mAlternates)
if (altFont.mOwned)
delete altFont.mFont;
DeleteAndNullify!(mAlternates);
}
DeleteAndNullify!(mPath);
DeleteAndNullify!(mLoKerningTable);
}
public void Dispose()
{
Dispose(false);
}
public static void ClearCache()
{
FTFont_ClearCache();
}
public void AddAlternate(Font altFont)
{
AltFont altFontEntry;
altFontEntry.mFont = altFont;
altFontEntry.mOwned = false;
mAlternates.Add(altFontEntry);
}
public Result<void> AddAlternate(String path, float pointSize = -1)
{
Font altFont = Try!(LoadFromFile(path, pointSize));
AltFont altFontEntry;
altFontEntry.mFont = altFont;
altFontEntry.mOwned = true;
mAlternates.Add(altFontEntry);
return .Ok;
}
public bool GetVal(String outVal, List<String> cmds, String find)
{
for (String cmd in cmds)
{
if (cmd.StartsWith(find) && (cmd[find.Length] == '='))
{
outVal.Append(cmd, find.Length + 1);
return true;
}
}
return false;
}
public int32 GetValInt(List<String> cmds, String find)
{
String strVal = scope String();
if (!GetVal(strVal, cmds, find))
return 0;
return int32.Parse(strVal);
}
public void CalcKerning()
{
for (char8 c0 = ' '; c0 < '\x80'; c0++)
{
for (char8 c1 = ' '; c1 < '\x80'; c1++)
{
float kernVal = FTFont_GetKerning(mFTFont, (int32)c0, (int32)c1);
if (kernVal != 0)
{
if (mLoKerningTable == null)
mLoKerningTable = new float[128*128];
mLoKerningTable[(int32)c0 + ((int32)c1)*128] = kernVal;
}
}
}
}
public float GetKerning(char32 c0, char32 c1)
{
if (mLoKerningTable == null)
return 0;
if ((c0 < '\x80') && (c1 < '\x80'))
{
return mLoKerningTable[(int32)c0 + ((int32)c1)*128];
}
return FTFont_GetKerning(mFTFont, (int32)c0, (int32)c1);
}
void GetFontPath(StringView fontName, String path)
{
if (fontName.Contains('.'))
{
Path.GetAbsolutePath(fontName, BFApp.sApp.mInstallDir, path);
}
else
{
using (sMonitor.Enter())
{
if (sFontNameMap == null)
BuildFontNameCache();
#if BF_PLATFORM_WINDOWS
let lookupStr = scope String(fontName)..ToUpper();
String pathStr;
if (sFontNameMap.TryGetValue(lookupStr, out pathStr))
{
char8[256] windowsDir;
Windows.GetWindowsDirectoryA(&windowsDir, 256);
path.Append(&windowsDir);
path.Append(@"\Fonts\");
path.Append(pathStr);
}
#endif
}
}
}
internal bool Load(StringView fontName, float pointSize = -1)
{
Dispose();
mCharData = new Dictionary<char32, CharData>();
mLowCharData = new CharData[LOW_CHAR_COUNT];
mAlternates = new List<AltFont>();
float usePointSize = pointSize;
mPath = new String();
GetFontPath(fontName, mPath);
String fontPath = scope String(mPath);
if (pointSize == -1)
{
fontPath.Set(BFApp.sApp.mInstallDir);
fontPath.Append("fonts/SourceCodePro-Regular.ttf");
usePointSize = 9;
}
mFTFont = FTFont_Load(fontPath, usePointSize);
if (mFTFont == null)
return false;
CalcKerning();
return true;
}
public static Result<Font> LoadFromFile(String path, float pointSize = -1)
{
scope AutoBeefPerf("Font.LoadFromFile");
Font font = new Font();
if (!font.Load(path, pointSize))
return .Err; //TODO: Make proper error
return font;
}
public bool HasChar(char32 theChar)
{
return true;
/*if ((theChar >= (char8)0) && (theChar < (char8)LOW_CHAR_COUNT))
return mLowCharData[(int)theChar] != null;
return mCharData.ContainsKey(theChar);*/
}
public float GetWidth(StringView theString)
{
float curX = 0;
int len = theString.Length;
if (len == 0)
{
return 0;
}
char32 prevChar = (char8)0;
for (var c in theString.DecodedChars)
{
int idx = @c.NextIndex;
if (c == (char32)'\x01')
{
@c.NextIndex = idx + 4;
continue;
}
else if (c == (char32)'\x02')
{
continue;
}
CharData charData = GetCharData((char32)c);
if ((charData != null) && (!charData.mIsCombiningMark))
{
curX += charData.mXAdvance;
if (prevChar != (char8)0)
{
float kernAmount = GetKerning(prevChar, c);
curX += kernAmount;
}
}
prevChar = c;
if (idx >= len)
break;
}
return curX;
}
static MarkPosition[] sMarkPositionsLow = new MarkPosition[0x70]
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
/*0*/{.AboveC, .AboveC, .AboveC, .AboveC, /**/ .AboveC, .AboveC, .AboveC, .AboveC, /**/ .AboveC, .AboveC, .AboveC, .AboveC, /**/ .AboveC, .AboveC, .AboveC, .AboveC,
/*1*/ .AboveC, .AboveC, .AboveC, .AboveC, /**/ .AboveC, .AboveE, .AboveC, .AboveC, /**/ .BelowC, .BelowC, .AboveE, .TopR, /**/ .BelowC, .BelowC, .BelowC, .BelowC,
/*2*/ .BelowC, .BelowC, .BelowC, .BelowC, /**/ .BelowC, .BelowC, .BelowC, .BelowC, /**/ .BelowC, .BelowC, .BelowC, .BelowC, /**/ .BelowC, .BelowC, .BelowC, .BelowC,
/*3*/ .BelowC, .BelowC, .BelowC, .BelowC, /**/ .OverC , .OverC , .OverC , .OverC , /**/ .OverC , .BelowC, .BelowC, .BelowC, /**/ .AboveC, .AboveC, .AboveC, .AboveC,
/*4*/ .AboveC, .AboveC, .AboveC, .AboveC, /**/ .AboveC, .BelowC, .AboveC, .BelowC, /**/ .BelowC, .BelowC, .AboveC, .AboveC, /**/ .AboveC, .BelowC, .BelowC, .OverC,
/*5*/ .AboveC, .AboveC, .AboveC, .BelowC, /**/ .BelowC, .BelowC, .BelowC, .AboveC, /**/ .AboveE, .BelowC, .AboveC, .AboveC, /**/ .BelowR, .AboveR, .AboveR, .BelowR,
/*6*/ .AboveR, .AboveR, .BelowR, .AboveC, /**/ .AboveC, .AboveC, .AboveC, .AboveC, /**/ .AboveC, .AboveC, .AboveC, .AboveC, /**/ .AboveC, .AboveC, .AboveC, .AboveC,
} ~ delete _;
MarkPosition GetMarkPosition(char32 checkChar)
{
if ((checkChar >= '\u{0300}') && (checkChar <= '\u{036F}'))
{
return sMarkPositionsLow[(int)(checkChar - '\u{0300}')];
}
return .OverC;
}
CharData GetCharData(char32 checkChar)
{
CharData charData;
if ((checkChar >= (char8)0) && (checkChar < (char32)LOW_CHAR_COUNT))
charData = mLowCharData[(int)checkChar];
else
mCharData.TryGetValue(checkChar, out charData);
if (charData == null)
{
for (int fontIdx = -1; fontIdx < mAlternates.Count; fontIdx++)
{
FTFont* ftFont;
if (fontIdx == -1)
ftFont = mFTFont;
else
ftFont = mAlternates[fontIdx].mFont.mFTFont;
if (ftFont == null)
continue;
var ftGlyph = FTFont_AllocGlyph(ftFont, (int32)checkChar, fontIdx == mAlternates.Count - 1);
if (ftGlyph == null)
continue;
charData = new CharData();
charData.mX = ftGlyph.mX;
charData.mY = ftGlyph.mY;
charData.mWidth = ftGlyph.mWidth;
charData.mHeight = ftGlyph.mHeight;
charData.mXAdvance = ftGlyph.mXAdvance;
charData.mXOffset = ftGlyph.mXOffset;
charData.mYOffset = ftGlyph.mYOffset;
charData.mImageSegment = new Image();
charData.mImageSegment.mNativeTextureSegment = ftGlyph.mTextureSegment;
charData.mImageSegment.mX = ftGlyph.mX;
charData.mImageSegment.mY = ftGlyph.mY;
charData.mImageSegment.mWidth = ftGlyph.mWidth;
charData.mImageSegment.mHeight = ftGlyph.mHeight;
charData.mImageSegment.mSrcWidth = ftGlyph.mWidth;
charData.mImageSegment.mSrcHeight = ftGlyph.mHeight;
charData.mIsCombiningMark = ((checkChar >= '\u{0300}') && (checkChar <= '\u{036F}')) || ((checkChar >= '\u{1DC0}') && (checkChar <= '\u{1DFF}'));
if (charData.mIsCombiningMark)
charData.mXAdvance = 0;
if ((checkChar >= (char32)0) && (checkChar < (char32)LOW_CHAR_COUNT))
mLowCharData[(int)checkChar] = charData;
else
mCharData[checkChar] = charData;
return charData;
}
if (checkChar == (char32)'?')
return null;
return GetCharData((char32)'?');
}
return charData;
}
MarkRefData GetMarkRefData()
{
if (mMarkRefData == null)
{
mMarkRefData = new MarkRefData();
var charData = GetCharData('o');
mMarkRefData.mTop = charData.mYOffset;
mMarkRefData.mBottom = charData.mYOffset + charData.mHeight;
}
return mMarkRefData;
}
public float GetWidth(char32 theChar)
{
CharData charData = GetCharData(theChar);
return charData.mXAdvance;
}
public int GetCharCountToLength(StringView theString, float maxLength, bool* hitTabStop = null)
{
float curX = 0;
int startIdx = 0;
char32 prevChar = (char8)0;
for (var c in theString.DecodedChars)
{
int idx = @c.NextIndex;
if (c == (char32)'\x01')
{
@c.NextIndex = idx + 4;
//startIdx = idx;
continue;
}
else if (c == (char32)'\x02')
{
//startIdx = idx;
continue;
}
else if (c == (char32)'\t')
{
if (hitTabStop != null)
{
*hitTabStop = true;
return startIdx;
}
}
CharData charData = GetCharData(c);
curX += charData.mXAdvance;
if (prevChar != (char32)0)
{
float kernAmount = GetKerning(prevChar, c);
curX += kernAmount;
}
if (curX > maxLength)
return startIdx;
prevChar = c;
startIdx = idx;
}
return (int32)theString.Length;
}
public float GetLineSpacing()
{
if (mFTFont == null)
return 0;
return mFTFont.mHeight;
}
public float GetHeight()
{
if (mFTFont == null)
return 0;
return mFTFont.mHeight;
}
public float GetAscent()
{
if (mFTFont == null)
return 0;
return mFTFont.mAscent;
}
public float GetDescent()
{
if (mFTFont == null)
return 0;
return mFTFont.mDescent;
}
public float GetWrapHeight(StringView theString, float width)
{
return Draw(null, theString, 0, 0, -1, width, FontOverflowMode.Wrap);
}
public static void StrEncodeColor(uint32 color, String outString)
{
uint32 colorVal = (color >> 1) & 0x7F7F7F7F;
outString.Append('\x01');
outString.Append((char8*)&colorVal, 4);
}
public static void StrEncodePopColor(String outString)
{
outString.Append('\x02');
}
public static char8[5] EncodeColor(uint32 color)
{
char8[5] val;
val[0] = '\x01';
*((uint32*)&val[1]) = (color >> 1) & 0x7F7F7F7F;
return val;
}
public static char8 EncodePopColor()
{
return '\x02';
}
public void Draw(Graphics g, StringView theString, FontMetrics* fontMetrics = null)
{
if (mFTFont == null)
return;
float curX = 0;
float curY = 0;
Matrix newMatrix = Matrix();
bool hasClipRect = g.mClipRect.HasValue;
Rect clipRect = g.mClipRect.GetValueOrDefault();
uint32 color = g.mColor;
g.PushTextRenderState();
#unwarn
float markScale = mFTFont.mHeight / 8.0f;
float markTopOfs = 0;
float markBotOfs = 0;
CharData lastCharData = null;
float lastCharX = 0;
char32 prevChar = (char32)0;
for (var c in theString.DecodedChars)
{
int idx = @c.NextIndex;
if (c == (char32)'\x01') // Set new color
{
if (idx <= theString.Length - 4)
{
uint32 newColor = *(uint32*)(theString.Ptr + idx) << 1;
color = Color.Mult(newColor, g.mColor);
@c.NextIndex = idx + 4;
continue;
}
}
else if (c == (char32)'\x02') // Restore color
{
color = g.mColor;
continue;
}
CharData charData = GetCharData(c);
float drawX = curX + charData.mXOffset;
float drawY = curY + charData.mYOffset;
if ((charData.mIsCombiningMark) && (lastCharData != null))
{
var markRefData = GetMarkRefData();
var markPos = GetMarkPosition(c);
if (markPos == .TopR)
{
drawX = lastCharX + lastCharData.mXOffset + lastCharData.mWidth - charData.mWidth / 2;
drawY = curY + lastCharData.mYOffset - charData.mHeight / 2;
}
else if ((markPos == .AboveE) || (markPos == .OverE))
{
drawX = lastCharX + lastCharData.mXOffset + lastCharData.mWidth - charData.mWidth / 2;
}
else
{
drawX = lastCharX + lastCharData.mXOffset + (lastCharData.mWidth / 2);
if ((markPos == .AboveC) || (markPos == .BelowC) || (markPos == .OverC))
drawX -= charData.mWidth / 2;
}
if ((markPos == .AboveC) || (markPos == .AboveR))
{
drawY += lastCharData.mYOffset - markRefData.mTop - markTopOfs;
markTopOfs += charData.mHeight;
}
else if ((markPos == .BelowC) || (markPos == .BelowR))
{
drawY += (lastCharData.mYOffset + lastCharData.mHeight) - markRefData.mBottom + markBotOfs;
markBotOfs += charData.mHeight;
}
}
else
{
lastCharX = curX;
markTopOfs = 0;
markBotOfs = 0;
if (prevChar != (char8)0)
{
float kernAmount = GetKerning(prevChar, c);
curX += kernAmount;
drawX += kernAmount;
}
lastCharData = charData;
}
newMatrix.SetMultiplied(drawX, drawY, ref g.mMatrix);
bool isFullyClipped = false;
if (hasClipRect)
{
if (newMatrix.tx < clipRect.mX -charData.mImageSegment.mWidth)
{
isFullyClipped = true;
}
else if (newMatrix.tx > clipRect.mX + clipRect.mWidth)
{
isFullyClipped = true;
if ((newMatrix.a > 0) && (fontMetrics == null)) // Forward? If so, all future char8s will clip
break;
}
}
if (!isFullyClipped)
charData.mImageSegment.Draw(newMatrix, g.ZDepth, color);
curX += charData.mXAdvance;
prevChar = c;
}
g.PopRenderState();
}
public float Draw(Graphics g, StringView theString, float x, float y, int32 justification = -1, float width = 0, FontOverflowMode stringEndMode = FontOverflowMode.Overflow, FontMetrics* fontMetrics = null)
{
float drawHeight = 0;
float useX = x;
float useY = y;
StringView workingStr = theString;
String tempStr = null;
void PopulateTempStr()
{
if (tempStr.Length != workingStr.Length)
{
tempStr.Clear();
tempStr.Append(workingStr);
}
}
while (true)
{
int32 crPos = (int32)workingStr.IndexOf('\n');
if (crPos == -1)
break;
float sectionHeight = Draw(g, StringView(workingStr, 0, crPos), useX, useY, justification, width, stringEndMode, fontMetrics);
drawHeight += sectionHeight;
useY += sectionHeight;
workingStr = .(workingStr, crPos + 1, workingStr.Length - (crPos + 1));
}
if ((justification != -1) || (stringEndMode != FontOverflowMode.Overflow))
{
float aWidth;
while (true)
{
aWidth = GetWidth(workingStr);
if (aWidth <= width)
break;
if (stringEndMode == FontOverflowMode.Ellipsis)
{
float ellipsisLen = GetWidth("...");
if (width < ellipsisLen)
return 0; // Don't draw at all if we don't even have enough space for the ellipsis
int strLen = GetCharCountToLength(workingStr, width - ellipsisLen);
tempStr = scope:: String(Math.Min(strLen, 128));
tempStr.Append(theString, 0, strLen);
tempStr.Append("...");
workingStr = tempStr;
aWidth = GetWidth(workingStr);
break;
}
else if (stringEndMode == FontOverflowMode.Truncate)
{
int strLen = GetCharCountToLength(workingStr, width);
tempStr = scope:: String(Math.Min(strLen, 128));
tempStr.Append(theString, 0, strLen);
workingStr = tempStr;
aWidth = GetWidth(workingStr);
break;
}
else if (stringEndMode == FontOverflowMode.Wrap)
{
int32 maxChars = (int32)GetCharCountToLength(workingStr, width);
int32 checkIdx = maxChars;
if (checkIdx < workingStr.Length)
{
while ((checkIdx > 0) && (!workingStr[checkIdx].IsWhiteSpace))
checkIdx--;
}
if (checkIdx == 0)
{
// Can't break on whitespace
checkIdx = maxChars;
}
if (checkIdx > 0)
{
if (fontMetrics != null)
fontMetrics.mLineCount++;
drawHeight += Draw(g, StringView(workingStr, 0, checkIdx), useX, useY, justification, width, stringEndMode, fontMetrics);
useY += GetLineSpacing();
workingStr.Adjust(checkIdx);
}
}
else
break;
}
if (fontMetrics != null)
fontMetrics.mMaxWidth = Math.Max(fontMetrics.mMaxWidth, aWidth);
if (justification == 0)
useX += (width - aWidth) / 2;
else if (justification == 1)
useX += width - aWidth;
}
if (g != null)
{
using (g.PushTranslate(useX, useY))
Draw(g, workingStr, fontMetrics);
}
else
{
if (fontMetrics != null)
fontMetrics.mMaxWidth = Math.Max(fontMetrics.mMaxWidth, GetWidth(workingStr));
}
drawHeight += GetLineSpacing();
if (fontMetrics != null)
fontMetrics.mLineCount++;
return drawHeight;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.gfx
{
public interface IDrawable
{
void Draw(Matrix matrix, float z, uint32 color);
}
}

View file

@ -0,0 +1,283 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Beefy.utils;
using System.Diagnostics;
#if STUDIO_CLIENT
using Beefy.ipc;
#endif
namespace Beefy.gfx
{
#if !STUDIO_CLIENT
public class Image : IDrawable
{
public Image mSrcTexture;
public int32 mSrcX;
public int32 mSrcY;
public int32 mSrcWidth;
public int32 mSrcHeight;
public float mWidth;
public float mHeight;
public float mX;
public float mY;
public void* mNativeTextureSegment;
public PixelSnapping mPixelSnapping = PixelSnapping.Auto;
[StdCall, CLink]
public static extern void Gfx_DrawTextureSegment(void* textureSegment, float a, float b, float c, float d, float tx, float ty, float z, uint32 color, int32 pixelSnapping);
[StdCall, CLink]
static extern void* Gfx_LoadTexture(char8* fileName, int32 additive);
[StdCall, CLink]
static extern void* Gfx_CreateDynTexture(int32 width, int32 height);
[StdCall, CLink]
static extern void* Gfx_CreateRenderTarget(int32 width, int32 height, int32 destAlpha);
[StdCall, CLink]
static extern void* Gfx_ModifyTextureSegment(void* destSegment, void* srcTextureSegment, int32 srcX, int32 srcY, int32 srcWidth, int32 srcHeight);
[StdCall, CLink]
static extern void* Gfx_CreateTextureSegment(void* textureSegment, int32 srcX, int32 srcY, int32 srcWidth, int32 srcHeight);
[StdCall, CLink]
public static extern void Gfx_SetDrawSize(void* textureSegment, int32 width, int32 height);
[StdCall, CLink]
static extern void Gfx_Texture_SetBits(void* textureSegment, int32 destX, int32 destY, int32 destWidth, int32 destHeight, int32 srcPitch, uint32* bits);
[StdCall, CLink]
static extern void Gfx_Texture_Delete(void* textureSegment);
[StdCall, CLink]
static extern int32 Gfx_Texture_GetWidth(void* textureSegment);
[StdCall, CLink]
static extern int32 Gfx_Texture_GetHeight(void* textureSegment);
internal this()
{
}
public ~this()
{
Gfx_Texture_Delete(mNativeTextureSegment);
}
public void Draw(Matrix matrix, float z, uint32 color)
{
Image.Gfx_DrawTextureSegment(mNativeTextureSegment, matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty, z,
color, (int32)mPixelSnapping);
}
public static Image CreateRenderTarget(int32 width, int32 height, bool destAlpha = false)
{
void* aNativeTextureSegment = Gfx_CreateRenderTarget(width, height, destAlpha ? 1 : 0);
if (aNativeTextureSegment == null)
return null;
return CreateFromNativeTextureSegment(aNativeTextureSegment);
}
public static Image LoadFromFile(String fileName, bool additive = false)
{
scope AutoBeefPerf("Image.LoadFromFile");
void* aNativeTextureSegment = Gfx_LoadTexture(fileName, additive ? 1 : 0);
if (aNativeTextureSegment == null)
return null;
return CreateFromNativeTextureSegment(aNativeTextureSegment);
}
public static Image CreateDynamic(int width, int height)
{
void* nativeTextureSegment = Gfx_CreateDynTexture((.)width, (.)height);
if (nativeTextureSegment == null)
return null;
return CreateFromNativeTextureSegment(nativeTextureSegment);
}
public static Image CreateFromNativeTextureSegment(void* nativeTextureSegment)
{
Image texture = new Image();
texture.mNativeTextureSegment = nativeTextureSegment;
texture.mSrcWidth = Gfx_Texture_GetWidth(nativeTextureSegment);
texture.mSrcHeight = Gfx_Texture_GetHeight(nativeTextureSegment);
texture.mWidth = texture.mSrcWidth;
texture.mHeight = texture.mSrcHeight;
return texture;
}
public Image CreateImageSegment(int srcX, int srcY, int srcWidth, int srcHeight)
{
Image textureSegment = new Image();
textureSegment.mSrcTexture = this;
textureSegment.mSrcX = (int32)srcX;
textureSegment.mSrcY = (int32)srcY;
textureSegment.mSrcWidth = (int32)srcWidth;
textureSegment.mSrcHeight = (int32)srcHeight;
textureSegment.mWidth = Math.Abs(srcWidth);
textureSegment.mHeight = Math.Abs(srcHeight);
textureSegment.mNativeTextureSegment = Gfx_CreateTextureSegment(mNativeTextureSegment, (int32)srcX, (int32)srcY, (int32)srcWidth, (int32)srcHeight);
return textureSegment;
}
public void CreateImageSegment(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight)
{
if (mNativeTextureSegment != null)
{
Gfx_Texture_Delete(mNativeTextureSegment);
}
mSrcTexture = srcImage;
mSrcX = (int32)srcX;
mSrcY = (int32)srcY;
mSrcWidth = (int32)srcWidth;
mSrcHeight = (int32)srcHeight;
mWidth = Math.Abs(srcWidth);
mHeight = Math.Abs(srcHeight);
mNativeTextureSegment = Gfx_CreateTextureSegment(srcImage.mNativeTextureSegment, (int32)srcX, (int32)srcY, (int32)srcWidth, (int32)srcHeight);
}
public void SetDrawSize(int width, int height)
{
mWidth = width;
mHeight = height;
Gfx_SetDrawSize(mNativeTextureSegment, (int32)width, (int32)height);
}
public void Scale(float scale)
{
mWidth = (int32)(mSrcWidth * scale);
mHeight = (int32)(mSrcHeight * scale);
Gfx_SetDrawSize(mNativeTextureSegment, (int32)mWidth, (int32)mHeight);
}
public void Modify(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight)
{
mSrcTexture = srcImage;
mSrcX = (int32)srcX;
mSrcY = (int32)srcY;
mSrcWidth = (int32)srcWidth;
mSrcHeight = (int32)srcHeight;
mWidth = Math.Abs(srcWidth);
mHeight = Math.Abs(srcHeight);
Gfx_ModifyTextureSegment(mNativeTextureSegment, srcImage.mNativeTextureSegment, (int32)srcX, (int32)srcY, (int32)srcWidth, (int32)srcHeight);
}
public void SetBits(int destX, int destY, int destWidth, int destHeight, int srcPitch, uint32* bits)
{
Gfx_Texture_SetBits(mNativeTextureSegment, (.)destX, (.)destY, (.)destWidth, (.)destHeight, (.)srcPitch, bits);
}
public void CreateImageCels(Image[,] celImages)
{
int32 rows = (int32)celImages.GetLength(0);
int32 cols = (int32)celImages.GetLength(1);
int32 celW = mSrcWidth / cols;
int32 celH = mSrcHeight / rows;
Debug.Assert(celW * cols == mSrcWidth);
Debug.Assert(celH * rows == mSrcHeight);
for (int32 row = 0; row < rows; row++)
{
for (int32 col = 0; col < cols; col++)
{
celImages[row, col] = CreateImageSegment(col * celW, row * celH, celW, celH);
}
}
}
}
#else
public class Image : IDrawable
{
public Image mSrcTexture;
public int mSrcX;
public int mSrcY;
public int mSrcWidth;
public int mSrcHeight;
public float mWidth;
public float mHeight;
public float mX;
public float mY;
public IPCProxy<IStudioImage> mStudioImage;
public Image[] mCelImages;
PixelSnapping mPixelSnapping = PixelSnapping.Auto;
public void Draw(Matrix matrix, float z, uint color, int cel)
{
//Image.Gfx_DrawTextureSegment(mNativeTextureSegment, matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty,
//color, mAdditive ? 1 : 0, (int)mPixelSnapping);
mStudioImage.Proxy.DrawTextureSegment(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty, z,
color, (int)mPixelSnapping);
}
public static Image LoadFromFile(string fileName, bool additive = false)
{
//void* aNativeTextureSegment = Gfx_LoadTexture(fileName);
IPCObjectId aNativeTextureSegmentId = BFApp.sApp.mStudioHost.Proxy.LoadImage(fileName, additive);
if (aNativeTextureSegmentId.IsNull())
return null;
return CreateFromNativeTextureSegment(aNativeTextureSegmentId);
}
public static Image CreateFromNativeTextureSegment(IPCObjectId nativeTextureSegmentId)
{
Image texture = new Image();
texture.mStudioImage = IPCProxy<IStudioImage>.Create(nativeTextureSegmentId);
texture.mSrcWidth = texture.mStudioImage.Proxy.GetSrcWidth();
texture.mSrcHeight = texture.mStudioImage.Proxy.GetSrcHeight();
texture.mWidth = texture.mSrcWidth;
texture.mHeight = texture.mSrcHeight;
return texture;
}
internal Image()
{
}
public Image CreateImageSegment(int srcX, int srcY, int srcWidth, int srcHeight)
{
Image aTextureSegment = new Image();
aTextureSegment.mStudioImage = IPCProxy<IStudioImage>.Create(mStudioImage.Proxy.CreateImageSegment(srcX, srcY, srcWidth, srcHeight));
aTextureSegment.mSrcTexture = this;
aTextureSegment.mSrcX = srcX;
aTextureSegment.mSrcY = srcY;
aTextureSegment.mSrcWidth = srcWidth;
aTextureSegment.mSrcHeight = srcHeight;
aTextureSegment.mWidth = Math.Abs(srcWidth);
aTextureSegment.mHeight = Math.Abs(srcHeight);
return aTextureSegment;
}
public void CreateImageCels(int cols, int rows)
{
int celW = mSrcWidth / cols;
int celH = mSrcHeight / rows;
Debug.Assert(celW * cols == mSrcWidth);
Debug.Assert(celH * rows == mSrcHeight);
mCelImages = new Image[cols * rows];
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
mCelImages[col + row * cols] = CreateImageSegment(col * celW, row * celH, celW, celH);
}
}
}
}
#endif
}

View file

@ -0,0 +1,205 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.geom;
namespace Beefy.gfx
{
public struct Matrix
{
public float a;
public float b;
public float c;
public float d;
public float tx;
public float ty;
public this()
{
a = 1;
b = 0;
c = 0;
d = 1;
tx = 0;
ty = 0;
}
public this(float _a, float _b, float _c, float _d, float _tx, float _ty)
{
a = _a;
b = _b;
c = _c;
d = _d;
tx = _tx;
ty = _ty;
}
public static Matrix IdentityMatrix = Matrix(1, 0, 0, 1, 0, 0);
public Matrix Duplicate()
{
return Matrix(a, b, c, d, tx, ty);
}
public void Identity() mut
{
tx = 0;
ty = 0;
a = 1;
b = 0;
c = 0;
d = 1;
}
public void Translate(float x, float y) mut
{
tx += x;
ty += y;
}
public void Scale(float scaleX, float scaleY) mut
{
a *= scaleX;
b *= scaleY;
c *= scaleX;
d *= scaleY;
tx *= scaleX;
ty *= scaleY;
}
public void Rotate(float angle) mut
{
float _a = a;
float _b = b;
float _c = c;
float _d = d;
float _tx = tx;
float _ty = ty;
float sin = (float)Math.Sin(angle);
float cos = (float)Math.Cos(angle);
a = _a * cos - _b * sin;
b = _a * sin + _b * cos;
c = _c * cos - _d * sin;
d = _c * sin + _d * cos;
tx = _tx * cos - _ty * sin;
ty = _tx * sin + _ty * cos;
}
public void Multiply(Matrix mat2) mut
{
float _a = a;
float _b = b;
float _c = c;
float _d = d;
float _tx = tx;
float _ty = ty;
a = _a * mat2.a + _b * mat2.c;
b = _a * mat2.b + _b * mat2.d;
c = _c * mat2.a + _d * mat2.c;
d = _c * mat2.b + _d * mat2.d;
tx = _tx * mat2.a + _ty * mat2.c + mat2.tx;
ty = _tx * mat2.b + _ty * mat2.d + mat2.ty;
}
public void Set(Matrix mat2) mut
{
a = mat2.a;
b = mat2.b;
c = mat2.c;
d = mat2.d;
tx = mat2.tx;
ty = mat2.ty;
}
public void SetMultiplied(float x, float y, ref Matrix mat2) mut
{
a = mat2.a;
b = mat2.b;
c = mat2.c;
d = mat2.d;
tx = x * mat2.a + y * mat2.c + mat2.tx;
ty = x * mat2.b + y * mat2.d + mat2.ty;
}
public void SetMultiplied(float x, float y, float width, float height, ref Matrix mat2) mut
{
a = mat2.a * width;
b = mat2.b * width;
c = mat2.c * height;
d = mat2.d * height;
tx = x * mat2.a + y * mat2.c + mat2.tx;
ty = x * mat2.b + y * mat2.d + mat2.ty;
}
public void SetMultiplied(Matrix mat1, Matrix mat2) mut
{
float a1 = mat1.a;
float b1 = mat1.b;
float c1 = mat1.c;
float d1 = mat1.d;
float tx1 = mat1.tx;
float ty1 = mat1.ty;
float a2 = mat2.a;
float b2 = mat2.b;
float c2 = mat2.c;
float d2 = mat2.d;
float tx2 = mat2.tx;
float ty2 = mat2.ty;
a = a1 * a2 + b1 * c2;
b = a1 * b2 + b1 * d2;
c = c1 * a2 + d1 * c2;
d = c1 * b2 + d1 * d2;
tx = tx1 * a2 + ty1 * c2 + tx2;
ty = tx1 * b2 + ty1 * d2 + ty2;
}
public Point Multiply(Point point)
{
return Point(tx + a * point.x + c * point.y, ty + b * point.x + d * point.y);
}
public void Invert() mut
{
float _a = a;
float _b = b;
float _c = c;
float _d = d;
float _tx = tx;
float _ty = ty;
float den = a * d - b * c;
a = _d / den;
b = -_b / den;
c = -_c / den;
d = _a / den;
tx = (_c * _ty - _d * _tx) / den;
ty = -(_a * _ty - _b * _tx) / den;
}
public static Matrix Lerp(Matrix mat1, Matrix mat2, float pct)
{
float omp = 1.0f - pct;
Matrix matrix = Matrix();
matrix.a = (mat1.a * omp) + (mat2.a * pct);
matrix.b = (mat1.b * omp) + (mat2.b * pct);
matrix.c = (mat1.c * omp) + (mat2.c * pct);
matrix.d = (mat1.d * omp) + (mat2.d * pct);
matrix.tx = (mat1.tx * omp) + (mat2.tx * pct);
matrix.ty = (mat1.ty * omp) + (mat2.ty * pct);
return matrix;
}
}
}

View file

@ -0,0 +1,391 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Beefy;
using Beefy.utils;
using Beefy.geom;
#if STUDIO_CLIENT
using Beefy.ipc;
#endif
namespace Beefy.gfx
{
public class ModelDef
{
public struct JointTranslation
{
public Quaternion mQuat;
public Vector3 mScale;
public Vector3 mTrans;
}
//[StructLayout(LayoutKind.Sequential)]
public struct VertexDef
{
[VertexMember(VertexElementUsage.Position3D)]
public Vector3 mPosition;
[VertexMember(VertexElementUsage.Color)]
public uint32 mColor;
[VertexMember(VertexElementUsage.TextureCoordinate)]
public TexCoords mTexCoords;
[VertexMember(VertexElementUsage.Normal)]
public Vector3 mNormal;
[VertexMember(VertexElementUsage.TextureCoordinate, 1)]
public TexCoords mBumpTexCoords;
[VertexMember(VertexElementUsage.Tangent)]
public Vector3 mTangent;
public static VertexDefinition sVertexDefinition ~ delete _;
public static void Init()
{
sVertexDefinition = new VertexDefinition(typeof(VertexDef));
}
}
}
#if !STUDIO_CLIENT
extension ModelDef
{
public class Animation
{
public void* mNativeModelDefAnimation;
public int32 mFrameCount;
public String mName;
public int32 mAnimIdx;
[StdCall, CLink]
extern static void ModelDefAnimation_GetJointTranslation(void* nativeAnimation, int32 jointIdx, float frame, out JointTranslation jointTranslation);
[StdCall, CLink]
extern static int32 ModelDefAnimation_GetFrameCount(void* nativeAnimation);
[StdCall, CLink]
extern static char8* ModelDefAnimation_GetName(void* nativeAnimation);
[StdCall, CLink]
extern static void ModelDefAnimation_Clip(void* nativeAnimation, int32 startFrame, int32 numFrames);
internal this(void* nativeModelDefAnimation)
{
mNativeModelDefAnimation = nativeModelDefAnimation;
mFrameCount = ModelDefAnimation_GetFrameCount(mNativeModelDefAnimation);
mName = new String(ModelDefAnimation_GetName(mNativeModelDefAnimation));
}
public void GetJointTranslation(int32 jointIdx, float frame, out JointTranslation jointTranslation)
{
ModelDefAnimation_GetJointTranslation(mNativeModelDefAnimation, jointIdx, frame, out jointTranslation);
}
public void Clip(int32 startFrame, int32 numFrames)
{
ModelDefAnimation_Clip(mNativeModelDefAnimation, startFrame, numFrames);
mFrameCount = ModelDefAnimation_GetFrameCount(mNativeModelDefAnimation);
}
}
public void* mNativeModelDef;
public float mFrameRate;
public int32 mJointCount;
public Animation[] mAnims;
public Dictionary<String, Animation> mAnimMap = new Dictionary<String, Animation>();
[StdCall, CLink]
extern static void* Res_OpenFBX(String fileName, void* nativeVertexDef);
[StdCall, CLink]
extern static void* ModelDef_CreateModelInstance(void* nativeModel);
[StdCall, CLink]
extern static float ModelDef_GetFrameRate(void* nativeModel);
[StdCall, CLink]
extern static int32 ModelDef_GetJointCount(void* nativeModel);
[StdCall, CLink]
extern static int32 ModelDef_GetAnimCount(void* nativeModel);
[StdCall, CLink]
extern static void* ModelDef_GetAnimation(void* nativeModel, int32 animIdx);
this(void* nativeModelDef)
{
mNativeModelDef = nativeModelDef;
mFrameRate = ModelDef_GetFrameRate(mNativeModelDef);
mJointCount = ModelDef_GetJointCount(mNativeModelDef);
int32 animCount = ModelDef_GetAnimCount(mNativeModelDef);
mAnims = new Animation[animCount];
for (int32 animIdx = 0; animIdx < animCount; animIdx++)
{
var anim = new Animation(ModelDef_GetAnimation(mNativeModelDef, animIdx));
anim.mAnimIdx = animIdx;
mAnims[animIdx] = anim;
mAnimMap[anim.mName] = anim;
}
}
public static ModelDef LoadModel(String fileName)
{
void* nativeModelDef = Res_OpenFBX(fileName, VertexDef.sVertexDefinition.mNativeVertexDefinition);
if (nativeModelDef == null)
return null;
return new ModelDef(nativeModelDef);
}
public ModelInstance CreateInstance()
{
void* nativeModelInstance = ModelDef_CreateModelInstance(mNativeModelDef);
if (nativeModelInstance == null)
return null;
var modelInstance = new ModelInstance(nativeModelInstance, this);
return modelInstance;
}
public Animation GetAnimation(String name)
{
return mAnimMap[name];
}
}
public class ModelInstance : RenderCmd
{
[StdCall, CLink]
extern static void ModelInstance_SetJointTranslation(void* nativeModelInstance, int32 jointIdx, ref ModelDef.JointTranslation jointTranslation);
[StdCall, CLink]
extern static void ModelInstance_SetMeshVisibility(void* nativeModelInstance, int32 jointIdx, int32 visibility);
public ModelDef mModelDef;
public ModelDef.Animation mAnim;
public float mFrame;
public float mAnimSpeed = 1.0f;
public bool mLoop;
internal this(void* nativeModelInstance, ModelDef modelDef)
{
mNativeRenderCmd = nativeModelInstance;
mModelDef = modelDef;
}
public void RehupAnimState()
{
for (int32 jointIdx = 0; jointIdx < mModelDef.mJointCount; jointIdx++)
{
ModelDef.JointTranslation jointTranslation;
mAnim.GetJointTranslation(jointIdx, mFrame, out jointTranslation);
SetJointTranslation(jointIdx, ref jointTranslation);
}
}
public void Update()
{
if (mAnim == null)
return;
mFrame += mModelDef.mFrameRate * BFApp.sApp.UpdateDelta * mAnimSpeed;
/*if ((mFrame >= 35.0f) || (mFrame < 1.0f))
mFrame = 34.0f;*/
if (mAnim.mFrameCount > 1)
{
float endFrameNum = mAnim.mFrameCount - 1.0f;
while (mFrame >= endFrameNum)
{
if (mLoop)
mFrame -= endFrameNum;
else
mFrame = endFrameNum - 0.00001f;
}
while (mFrame < 0)
mFrame += endFrameNum;
}
RehupAnimState();
}
public void Play(ModelDef.Animation anim, bool loop = false)
{
mLoop = loop;
mAnim = anim;
mFrame = 0;
RehupAnimState();
}
public void Play(String name, bool loop = false)
{
Play(mModelDef.GetAnimation(name), loop);
}
public void Play(bool loop = false)
{
Play(mModelDef.mAnims[0], loop);
}
public void SetJointTranslation(int32 jointIdx, ref ModelDef.JointTranslation jointTranslation)
{
ModelInstance_SetJointTranslation(mNativeRenderCmd, jointIdx, ref jointTranslation);
}
public void SetMeshVisibility(int32 meshIdx, bool visible)
{
ModelInstance_SetMeshVisibility(mNativeRenderCmd, meshIdx, visible ? 1 : 0);
}
}
#else
extension ModelDef
{
public class Animation
{
public void* mNativeModelDefAnimation;
public int mFrameCount;
public string mName;
public int mAnimIdx;
public IPCProxy<IStudioModelDefAnimation> mStudioModelDefAnimation;
internal Animation(IPCProxy<IStudioModelDefAnimation> studioModelDefAnimation)
{
mStudioModelDefAnimation = studioModelDefAnimation;
mFrameCount = mStudioModelDefAnimation.Proxy.GetFrameCount();
mName = mStudioModelDefAnimation.Proxy.GetName();
}
public void Clip(int startFrame, int numFrames)
{
//ModelDefAnimation_Clip(mNativeModelDefAnimation, startFrame, numFrames);
//mFrameCount = ModelDefAnimation_GetFrameCount(mNativeModelDefAnimation);
mStudioModelDefAnimation.Proxy.Clip(startFrame, numFrames);
mFrameCount = mStudioModelDefAnimation.Proxy.GetFrameCount();
}
}
public IPCProxy<IStudioModelDef> mStudioModelDef;
public float mFrameRate;
public int mJointCount;
public Animation[] mAnims;
public Dictionary<string, Animation> mAnimMap = new Dictionary<string, Animation>();
ModelDef(IPCProxy<IStudioModelDef> studioModelDef)
{
mStudioModelDef = studioModelDef;
mFrameRate = mStudioModelDef.Proxy.GetFrameRate();// ModelDef_GetFrameRate(mNativeModelDef);
mJointCount = mStudioModelDef.Proxy.GetJointCount();
int animCount = mStudioModelDef.Proxy.GetAnimCount();
mAnims = new Animation[animCount];
for (int animIdx = 0; animIdx < animCount; animIdx++)
{
var objId = mStudioModelDef.Proxy.GetAnimation(animIdx);
var anim = new Animation(IPCProxy<IStudioModelDefAnimation>.Create(objId));
anim.mAnimIdx = animIdx;
mAnims[animIdx] = anim;
mAnimMap[anim.mName] = anim;
}
}
public static ModelDef LoadModel(string fileName)
{
var objId = BFApp.StudioHostProxy.Res_OpenFBX(fileName, VertexDef.sVertexDefinition.mStudioVertexDefinition);
IPCProxy<IStudioModelDef> studioModelDef = IPCProxy<IStudioModelDef>.Create(objId);
if (studioModelDef == null)
return null;
return new ModelDef(studioModelDef);
}
public ModelInstance CreateInstance()
{
var objId = mStudioModelDef.Proxy.CreateModelInstance();
IPCProxy<IStudioModelInstance> studioModelInstance = IPCProxy<IStudioModelInstance>.Create(objId);
if (studioModelInstance == null)
return null;
var modelInstance = new ModelInstance(studioModelInstance, this);
return modelInstance;
}
public Animation GetAnimation(string name)
{
return mAnimMap[name];
}
}
public class ModelInstance : RenderCmd
{
public ModelDef mModelDef;
public ModelDef.Animation mAnim;
public float mFrame;
public float mAnimSpeed = 1.0f;
public bool mLoop;
public IPCProxy<IStudioModelInstance> mStudioModelInstance;
internal ModelInstance(IPCProxy<IStudioModelInstance> studioModelInstance, ModelDef modelDef)
{
mStudioModelInstance = studioModelInstance;
var objId = studioModelInstance.Proxy.GetAsRenderCmd();
mStudioRenderCmd = IPCProxy<IStudioRenderCmd>.Create(objId);
mModelDef = modelDef;
}
void RehupAnimState()
{
mStudioModelInstance.Proxy.RehupAnimState(mAnim.mAnimIdx, mFrame);
}
public void Update()
{
if (mAnim == null)
return;
mFrame += mModelDef.mFrameRate * BFApp.sApp.UpdateDelta * mAnimSpeed;
/*if ((mFrame >= 35.0f) || (mFrame < 1.0f))
mFrame = 34.0f;*/
if (mAnim.mFrameCount > 1)
{
float endFrameNum = mAnim.mFrameCount - 1.0f;
while (mFrame >= endFrameNum)
{
if (mLoop)
mFrame -= endFrameNum;
else
mFrame = endFrameNum - 0.00001f;
}
while (mFrame < 0)
mFrame += endFrameNum;
}
RehupAnimState();
}
public void Play(ModelDef.Animation anim, bool loop = false)
{
mLoop = loop;
mAnim = anim;
mFrame = 0;
RehupAnimState();
}
public void Play(string name, bool loop = false)
{
Play(mModelDef.GetAnimation(name), loop);
}
public void Play(bool loop = false)
{
Play(mModelDef.mAnims[0], loop);
}
public void SetMeshVisibility(int meshIdx, bool visible)
{
mStudioModelInstance.Proxy.SetMeshVisibility(meshIdx, visible);
}
}
#endif
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.gfx
{
public enum PixelSnapping
{
Never,
Always,
Auto,
Default
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
#if STUDIO_CLIENT
using Beefy.ipc;
#endif
namespace Beefy.gfx
{
#if !STUDIO_CLIENT
public class RenderCmd
{
public void* mNativeRenderCmd;
}
#else
public class RenderCmd
{
public IPCProxy<IStudioRenderCmd> mStudioRenderCmd;
}
#endif
}

View file

@ -0,0 +1,175 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Beefy;
using Beefy.geom;
namespace Beefy.gfx
{
public enum DepthFunc
{
Never,
Less,
LessEqual,
Equal,
Greater,
NotEqual,
GreaterEqual,
Always
}
#if !STUDIO_CLIENT
public class RenderState
{
[StdCall, CLink]
static extern void* Gfx_CreateRenderState(void* srcNativeRenderState);
[StdCall, CLink]
static extern void RenderState_Delete(void* renderState);
[StdCall, CLink]
static extern void RenderState_SetClip(void* renderState, float x, float y, float width, float height);
[StdCall, CLink]
static extern void RenderState_DisableClip(void* renderState);
[StdCall, CLink]
static extern void RenderState_SetShader(void* nativeRenderState, void* nativeShader);
[StdCall, CLink]
static extern void RenderState_SetDepthFunc(void* nativeRenderState, int32 depthFunc);
[StdCall, CLink]
static extern void RenderState_SetDepthWrite(void* nativeRenderState, int32 depthWrite);
public void* mNativeRenderState;
public bool mIsFromDefaultRenderState;
internal this()
{
}
internal ~this()
{
RenderState_Delete(mNativeRenderState);
}
public static RenderState Create(RenderState srcRenderState = null)
{
void* nativeRenderState = Gfx_CreateRenderState((srcRenderState != null) ? srcRenderState.mNativeRenderState : null);
if (nativeRenderState == null)
return null;
RenderState renderState = new RenderState();
renderState.mNativeRenderState = nativeRenderState;
return renderState;
}
public Shader Shader
{
set
{
RenderState_SetShader(mNativeRenderState, value.mNativeShader);
}
}
public DepthFunc DepthFunc
{
set
{
RenderState_SetDepthFunc(mNativeRenderState, (int32)value);
}
}
public bool DepthWrite
{
set
{
RenderState_SetDepthWrite(mNativeRenderState, value ? 1 : 0);
}
}
public Rect? ClipRect
{
set
{
if (value.HasValue)
{
Rect rect = value.Value;
RenderState_SetClip(mNativeRenderState, rect.mX, rect.mY, rect.mWidth, rect.mHeight);
}
else
RenderState_DisableClip(mNativeRenderState);
}
}
}
#else
public class RenderState
{
public IPCProxy<IStudioRenderState> mStudioRenderState;
public bool mIsFromDefaultRenderState;
internal RenderState()
{
}
public static RenderState Create(RenderState srcRenderState = null)
{
/*if (nativeRenderState == IntPtr.Zero)
return null;*/
RenderState renderState = new RenderState();
var renderStateRef = new IPCStudioObjectRef<IStudioRenderState>();
if (srcRenderState != null)
renderStateRef = srcRenderState.mStudioRenderState;
var objId = BFApp.sApp.mStudioHost.Proxy.CreateRenderState(renderStateRef);
renderState.mStudioRenderState = IPCProxy<IStudioRenderState>.Create(objId);
return renderState;
}
public Shader Shader
{
set
{
mStudioRenderState.Proxy.SetShader(value.mStudioShader);
}
}
public DepthFunc DepthFunc
{
set
{
mStudioRenderState.Proxy.SetDepthFunc((int)value); ;
}
}
public bool DepthWrite
{
set
{
mStudioRenderState.Proxy.SetDepthWrite(value);
}
}
public Rect? ClipRect
{
set
{
if (value.HasValue)
{
Rect rect = value.Value;
mStudioRenderState.Proxy.SetClipRect(rect.mX, rect.mY, rect.mWidth, rect.mHeight);
}
else
{
mStudioRenderState.Proxy.DisableClipRect();
}
}
}
}
#endif
}

View file

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Beefy.gfx
{
public class ShaderParam
{
public void* mNativeShaderParam;
internal this(void* shaderParam)
{
}
}
#if !STUDIO_CLIENT
public class Shader
{
public void* mNativeShader;
public Dictionary<String, ShaderParam> mShaderParamMap;
[StdCall, CLink]
static extern void* Gfx_LoadShader(char8* fileName, void* vertexDefinition);
[StdCall, CLink]
static extern void* Gfx_Shader_Delete(void* shader);
[StdCall, CLink]
static extern void* Gfx_GetShaderParam(void* shader, String paramName);
public static Shader CreateFromFile(String fileName, VertexDefinition vertexDefinition)
{
void* aNativeShader = Gfx_LoadShader(fileName, vertexDefinition.mNativeVertexDefinition);
if (aNativeShader == null)
return null;
Shader aShader = new Shader(aNativeShader);
return aShader;
}
internal this(void* nativeShader)
{
mNativeShader = nativeShader;
}
public ~this()
{
Gfx_Shader_Delete(mNativeShader);
}
ShaderParam GetParam(String paramName)
{
ShaderParam aShaderParam = null;
if (!mShaderParamMap.TryGetValue(paramName, out aShaderParam))
{
void* nativeShaderParam = Gfx_GetShaderParam(mNativeShader, paramName);
if (nativeShaderParam != null)
aShaderParam = new ShaderParam(nativeShaderParam);
mShaderParamMap[paramName] = aShaderParam;
}
return aShaderParam;
}
}
#else
public class Shader : IStudioShader
{
public IPCProxy<IStudioShader> mStudioShader;
public static Shader CreateFromFile(string fileName, VertexDefinition vertexDefinition)
{
Shader shader = new Shader();
IPCObjectId objId = BFApp.StudioHostProxy.CreateShaderFromFile(fileName, vertexDefinition.mStudioVertexDefinition);
shader.mStudioShader = IPCProxy<IStudioShader>.Create(objId);
return shader;
}
internal Shader()
{
}
}
#endif
}

View file

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Beefy.gfx
{
public struct TexCoords
{
[Reflect]
public float mU;
[Reflect]
public float mV;
public this(float u, float v)
{
mU = u;
mV = v;
}
}
}

View file

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace Beefy.gfx
{
//[StructLayout(LayoutKind.Sequential)]
public struct Vertex3D
{
public float mX;
public float mY;
public float mZ;
public float mU;
public float mV;
public uint32 mColor;
public this(float x, float y, float z, float u, float v, uint32 color)
{
mX = x;
mY = y;
mZ = z;
mU = u;
mV = v;
mColor = color;
}
}
}

View file

@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
namespace Beefy.gfx
{
public class VertexDefinition
{
enum VertexElementFormat
{
Float,
Vector2,
Vector3,
Vector4,
Color,
Byte4,
Short2,
Short4,
NormalizedShort2,
NormalizedShort4,
HalfVector2,
HalfVector4
}
[CRepr]
struct VertexDefData
{
public VertexElementUsage mUsage;
public int32 mUsageIndex;
public VertexElementFormat mFormat;
}
#if !STUDIO_CLIENT
[StdCall, CLink]
static extern void* Gfx_CreateVertexDefinition(VertexDefData* elementData, int32 numElements);
[StdCall, CLink]
static extern void Gfx_VertexDefinition_Delete(void* nativeVertexDefinition);
public void* mNativeVertexDefinition;
#else
public IPCProxy<IStudioVertexDefinition> mStudioVertexDefinition;
#endif
public int32 mVertexSize;
public int32 mPosition2DOffset = -1;
public static void FindPrimitives(Type type, List<Type> primitives)
{
if ((type.IsPrimitive) /*|| (field.FieldType.IsArray)*/)
{
primitives.Add(type);
return;
}
var typeInst = type as TypeInstance;
if (typeInst == null)
return;
for (var field in typeInst.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
FindPrimitives(field.FieldType, primitives);
}
}
#if !STUDIO_CLIENT
public static VertexDefinition CreateFromData(void* elementData, int32 numElements, int32 vertexSize)
{
var vertexDefinition = new VertexDefinition();
vertexDefinition.mNativeVertexDefinition = Gfx_CreateVertexDefinition((VertexDefData*)elementData, numElements);
vertexDefinition.mVertexSize = vertexSize;
return vertexDefinition;
}
#endif
internal this()
{
}
public ~this()
{
Gfx_VertexDefinition_Delete(mNativeVertexDefinition);
}
public this(Type type)
{
var typeInst = type as TypeInstance;
var vertexDefDataArray = scope VertexDefData[typeInst.FieldCount];
mVertexSize = typeInst.InstanceSize;
List<Type> primitives = scope List<Type>(3);
int32 fieldIdx = 0;
for (var field in typeInst.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
var memberAttribute = field.GetCustomAttribute<VertexMemberAttribute>().Get();
var vertexDefData = VertexDefData();
vertexDefData.mUsage = memberAttribute.mElementUsage;
vertexDefData.mUsageIndex = memberAttribute.mUsageIndex;
primitives.Clear();
FindPrimitives(field.FieldType, primitives);
int32 floats = 0;
int32 shorts = 0;
int32 colors = 0;
for (var prim in primitives)
{
if (prim == typeof(float))
floats++;
else if (prim == typeof(uint16))
shorts++;
else if (prim == typeof(uint32))
colors++;
}
if (memberAttribute.mElementUsage == VertexElementUsage.Position2D)
mPosition2DOffset = field.MemberOffset;
if (floats != 0)
{
Debug.Assert(floats == primitives.Count);
Debug.Assert(floats <= 4);
vertexDefData.mFormat = VertexElementFormat.Float + floats - 1;
}
else if (shorts != 0)
{
if (shorts == 2)
vertexDefData.mFormat = VertexElementFormat.Short2;
else if (shorts == 4)
vertexDefData.mFormat = VertexElementFormat.Short4;
else
Runtime.FatalError("Invalid short count");
}
else if (colors != 0)
{
if (colors == 1)
vertexDefData.mFormat = VertexElementFormat.Color;
else
Runtime.FatalError("Invalid color count");
}
vertexDefDataArray[fieldIdx++] = vertexDefData;
}
#if !STUDIO_CLIENT
mNativeVertexDefinition = Gfx_CreateVertexDefinition(vertexDefDataArray.CArray(), fieldIdx);
#else
fixed (VertexDefData* vertexDefData = vertexDefDataArray)
{
IPCObjectId objId = BFApp.sApp.mStudioHost.Proxy.CreateVertexDefinition(Marshal.SizeOf(typeof(VertexDefData)) * vertexDefDataArray.Length, vertexDefData, vertexDefDataArray.Length, mVertexSize);
mStudioVertexDefinition = IPCProxy<IStudioVertexDefinition>.Create(objId);
}
#endif
}
}
}

View file

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Beefy.gfx
{
public enum VertexElementUsage
{
Position2D,
Position3D,
Color,
TextureCoordinate,
Normal,
Binormal,
Tangent,
BlendIndices,
BlendWeight,
Depth,
Fog,
PointSize,
Sample,
TessellateFactor
}
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Beefy.gfx
{
public class VertexLayout
{
}
}

View file

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Beefy.gfx
{
[AttributeUsage(.Field, .ReflectAttribute, ReflectUser=.All)]
public struct VertexMemberAttribute : Attribute
{
public VertexElementUsage mElementUsage;
public int32 mUsageIndex;
public this(VertexElementUsage elementUsage, int32 usageIndex = 0)
{
mElementUsage = elementUsage;
mUsageIndex = usageIndex;
}
}
}

View file

@ -0,0 +1,206 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Beefy.gfx;
namespace Beefy.res
{
#if !STUDIO_CLIENT
public class PSDLayer
{
[StdCall, CLink]
extern static void Res_PSDLayer_GetSize(void* layerInfo, out int32 x, out int32 y, out int32 width, out int32 height);
[StdCall, CLink]
extern static int32 Res_PSDLayer_GetLayerId(void* layerInfo);
[StdCall, CLink]
extern static char8* Res_PSDLayer_GetName(void* layerInfo);
[StdCall, CLink]
extern static int32 Res_PSDLayer_IsVisible(void* layerInfo);
public void* mNativeLayerInfo;
public int32 mIdx;
public this(void* nativeLayerInfo, int32 idx)
{
mNativeLayerInfo = nativeLayerInfo;
mIdx = idx;
}
public void GetName(String str)
{
str.Append(Res_PSDLayer_GetName(mNativeLayerInfo));
}
public int32 GetLayerId()
{
return Res_PSDLayer_GetLayerId(mNativeLayerInfo);
}
public void GetSize(out int32 x, out int32 y, out int32 width, out int32 height)
{
Res_PSDLayer_GetSize(mNativeLayerInfo, out x, out y, out width, out height);
}
public bool IsVisible()
{
return Res_PSDLayer_IsVisible(mNativeLayerInfo) != 0;
}
}
public class PSDReader
{
[StdCall, CLink]
extern static void* Res_OpenPSD(String fileName);
[StdCall, CLink]
extern static void Res_DeletePSDReader(void* pSDReader);
[StdCall, CLink]
extern static int32 Res_PSD_GetLayerCount(void* pSDReader);
[StdCall, CLink]
extern static void* Res_PSD_GetLayerTexture(void* pSDReader, int32 layerIdx, out int32 xOfs, out int32 yOfs);
[StdCall, CLink]
extern static void* Res_PSD_GetMergedLayerTexture(void* pSDReader, void* layerIndices, int32 count, out int32 xOfs, out int32 yOfs);
[StdCall, CLink]
extern static void* Res_PSD_GetLayerInfo(void* pSDReader, int32 layerIdx);
void* mNativePSDReader;
protected this()
{
}
public int32 GetLayerCount()
{
return Res_PSD_GetLayerCount(mNativePSDReader);
}
public PSDLayer GetLayer(int32 layerIdx)
{
return new PSDLayer(Res_PSD_GetLayerInfo(mNativePSDReader, layerIdx), layerIdx);
}
public static PSDReader OpenFile(String fileName)
{
void* nativePSDReader = Res_OpenPSD(fileName);
if (nativePSDReader == null)
return null;
PSDReader aPSDReader = new PSDReader();
aPSDReader.mNativePSDReader = nativePSDReader;
return aPSDReader;
}
public Image LoadLayerImage(int32 layerIdx)
{
int32 aXOfs = 0;
int32 aYOfs = 0;
void* texture = Res_PSD_GetLayerTexture(mNativePSDReader, layerIdx, out aXOfs, out aYOfs);
if (texture == null)
return null;
Image image = Image.CreateFromNativeTextureSegment(texture);
image.mX = aXOfs;
image.mY = aYOfs;
return image;
}
public Image LoadMergedLayerImage(int32 [] layerIndices)
{
int32 aXOfs = 0;
int32 aYOfs = 0;
void* texture = Res_PSD_GetMergedLayerTexture(mNativePSDReader, layerIndices.CArray(), (int32)layerIndices.Count, out aXOfs, out aYOfs);
if (texture == null)
return null;
Image image = Image.CreateFromNativeTextureSegment(texture);
image.mX = aXOfs;
image.mY = aYOfs;
return image;
}
public void Dipose()
{
if (mNativePSDReader != null)
{
Res_DeletePSDReader(mNativePSDReader);
mNativePSDReader = null;
}
}
}
#else
public class PSDLayer
{
public int mIdx;
public PSDLayer(int nativeLayerInfo, int idx)
{
//mNativeLayerInfo = nativeLayerInfo;
mIdx = idx;
}
public string GetName()
{
return null;
}
public int GetLayerId()
{
return 0;
}
public void GetSize(out int x, out int y, out int width, out int height)
{
x = 0;
y = 0;
width = 0;
height = 0;
return;
}
public bool IsVisible()
{
return false;
}
}
public class PSDReader
{
protected PSDReader()
{
}
public int GetLayerCount()
{
return 0;
}
public PSDLayer GetLayer(int layerIdx)
{
return null;
}
public static PSDReader OpenFile(string fileName)
{
return null;
}
public Image LoadLayerImage(int layerIdx)
{
return null;
}
public Image LoadMergedLayerImage(int [] layerIndices)
{
return null;
}
public void Dipose()
{
//TODO: Dispose
}
}
#endif
}

View file

@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Beefy.utils;
using Beefy.gfx;
using System.Runtime.InteropServices;
namespace Beefy.res
{
public class ResInfo
{
public String mName ~ delete _;
public String mFilePath ~ delete _;
public Guid mResId;
public Object mLoadedObject;
}
public class ResImageInfo : ResInfo
{
}
public class ResGroup
{
public List<ResInfo> mResInfoList = new List<ResInfo>() ~ DeleteContainerAndItems!(_);
}
public class ResourceManager
{
/*[StdCall, CLink]
static extern void Wwise_Shutdown();*/
public Dictionary<String, ResGroup> mResGroupMap = new Dictionary<String, ResGroup>() ~ delete _;
public Dictionary<Guid, ResInfo> mIdToResInfoMap = new Dictionary<Guid, ResInfo>() ~ delete _;
public ~this()
{
//Wwise_Shutdown();
}
public void ParseConfigData(StructuredData data)
{
ThrowUnimplemented();
/*int fileResVer = data.GetInt("ResVer");
using (data.Open("Groups"))
{
for (int groupIdx = 0; groupIdx < data.Count; groupIdx++)
{
using (data.Open(groupIdx))
{
ResGroup resGroup = new ResGroup();
mResGroupMap[data.GetString("Name")] = resGroup;
using (data.Open("Resources"))
{
for (int resIdx = 0; resIdx < data.Count; resIdx++)
{
using (data.Open(resIdx))
{
ResInfo resInfo = null;
string aType = data.GetString("Type");
if (aType == "Image")
{
resInfo = new ResImageInfo();
}
resInfo.mName = data.GetString("Name");
resInfo.mResId = Guid.Parse(data.GetString("Id"));
resInfo.mFilePath = data.GetString("Path");
resGroup.mResInfoList.Add(resInfo);
}
}
}
}
}
}
Type appType = BFApp.sApp.GetType();
Type resourcesType = appType.Assembly.GetType(appType.Namespace + ".Res");
if (resourcesType == null)
return;
Type soundBanksTypes = resourcesType.GetNestedType("SoundBanks");
if (soundBanksTypes != null)
{
using (data.Open("SoundBanks"))
{
for (int soundBanksIdx = 0; soundBanksIdx < data.Count; soundBanksIdx++)
{
string name = data.Keys[soundBanksIdx];
uint wwiseId = data.GetUInt(soundBanksIdx);
SoundBank soundBank = new SoundBank();
soundBank.mName = name;
soundBank.mWwiseSoundId = wwiseId;
FieldInfo fieldInfo = soundBanksTypes.GetField(name);
fieldInfo.SetValue(null, soundBank);
}
}
}
Type soundEventsTypes = resourcesType.GetNestedType("SoundEvents");
if (soundEventsTypes != null)
{
using (data.Open("SoundEvents"))
{
for (int soundBanksIdx = 0; soundBanksIdx < data.Count; soundBanksIdx++)
{
string name = data.Keys[soundBanksIdx];
uint wwiseId = data.GetUInt(soundBanksIdx);
SoundEvent soundRes = new SoundEvent();
soundRes.mWwiseEventId = wwiseId;
FieldInfo fieldInfo = soundEventsTypes.GetField(name);
fieldInfo.SetValue(null, soundRes);
}
}
}
Type soundParametersTypes = resourcesType.GetNestedType("SoundParameters");
if (soundParametersTypes != null)
{
using (data.Open("SoundParameters"))
{
for (int soundBanksIdx = 0; soundBanksIdx < data.Count; soundBanksIdx++)
{
string name = data.Keys[soundBanksIdx];
uint wwiseId = data.GetUInt(soundBanksIdx);
SoundParameter soundParameter = new SoundParameter();
soundParameter.mWwiseParamId = wwiseId;
FieldInfo fieldInfo = soundParametersTypes.GetField(name);
fieldInfo.SetValue(null, soundParameter);
}
}
}*/
}
public bool LoadResGroup(String groupName)
{
ThrowUnimplemented();
/*Type appType = BFApp.sApp.GetType();
Type resourcesType = appType.Assembly.GetType(appType.Namespace + ".Res");
Type imagesType = resourcesType.GetNestedType("Images");
ResGroup resGroup = mResGroupMap[groupName];
foreach (ResInfo resInfo in resGroup.mResInfoList)
{
if (resInfo is ResImageInfo)
{
string fileName = resInfo.mFilePath;
if (!fileName.Contains(':'))
fileName = BFApp.sApp.mInstallDir + resInfo.mFilePath;
Image image = Image.LoadFromFile(fileName, false);
FieldInfo fieldInfo = imagesType.GetField(resInfo.mName);
fieldInfo.SetValue(null, image);
}
}
return true;*/
}
public Object GetResourceById(Guid id, bool allowLoad = false)
{
ThrowUnimplemented();
/*ResInfo resInfo = mIdToResInfoMap[id];
if ((resInfo.mLoadedObject == null) && (allowLoad))
{
if (resInfo is ResImageInfo)
resInfo.mLoadedObject = Image.LoadFromFile(resInfo.mFilePath, false);
}
return resInfo.mLoadedObject;*/
}
}
}

View file

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Beefy;
namespace Beefy.res
{
/*public class SoundBank
{
[StdCall, CLink]
static extern void Wwise_LoadBankByName(String name);
public String mName;
public uint32 mWwiseSoundId;
public void Load()
{
Wwise_LoadBankByName(mName);
}
}*/
}

View file

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Beefy;
namespace Beefy.res
{
/*public class SoundEvent
{
[StdCall, CLink]
static extern void Wwise_SendEvent(uint32 eventId, void* objectId);
public uint32 mWwiseEventId;
public void Post(SoundGameObject soundGameObject = null)
{
if (soundGameObject == null)
Wwise_SendEvent(mWwiseEventId, null);
else if (soundGameObject == null)
Wwise_SendEvent(mWwiseEventId, soundGameObject.mWwiseObject);
}
}*/
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.res
{
public class SoundGameObject
{
public void* mWwiseObject;
}
}

View file

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Beefy;
namespace Beefy.res
{
/*public class SoundParameter
{
[StdCall, CLink]
static extern int32 Wwise_SetRTPCValue(uint32 paramId, float value, void* soundGameObject);
public uint32 mWwiseParamId;
public bool Set(float value, SoundGameObject soundGameObject = null)
{
return Wwise_SetRTPCValue(mWwiseParamId, value, (soundGameObject == null) ? null : soundGameObject.mWwiseObject) != 0;
}
}*/
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.sys
{
public class SysBitmap
{
public void* mNativeBFBitmap;
}
}

View file

@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
using Beefy;
using System.Runtime.InteropServices;
namespace Beefy.sys
{
public class SysMenu : IMenu
{
public String mText ~ delete _;
public String mHotKey ~ delete _;
public SysBitmap mBitmap;
public bool mEnabled;
public int32 mCheckState;
public bool mRadioCheck;
public SysMenu mParent;
public BFWindow mWindow;
public void* mNativeBFMenu;
public Event<MenuItemSelectedHandler> mOnMenuItemSelected ~ _.Dispose();
public Event<MenuItemUpdateHandler> mOnMenuItemUpdate ~ _.Dispose();
public List<SysMenu> mChildren ~ DeleteContainerAndItems!(_);
internal this()
{
}
public int ChildCount
{
get
{
return (mChildren != null) ? mChildren.Count : 0;
}
}
public virtual SysMenu AddMenuItem(String text, String hotKey = null, MenuItemSelectedHandler menuItemSelectedHandler = null, MenuItemUpdateHandler menuItemUpdateHandler = null,
SysBitmap bitmap = null, bool enabled = true, int32 checkState = -1, bool radioCheck = false)
{
if (mChildren == null)
mChildren = new List<SysMenu>();
SysMenu sysMenu = new SysMenu();
if (text != null)
sysMenu.mText = new String(text);
if (hotKey != null)
sysMenu.mHotKey = new String(hotKey);
sysMenu.mBitmap = bitmap;
sysMenu.mEnabled = enabled;
sysMenu.mCheckState = checkState;
sysMenu.mRadioCheck = radioCheck;
if (menuItemSelectedHandler != null)
sysMenu.mOnMenuItemSelected.Add(menuItemSelectedHandler);
if (menuItemUpdateHandler != null)
sysMenu.mOnMenuItemUpdate.Add(menuItemUpdateHandler);
sysMenu.mNativeBFMenu = mWindow.AddMenuItem(mNativeBFMenu, mChildren.Count, text, hotKey, (bitmap != null) ? bitmap.mNativeBFBitmap : null, enabled, checkState, radioCheck);
sysMenu.mParent = this;
sysMenu.mWindow = mWindow;
mWindow.mSysMenuMap[(int)sysMenu.mNativeBFMenu ] = sysMenu;
mChildren.Add(sysMenu);
return sysMenu;
}
public void SetDisabled(bool disabled)
{
mEnabled = !disabled;
Modify(mText, mHotKey, mBitmap, mEnabled, mCheckState, mRadioCheck);
}
public void SetHotKey(StringView hotKey)
{
if (hotKey.IsNull)
{
DeleteAndNullify!(mHotKey);
}
else
{
if (mHotKey == null)
mHotKey = new String(hotKey);
else
mHotKey.Set(hotKey);
}
UpdateChanges();
}
public void UpdateChanges()
{
mWindow.ModifyMenuItem(mNativeBFMenu, mText, mHotKey, (mBitmap != null) ? mBitmap.mNativeBFBitmap : null, mEnabled, mCheckState, mRadioCheck);
}
public virtual void Modify(String text, String hotKey = null, SysBitmap bitmap = null, bool enabled = true, int32 checkState = -1, bool radioCheck = false)
{
if ((Object)mText != text)
{
if (text != null)
{
if (mText == null)
mText = new String(text);
else
mText.Set(text);
}
else
DeleteAndNullify!(mText);
}
if ((Object)mHotKey != hotKey)
{
if (hotKey != null)
{
if (mHotKey == null)
mHotKey = new String(hotKey);
else
mHotKey.Set(hotKey);
}
else
DeleteAndNullify!(mHotKey);
}
mBitmap = bitmap;
mEnabled = enabled;
mCheckState = checkState;
mRadioCheck = radioCheck;
UpdateChanges();
}
public virtual void Dispose()
{
mWindow.mSysMenuMap.Remove((int)mNativeBFMenu);
mWindow.DeleteMenuItem(mNativeBFMenu);
}
public void UpdateChildItems()
{
if (mChildren != null)
{
for (SysMenu child in mChildren)
child.mOnMenuItemUpdate(child);
}
}
public virtual void Selected()
{
mOnMenuItemSelected(this);
UpdateChildItems();
}
}
}

View file

@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
using Beefy.gfx;
namespace Beefy.theme
{
public class DesignToolboxEntry
{
public String mGroupName;
public String mName;
public String mSortName;
public Image mIcon;
public Type mType;
public this(String name, Type theType, Image icon = null)
{
int32 index = (int32)name.IndexOf('@');
if (index != -1)
{
mName = new String(index);
mName.Append(name, 0, index);
mSortName = new String();
mSortName.Append(name, index + 1);
}
else
{
mName = new String(name);
mSortName = new String(name);
}
mType = theType;
mIcon = icon;
}
}
public class ThemeFactory
{
public static ThemeFactory mDefault;
public virtual void Init()
{
}
public virtual void Update()
{
}
public virtual ButtonWidget CreateButton(Widget parent, String caption, float x, float y, float width, float height)
{
return null;
}
public virtual CheckBox CreateCheckbox(Widget parent, float x = 0, float y = 0, float width = 0, float height = 0)
{
return null;
}
public virtual EditWidget CreateEditWidget(Widget parent, float x = 0, float y = 0, float width = 0, float height = 0)
{
return null;
}
public virtual TabbedView CreateTabbedView(TabbedView.SharedData sharedData, Widget parent = null, float x = 0, float y = 0, float width = 0, float height = 0)
{
return null;
}
public virtual DockingFrame CreateDockingFrame(DockingFrame parent = null)
{
return null;
}
public virtual ListView CreateListView()
{
return null;
}
public virtual Scrollbar CreateScrollbar(Scrollbar.Orientation orientation)
{
return null;
}
public virtual InfiniteScrollbar CreateInfiniteScrollbar()
{
return null;
}
public virtual MenuWidget CreateMenuWidget(Menu menu)
{
return null;
}
public virtual Dialog CreateDialog(String title = null, String text = null, Image icon = null)
{
return null;
}
}
}

View file

@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
using Beefy.gfx;
using Beefy.utils;
namespace Beefy.theme.dark
{
public class DarkButton : ButtonWidget, IHotKeyHandler
{
public String mLabel ~ delete _;
public float mDrawDownPct;
public float mLabelYOfs;
[DesignEditable(DefaultEditString=true)]
public String Label
{
get
{
return mLabel;
}
set
{
String.NewOrSet!(mLabel, value);
}
}
bool IHotKeyHandler.Handle(KeyCode keyCode)
{
if (mDisabled)
return false;
if (DarkTheme.CheckUnderlineKeyCode(mLabel, keyCode))
{
mDrawDownPct = 1.0f;
MouseClicked(0, 0, 3);
return true;
}
return false;
}
public override void DefaultDesignInit()
{
base.DefaultDesignInit();
mIdStr = "Button";
Label = "Button";
mWidth = GS!(80);
mHeight = GS!(20);
}
public override void Draw(Graphics g)
{
base.Draw(g);
bool drawDown = ((mMouseDown && mMouseOver) || (mMouseFlags.HasFlag(MouseFlag.Kbd)));
if (mDrawDownPct > 0)
drawDown = true;
Image texture = drawDown ? DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.BtnDown] :
mMouseOver ? DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.BtnOver] :
DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.BtnUp];
if (mDisabled)
texture = DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.BtnUp];
g.DrawBox(texture, 0, 0, mWidth, mHeight);
if ((mHasFocus) && (!mDisabled))
{
using (g.PushColor(DarkTheme.COLOR_SELECTED_OUTLINE))
g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Outline), 0, 0, mWidth, mHeight);
}
g.SetFont(DarkTheme.sDarkTheme.mSmallFont);
if (mLabel != null)
{
using (g.PushColor(mDisabled ? 0x80FFFFFF : Color.White))
{
DarkTheme.DrawUnderlined(g, mLabel, GS!(2), (mHeight - GS!(20)) / 2 + mLabelYOfs, .Centered, mWidth - GS!(4), .Truncate);
}
}
}
public override void Update()
{
base.Update();
if (mDrawDownPct > 0)
{
mDrawDownPct = Math.Max(mDrawDownPct - 0.25f, 0);
MarkDirty();
}
}
public override void Serialize(StructuredData data)
{
base.Serialize(data);
data.Add("Label", mLabel);
}
public override bool Deserialize(StructuredData data)
{
base.Deserialize(data);
data.GetString(mLabel, "Label");
return true;
}
public override void GotFocus()
{
base.GotFocus();
}
}
}

View file

@ -0,0 +1,176 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
using Beefy.gfx;
namespace Beefy.theme.dark
{
public class DarkCheckBox : CheckBox, IHotKeyHandler
{
public bool mLargeFormat;
public Image mCheckIcon;
public Image mIndeterminateIcon;
public String mLabel ~ delete _;
public Font mFont;
public bool mDisabled;
public State mState;
public override bool Checked
{
get
{
return mState != .Unchecked;
}
set
{
mState = value ? .Checked : .Unchecked;
}
}
public override State State
{
get
{
return mState;
}
set
{
mState = value;
}
}
public String Label
{
get
{
return mLabel;
}
set
{
String.NewOrSet!(mLabel, value);
}
}
public this()
{
mMouseInsets = new Insets(2, 2, 3, 3);
mCheckIcon = DarkTheme.sDarkTheme.GetImage(.Check);
mIndeterminateIcon = DarkTheme.sDarkTheme.GetImage(.CheckIndeterminate);
mFont = DarkTheme.sDarkTheme.mSmallFont;
}
bool IHotKeyHandler.Handle(KeyCode keyCode)
{
if (mDisabled)
return false;
if (DarkTheme.CheckUnderlineKeyCode(mLabel, keyCode))
{
//SetFocus();
Checked = !Checked;
return true;
}
return false;
}
public override void DefaultDesignInit()
{
base.DefaultDesignInit();
mIdStr = "CheckBox";
mWidth = 20;
mHeight = 20;
}
public override void Draw(Graphics g)
{
base.Draw(g);
if (mLargeFormat)
{
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.CheckboxLarge));
}
else
{
if (mMouseOver)
{
if (mMouseDown)
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.CheckboxDown));
else
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.CheckboxOver));
}
else
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Checkbox));
}
if (mState == .Checked)
g.Draw(mCheckIcon);
else if (mState == .Indeterminate)
g.Draw(mIndeterminateIcon);
if (mHasFocus)
{
using (g.PushColor(DarkTheme.COLOR_SELECTED_OUTLINE))
g.DrawButton(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Outline), 0, 0, mWidth);
}
if (mLabel != null)
{
g.SetFont(mFont);
DarkTheme.DrawUnderlined(g, mLabel, GS!(22), 0);
/*int underlinePos = mLabel.IndexOf('&');
if ((underlinePos != -1) && (underlinePos < mLabel.Length - 1))
{
String label = scope String();
label.Append(mLabel, 0, underlinePos);
float underlineX = mFont.GetWidth(label);
char32 underlineC = mLabel.GetChar32(underlinePos + 1).0;
float underlineWidth = mFont.GetWidth(underlineC);
label.Append(mLabel, underlinePos + 1);
g.DrawString(label, GS!(22), 0);
g.FillRect(GS!(22) + underlineX, mFont.GetAscent() + GS!(1), underlineWidth, (int)GS!(1.2f));
}
else
{
g.DrawString(mLabel, GS!(22), 0);
}*/
}
}
public override void DrawAll(Graphics g)
{
if (mDisabled)
{
using (g.PushColor(0x80FFFFFF))
base.DrawAll(g);
}
else
base.DrawAll(g);
}
public float CalcWidth()
{
if (mLabel == null)
return 20;
return mFont.GetWidth(mLabel) + GS!(22);
}
public override void KeyChar(char32 theChar)
{
if (mDisabled)
return;
base.KeyChar(theChar);
if (theChar == ' ')
Checked = !Checked;
}
}
}

View file

@ -0,0 +1,375 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
using Beefy.gfx;
using Beefy.events;
namespace Beefy.theme.dark
{
public class DarkComboBox : ComboBox
{
public class CBMenuWidget : DarkMenuWidget
{
public this(Menu menu) :
base(menu)
{
}
public override float GetReverseAdjust()
{
return GS!(-10);
}
}
/*public string Label
{
get
{
if (mEditWidget == null)
return mLabel;
else
return mEditWidget.Text;
}
set
{
if (mEditWidget == null)
mLabel = value;
else
mEditWidget.Text = value;
}
}*/
String mLabel ~ delete _;
public float mLabelX = GS!(8);
public FontAlign mLabelAlign = FontAlign.Centered;
public bool mFrameless = false;
public Event<Action<Menu>> mPopulateMenuAction ~ _.Dispose();
public CBMenuWidget mCurMenuWidget;
bool mJustClosed;
public uint32 mBkgColor;
public DarkEditWidget mEditWidget;
bool mAllowReverseDropdown; // Allow popdown to "popup" if there isn't enough space
public Widget mPrevFocusWidget;
public bool mFocusDropdown = true;
virtual public StringView Label
{
get
{
if (mEditWidget != null)
{
if (mLabel == null)
mLabel = new String();
mLabel.Clear();
mEditWidget.GetText(mLabel);
}
return mLabel;
}
set
{
String.NewOrSet!(mLabel, value);
if (mEditWidget != null)
mEditWidget.SetText(mLabel);
}
}
public override void Draw(Graphics g)
{
base.Draw(g);
float yOfs = 0;
if (mEditWidget != null)
{
g.DrawBox(DarkTheme.sDarkTheme.GetImage(.EditBox), 0, 0, mWidth, mHeight);
g.Draw(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.ComboEnd], mWidth - GS!(25), (mHeight - GS!(22)) / 2 + yOfs);
if ((mHasFocus) || (mEditWidget.mHasFocus))
{
using (g.PushColor(DarkTheme.COLOR_SELECTED_OUTLINE))
g.DrawBox(DarkTheme.sDarkTheme.GetImage(.Outline), 0, 0, mWidth, mHeight);
}
return;
}
if (!mFrameless)
{
Image texture = DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.ComboBox];
g.DrawBox(texture, 0, -2, mWidth, mHeight);
}
else
{
if (mBkgColor != 0)
{
using (g.PushColor(mBkgColor))
g.FillRect(0, 0, mWidth, mHeight);
}
yOfs = 2.0f;
}
if (mEditWidget == null)
{
using (g.PushColor(mDisabled ? 0x80FFFFFF : Color.White))
{
g.Draw(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.ComboEnd], mWidth - GS!(25), (mHeight - GS!(24)) / 2 + yOfs);
g.SetFont(DarkTheme.sDarkTheme.mSmallFont);
String label = scope String();
GetLabel(label);
if (label != null)
{
float fontHeight = g.mFont.GetHeight();
//g.DrawString(label, mLabelX, (mHeight - GS!(24)) / 2, mLabelAlign, mWidth - mLabelX - GS!(24), FontOverflowMode.Ellipsis);
g.DrawString(label, mLabelX, (mHeight - fontHeight) / 2 - GS!(2) - 1, mLabelAlign, mWidth - mLabelX - GS!(24), FontOverflowMode.Ellipsis);
}
}
if (mHasFocus)
{
using (g.PushColor(DarkTheme.COLOR_SELECTED_OUTLINE))
g.DrawBox(DarkTheme.sDarkTheme.GetImage(.Outline), GS!(2), 0, mWidth - GS!(4), mHeight - GS!(4));
}
}
}
public void GetLabel(String label)
{
if (mEditWidget == null)
{
if (mLabel != null)
label.Append(mLabel);
}
else
mEditWidget.GetText(label);
}
void HandleKeyDown(KeyDownEvent evt)
{
if (evt.mKeyCode == KeyCode.Escape)
{
evt.mHandled = true;
mCurMenuWidget.Close();
}
}
public virtual void MenuClosed()
{
if (mPrevFocusWidget != null)
{
mPrevFocusWidget.SetFocus();
}
}
void HandleClose(Menu menu, Menu selectedItem)
{
mCurMenuWidget = null;
mJustClosed = true;
//mWidgetWindow.mWindowKeyDownDelegate -= HandleKeyDown;
MenuClosed();
}
public virtual MenuWidget ShowDropdown()
{
mPrevFocusWidget = mWidgetWindow.mFocusWidget;
float popupXOfs = GS!(5);
float popupYOfs = GS!(-2);
if (mEditWidget != null)
{
popupXOfs = GS!(2);
popupYOfs = GS!(2);
}
else if (mFrameless)
{
popupXOfs = GS!(2);
popupYOfs = GS!(2);
}
//if (mCurMenuWidget != null)
//mCurMenuWidget.Close();
mAutoFocus = false;
Menu aMenu = new Menu();
mPopulateMenuAction(aMenu);
WidgetWindow menuWindow = null;
if (mCurMenuWidget != null)
menuWindow = mCurMenuWidget.mWidgetWindow;
let menuWidget = new CBMenuWidget(aMenu);
//menuWidget.SetShowPct(0.0f);
//menuWidget.mWindowFlags &= ~(BFWindow.Flags.PopupPosition);
mCurMenuWidget = menuWidget;
aMenu.mOnMenuClosed.Add(new => HandleClose);
menuWidget.mMinContainerWidth = mWidth + GS!(8);
menuWidget.mMaxContainerWidth = Math.Max(menuWidget.mMinContainerWidth, 1536);
menuWidget.mWindowFlags = .ClientSized | .DestAlpha | .FakeFocus;
if (!mFocusDropdown)
menuWidget.mWindowFlags |= .NoActivate;
menuWidget.CalcSize();
float popupY = mHeight + popupYOfs;
//TODO: Autocomplete didn't work on this: BFApp.sApp.GetW...
menuWidget.Init(this, popupXOfs, popupY, true, menuWindow);
// Why were we capturing?
mWidgetWindow.TransferMouse(menuWidget.mWidgetWindow);
if (menuWindow == null)
menuWidget.SetShowPct(0.0f);
return menuWidget;
}
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
{
base.MouseDown(x, y, btn, btnCount);
if (mDisabled)
return;
if ((mCurMenuWidget == null) && (!mJustClosed))
{
if (mEditWidget != null)
SetFocus();
ShowDropdown();
//mCurMenuWidget.SetFocus();
//mWidgetWindow.mWindowKeyDownDelegate += HandleKeyDown;
}
}
public override void SetFocus()
{
if (mEditWidget != null)
{
mEditWidget.SetFocus();
return;
}
base.SetFocus();
}
public override void Update()
{
base.Update();
mJustClosed = false;
bool hasFocus = mHasFocus;
if ((mEditWidget != null) && (mEditWidget.mHasFocus))
hasFocus = true;
if ((!hasFocus) && (mCurMenuWidget != null))
if (mCurMenuWidget.mWidgetWindow.mHasFocus)
hasFocus = true;
if ((!hasFocus) && (mCurMenuWidget != null))
{
mCurMenuWidget.SubmitSelection();
if (mCurMenuWidget != null)
mCurMenuWidget.Close();
}
}
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
ResizeComponents();
}
private void ResizeComponents()
{
if (mEditWidget != null)
{
mEditWidget.Resize(0, 0, Math.Max(mWidth - GS!(24), 0), mHeight);
}
}
public virtual bool WantsKeyHandling()
{
return true;
}
void EditKeyDownHandler(KeyDownEvent evt)
{
if (!WantsKeyHandling())
return;
if ((evt.mKeyCode == .Up) || (evt.mKeyCode == .Down) ||
(evt.mKeyCode == .PageUp) || (evt.mKeyCode == .PageDown) ||
(evt.mKeyCode == .Home) || (evt.mKeyCode == .End))
{
if (mCurMenuWidget != null)
mCurMenuWidget.KeyDown(evt.mKeyCode, false);
}
if ((evt.mKeyCode == .Down) && (mCurMenuWidget == null))
{
ShowDropdown();
var label = Label;
for (let itemWidget in mCurMenuWidget.mItemWidgets)
{
if (itemWidget.mMenuItem.mLabel == label)
mCurMenuWidget.SetSelection(@itemWidget.Index);
}
}
if ((evt.mKeyCode == .Escape) && (mCurMenuWidget != null) && (mEditWidget != null))
{
mCurMenuWidget.Close();
mEditWidget.SetFocus();
evt.mHandled = true;
}
if ((evt.mKeyCode == .Return) && (mCurMenuWidget != null))
{
mCurMenuWidget.SubmitSelection();
evt.mHandled = true;
}
}
public override void KeyDown(KeyCode keyCode, bool isRepeat)
{
if (mCurMenuWidget != null)
mCurMenuWidget.KeyDown(keyCode, isRepeat);
}
public void MakeEditable(DarkEditWidget editWidget = null)
{
if (mEditWidget == null)
{
mEditWidget = editWidget;
if (mEditWidget == null)
mEditWidget = new DarkEditWidget();
mEditWidget.mDrawBox = false;
mEditWidget.mOnSubmit.Add(new => EditSubmit);
mEditWidget.mOnKeyDown.Add(new => EditKeyDownHandler);
var ewc = (DarkEditWidgetContent)mEditWidget.mEditWidgetContent;
ewc.mScrollToStartOnLostFocus = true;
AddWidget(mEditWidget);
ResizeComponents();
}
}
private void EditSubmit(EditEvent theEvent)
{
if (mCurMenuWidget != null)
{
if (mCurMenuWidget.mSelectIdx != -1)
{
mCurMenuWidget.SubmitSelection();
if (mCurMenuWidget != null)
mCurMenuWidget.Close();
}
}
}
public override void KeyDown(KeyDownEvent keyEvent)
{
base.KeyDown(keyEvent);
EditKeyDownHandler(keyEvent);
}
}
}

View file

@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.gfx;
using Beefy.widgets;
namespace Beefy.theme.dark
{
public class DarkDialog : Dialog
{
public Font mFont;
public Insets mTextInsets = new Insets() ~ delete _;
public float mMinWidth;
public float mButtonBottomMargin = GS!(12);
public float mButtonRightMargin = GS!(16);
public this(String title = null, String text = null, Image icon = null) :
base(title, text, icon)
{
mFont = DarkTheme.sDarkTheme.mSmallFont;
mTextInsets.Set(GS!(20), GS!(20), GS!(20), GS!(20));
if (icon != null)
mTextInsets.mLeft += icon.mWidth + GS!(20);
}
public override ButtonWidget CreateButton(String label)
{
DarkButton button = new DarkButton();
button.Label = label;
button.mAutoFocus = true;
return button;
}
public override EditWidget CreateEditWidget()
{
return new DarkEditWidget();
}
public override void CalcSize()
{
base.CalcSize();
// Size buttons with a zero width first so we can determine a minimium size this dialog needs to be
mWidth = mMinWidth;
mHeight = 0;
ResizeComponents();
String str = scope String();
for (var strView in mText.Split('\n'))
{
str.Clear();
strView.ToString(str);
mWidth = Math.Max(mWidth, mFont.GetWidth(str) + mTextInsets.Horz);
}
mWidth = Math.Max(mWidth, GS!(240));
float maxWidth = GS!(900);
if (mWidth >= maxWidth)
{
// We don't want to barely size the dialog large enough, otherwise the wrapping would leave just a short chunk
if (mWidth < maxWidth * 1.4f)
mWidth = maxWidth * 0.7f;
else
mWidth = maxWidth;
}
mWidth = Math.Max(-mButtons[0].mX + mTextInsets.mLeft, mWidth);
mHeight = GS!(80);
for (var strView in mText.Split('\n'))
{
str.Clear();
strView.ToString(str);
mHeight += mFont.GetWrapHeight(str, mWidth - mTextInsets.Horz);
}
if (mDialogEditWidget != null)
mHeight += GS!(16);
}
public override void ResizeComponents()
{
base.ResizeComponents();
float maxTextLen = 0;
for (DarkButton button in mButtons)
maxTextLen = Math.Max(maxTextLen, mFont.GetWidth(button.mLabel));
float buttonBaseSize = GS!(30) + maxTextLen;
float spacing = GS!(8);
float curY = mHeight - GS!(20) - mButtonBottomMargin;
float curX = mWidth - (mButtons.Count * buttonBaseSize) - ((mButtons.Count - 1) * spacing) - mButtonRightMargin;
if (mDialogEditWidget != null)
{
mDialogEditWidget.Resize(GS!(16), curY - GS!(36), Math.Max(mWidth - GS!(16) * 2, 0), GS!(24));
}
for (DarkButton button in mButtons)
{
float aSize = buttonBaseSize;
button.Resize(curX, curY, aSize, GS!(22));
curX += aSize + spacing;
}
}
public override void Draw(Graphics g)
{
base.Draw(g);
using (g.PushColor(DarkTheme.COLOR_WINDOW))
g.FillRect(0, 0, mWidth, mHeight);
if (mIcon != null)
g.Draw(mIcon, GS!(20), (mHeight - GS!(8) - mIcon.mHeight) / 2);
g.SetFont(mFont);
if (mText != null)
g.DrawString(mText, mTextInsets.mLeft, mTextInsets.mTop, FontAlign.Left, mWidth - mTextInsets.Horz, FontOverflowMode.Wrap);
}
}
}

View file

@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
using Beefy.gfx;
namespace Beefy.theme.dark
{
public class DarkDockingFrame : DockingFrame
{
IDockable mCurDragTarget;
public bool mDrawBkg = true;
public this()
{
mMinWindowSize = GS!(100);
mMinWindowSize = GS!(32);
mDragMarginSize = GS!(64);
mDragWindowMarginSize = GS!(10);
mWindowMargin = 0;
mSplitterSize = GS!(6.0f);
mWindowSpacing = GS!(2.0f);
}
public ~this()
{
}
public override void RemovedFromParent(Widget previousParent, WidgetWindow window)
{
base.RemovedFromParent(previousParent, window);
}
public override void Draw(Graphics g)
{
if (mDrawBkg)
{
using (g.PushColor(DarkTheme.COLOR_BKG))
g.FillRect(0, 0, mWidth, mHeight);
}
base.Draw(g);
}
public override void DrawAll(Graphics g)
{
base.DrawAll(g);
if ((mCurDragTarget != null) && (mWidgetWindow.mAlpha == 1.0f))
{
using (g.PushTranslate(mWidgetWindow.mMouseX, mWidgetWindow.mMouseY))
{
mCurDragTarget.DrawDockPreview(g);
}
}
}
public override void DrawDraggingDock(Graphics g)
{
if (mDraggingCustomDock != null)
{
mDraggingCustomDock.Draw(g);
}
else
{
if (mDraggingAlign == WidgetAlign.Inside)
{
using (g.PushColor(0x30FFFFFF))
g.DrawBox(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.WhiteCircle], mDraggingRef.mX, mDraggingRef.mY, mDraggingRef.mWidth, mDraggingRef.mHeight);
}
else
{
DockedWidget widgetRef = mDraggingRef ?? this;
Matrix matrix = Matrix.IdentityMatrix;
float dist = 0;
if (mDraggingAlign == WidgetAlign.Left)
{
matrix.Rotate(Math.PI_f);
matrix.Translate(widgetRef.mX, widgetRef.mY + widgetRef.mHeight);
dist = widgetRef.mHeight;
}
else if (mDraggingAlign == WidgetAlign.Right)
{
matrix.Rotate(0);
matrix.Translate(widgetRef.mX + widgetRef.mWidth, widgetRef.mY);
dist = widgetRef.mHeight;
}
else if (mDraggingAlign == WidgetAlign.Top)
{
matrix.Rotate(-Math.PI_f / 2);
matrix.Translate(widgetRef.mX, widgetRef.mY);
dist = widgetRef.mWidth;
}
else if (mDraggingAlign == WidgetAlign.Bottom)
{
matrix.Rotate(Math.PI_f / 2);
matrix.Translate(widgetRef.mX + widgetRef.mWidth, widgetRef.mY + widgetRef.mHeight);
dist = widgetRef.mWidth;
}
using (g.PushMatrix(matrix))
{
if (mDraggingRef != null)
g.DrawBox(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.GlowDot], GS!(-9), GS!(-8), GS!(20), dist + GS!(8) * 2);
else
g.DrawBox(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.WhiteCircle], GS!(-13), GS!(-8), GS!(20), dist + GS!(8) * 2);
int32 arrowCount = 3;
if (dist < 80)
arrowCount = 1;
else if (dist < 120)
arrowCount = 2;
float arrowSep = dist / (arrowCount + 1);
for (int32 arrowNum = 0; arrowNum < arrowCount; arrowNum++)
g.Draw(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.ArrowRight], GS!(-22), GS!(-9) + (arrowNum + 1) * arrowSep);
}
}
}
}
public override void ShowDragTarget(IDockable draggingItem)
{
base.ShowDragTarget(draggingItem);
mCurDragTarget = draggingItem;
}
public override void HideDragTarget(IDockable draggingItem, bool executeDrag = false)
{
base.HideDragTarget(draggingItem, executeDrag);
mCurDragTarget = null;
}
}
}

View file

@ -0,0 +1,922 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Beefy.widgets;
using Beefy.gfx;
using Beefy.utils;
namespace Beefy.theme.dark
{
public class DarkEditWidgetContent : EditWidgetContent
{
public Font mFont;
public uint32[] mTextColors = sDefaultColors;
public uint32 mHiliteColor = 0xFF2f5c88;
public uint32 mUnfocusedHiliteColor = 0x00000000;
public int32 mRecalcSizeLineNum = -1;
public float mRecalcSizeCurMaxWidth = 0;
public bool mHasQueuedRecalcSize;
public int32 mTopCharId = -1;
public double mTopCharIdVertPos = -1;
public bool mWantsCheckScrollPosition;
public uint32 mViewWhiteSpaceColor;
public bool mScrollToStartOnLostFocus;
protected static uint32[] sDefaultColors = new uint32[] { Color.White } ~ delete _;
public this(EditWidgetContent refContent = null) : base(refContent)
{
//mTextInsets.Set(-3, 2, 0, 2);
//mTextInsets.Set(GS!(-3), GS!(2), 0, GS!(2));
mTextInsets.Set(GS!(0), GS!(2), 0, GS!(2));
mWidth = GS!(100);
mHeight = GS!(24);
mHorzJumpSize = GS!(40);
mFont = DarkTheme.sDarkTheme.mSmallFont;
}
public override void GetTextData()
{
// Generate text flags if we need to...
if ((mData.mTextFlags == null) && (mWordWrap))
{
scope AutoBeefPerf("DEWC.GetTextData");
mData.mTextFlags = new uint8[mData.mTextLength + 1];
int32 lineIdx = 0;
int32 lineStartIdx = 0;
String lineCheck = scope String();
for (int32 i = 0; i < mData.mTextLength; i++)
{
char8 c = (char8)mData.mText[i].mChar;
lineCheck.Clear();
if (c == '\n')
ExtractString(lineStartIdx, i - lineStartIdx, lineCheck);
else if (i == mData.mTextLength - 1)
ExtractString(lineStartIdx, i - lineStartIdx + 1, lineCheck);
if (lineCheck.Length > 0)
{
String lineCheckLeft = scope String();
lineCheckLeft.Reference(lineCheck);
while (true)
{
int32 maxChars = GetTabbedCharCountToLength(lineCheckLeft, mEditWidget.mScrollContentContainer.mWidth - mTextInsets.mLeft - mTextInsets.mRight);
if (maxChars == 0)
maxChars = 1;
if (maxChars >= lineCheckLeft.Length)
break;
int32 checkIdx = maxChars;
while ((checkIdx > 0) && (!lineCheckLeft[checkIdx].IsWhiteSpace))
checkIdx--;
if (checkIdx == 0)
checkIdx = maxChars - 1;
mData.mTextFlags[lineStartIdx + checkIdx + 1] |= (int32)TextFlags.Wrap;
lineStartIdx += checkIdx + 1;
//lineCheck.Remove(0, checkIdx + 1);
lineCheckLeft.AdjustPtr(checkIdx + 1);
}
}
if (c == '\n')
{
lineStartIdx = i + 1;
lineIdx++;
}
}
}
base.GetTextData();
}
protected override void AdjustCursorsAfterExternalEdit(int index, int ofs)
{
base.AdjustCursorsAfterExternalEdit(index, ofs);
mWantsCheckScrollPosition = true;
}
public float GetTabbedPos(float startX)
{
float spaceWidth = mFont.GetWidth((char32)' ');
if (mTabSize == 0)
return startX + spaceWidth;
return (float)Math.Truncate((startX + spaceWidth) / mTabSize + 0.999f) * mTabSize;
}
static mixin GetTabSection(var origString, var stringLeft, var subStr)
{
int32 tabIdx = (int32)stringLeft.IndexOf('\t');
if (tabIdx == -1)
break;
if (subStr == null)
{
subStr = scope:: String(stringLeft, 0, tabIdx);
stringLeft = scope:: String(origString, tabIdx + 1);
}
else
{
subStr.Clear();
subStr.Append(stringLeft, 0, tabIdx);
stringLeft.Remove(0, tabIdx + 1);
}
tabIdx
}
public float DoDrawText(Graphics g, String origString, float x, float y)
{
String stringLeft = origString;
float aX = x;
float aY = y;
void DrawString(String str, float x, float y)
{
if (str.Length == 0)
return;
g.DrawString(str, x, y);
if (mViewWhiteSpaceColor != 0)
{
let prevColor = g.mColor;
g.PopColor();
g.PushColor(mViewWhiteSpaceColor);
float curX = x;
int lastNonSpace = 0;
for (int i < str.Length)
{
char8 c = str[i];
if (c == ' ')
{
// Flush length
if (lastNonSpace < i)
{
var contentStr = scope String();
contentStr.Reference(str.Ptr + lastNonSpace, i - lastNonSpace);
curX += mFont.GetWidth(contentStr);
}
g.DrawString("·", curX, y);
curX += mFont.GetWidth(' ');
lastNonSpace = i + 1;
}
}
g.PopColor();
g.PushColorOverride(prevColor);
}
}
String subStr = null;
while (true)
{
GetTabSection!(origString, stringLeft, subStr);
if (g != null)
DrawString(subStr, aX, aY);
aX += mFont.GetWidth(subStr);
if ((mViewWhiteSpaceColor != 0) && (g != null))
{
let prevColor = g.mColor;
g.PopColor();
g.PushColor(mViewWhiteSpaceColor);
g.DrawString("→", aX, y);
g.PopColor();
g.PushColorOverride(prevColor);
}
aX = GetTabbedPos(aX);
}
if (g != null)
DrawString(stringLeft, aX, aY);
//TODO: This is just an "emergency dropout", remove when we optimize more?
/*if ((mX + x >= 0) && (stringLeft.Length > 1000))
{
return aX + 10000;
}*/
aX += mFont.GetWidth(stringLeft);
return aX;
}
/*public int GetTabbedCharCountToLength(String origString, float len)
{
String stringLeft = origString;
float aX = 0;
int idx = 0;
String subStr = null;
while (true)
{
int tabIdx = GetTabSection!(origString, stringLeft, subStr);
int char8Count = mFont.GetCharCountToLength(subStr, len - aX);
if (char8Count < subStr.Length)
return idx + char8Count;
idx += tabIdx + 1;
aX += mFont.GetWidth(subStr);
float prevX = aX;
aX = GetTabbedPos(aX);
if (len < aX)
return idx - 1;
}
return idx + mFont.GetCharCountToLength(stringLeft, len - aX);
}*/
public int32 GetTabbedCharCountToLength(String origString, float len)
{
float aX = 0;
int32 idx = 0;
String subStr = scope String();
subStr.Reference(origString);
while (true)
{
bool hitTabStop = false;
int32 char8Count = (int32)mFont.GetCharCountToLength(subStr, len - aX, &hitTabStop);
if (!hitTabStop)
return idx + char8Count;
aX += mFont.GetWidth(StringView(subStr, 0, char8Count));
aX = GetTabbedPos(aX);
if (aX > len + 0.001f)
return idx + char8Count;
idx += char8Count + 1;
subStr.AdjustPtr(char8Count + 1);
}
}
public virtual void DrawSectionFlagsOver(Graphics g, float x, float y, float width, uint8 flags)
{
}
public float GetTabbedWidth(String origString, float x, bool forceAccurate = false)
{
String stringLeft = origString;
float aX = x;
String subStr = null;
while (true)
{
#unwarn
int32 tabIdx = GetTabSection!(origString, stringLeft, subStr);
aX += mFont.GetWidth(subStr);
aX = GetTabbedPos(aX);
}
//TODO: This is just an "emergency dropout", remove when we optimize more?
/*if ((!forceAccurate) && (mX + x >= 0) && (stringLeft.Length > 1000))
{
return aX + 10000;
}*/
return aX + mFont.GetWidth(stringLeft);
}
public void SetFont(Font font, bool isMonospace, bool virtualCursor)
{
mFont = font;
if (isMonospace)
{
mCharWidth = mFont.GetWidth((char32)' ');
//Debug.Assert(mFont.GetWidth((char32)'W') == mCharWidth);
if (mTabSize == 0)
mTabSize = mTabLength * mCharWidth;
else
mTabSize = (float)Math.Round(mTabSize / mCharWidth) * mCharWidth;
}
else
mCharWidth = -1;
if (virtualCursor)
Debug.Assert(isMonospace);
mAllowVirtualCursor = virtualCursor;
}
public override void RehupScale(float oldScale, float newScale)
{
base.RehupScale(oldScale, newScale);
Utils.RoundScale(ref mTabSize, newScale / oldScale);
SetFont(mFont, mCharWidth != -1, mAllowVirtualCursor);
mContentChanged = true; // Defer calling of RecalcSize
}
public virtual float DrawText(Graphics g, String str, float x, float y, uint16 typeIdAndFlags)
{
using (g.PushColor(mTextColors[typeIdAndFlags & 0xFF]))
return DoDrawText(g, str, x, y);
}
public virtual uint32 GetSelectionColor(uint8 flags)
{
return mEditWidget.mHasFocus ? mHiliteColor : mUnfocusedHiliteColor;
}
public override void Draw(Graphics g)
{
base.Draw(g);
#unwarn
int lineCount = GetLineCount();
float lineSpacing = GetLineHeight(0);
g.SetFont(mFont);
float offsetY = mTextInsets.mTop;
if (mHeight < lineSpacing)
offsetY = (mHeight - lineSpacing) * 0.75f;
g.PushTranslate(mTextInsets.mLeft, offsetY);
int selStartLine = -1;
int selStartCharIdx = -1;
int selEndLine = -1;
int selEndCharIdx = -1;
int selStartIdx = -1;
int selEndIdx = -1;
if (mSelection != null)
{
mSelection.Value.GetAsForwardSelect(out selStartIdx, out selEndIdx);
GetLineCharAtIdx(selStartIdx, out selStartLine, out selStartCharIdx);
GetLineCharAtIdx(selEndIdx, out selEndLine, out selEndCharIdx);
}
int firstLine;
int firstCharIdx;
float overflowX;
GetLineCharAtCoord(0, -mY, out firstLine, out firstCharIdx, out overflowX);
int lastLine;
int lastCharIdx;
float lastOverflowX;
GetLineCharAtCoord(0, -mY + mEditWidget.mScrollContentContainer.mHeight, out lastLine, out lastCharIdx, out lastOverflowX);
bool drewCursor = false;
String sectionText = scope String(256);
for (int lineIdx = firstLine; lineIdx <= lastLine; lineIdx++)
{
//string lineText = GetLineText(lineIdx);
int lineStart;
int lineEnd;
GetLinePosition(lineIdx, out lineStart, out lineEnd);
int lineDrawStart = lineStart;
float curX = 0;
float curY = lineIdx * lineSpacing;
while (true)
{
int lineDrawEnd = lineDrawStart;
uint16 curTypeIdAndFlags = *(uint16*)&mData.mText[lineDrawStart].mDisplayTypeId;
// Check for transition of curTypeIdAndFlags - colors ignore whitespace, but if flags are set then we need
// to be exact
/*while ((lineDrawEnd < lineEnd) && ((*(uint16*)&mData.mText[lineDrawEnd].mDisplayTypeId == curTypeIdAndFlags) ||
((curTypeIdAndFlags < 0x100) && (((char8)mData.mText[lineDrawEnd].mChar).IsWhiteSpace))))
lineDrawEnd++;*/
while (true)
{
var checkEnd = ref mData.mText[lineDrawEnd];
if ((lineDrawEnd < lineEnd) && ((*(uint16*)&checkEnd.mDisplayTypeId == curTypeIdAndFlags) ||
((curTypeIdAndFlags < 0x100) && (checkEnd.mChar.IsWhiteSpace) && (checkEnd.mDisplayFlags == 0))))
lineDrawEnd++;
else
break;
}
sectionText.Clear();
ExtractString(lineDrawStart, lineDrawEnd - lineDrawStart, sectionText);
int selStart = Math.Max(0, selStartIdx - lineDrawStart);
int selEnd = Math.Min(lineDrawEnd - lineDrawStart, selEndIdx - lineDrawStart);
uint8 flags = (uint8)(curTypeIdAndFlags >> 8);
if ((lineDrawStart >= selStartIdx) && (lineDrawEnd < selEndIdx) && (lineDrawEnd == lineDrawStart))
{
// Blank line selected
using (g.PushColor(GetSelectionColor(flags)))
g.FillRect(curX, curY, 4, lineSpacing);
}
if (selEnd > selStart)
{
String selPrevString = scope String(selStart);
selPrevString.Append(sectionText, 0, selStart);
String selIncludeString = scope String(selEnd);
selIncludeString.Append(sectionText, 0, selEnd);
float selStartX = GetTabbedWidth(selPrevString, curX);
float selEndX = GetTabbedWidth(selIncludeString, curX);
if (lineIdx != selEndLine)
selEndX += mFont.GetWidth((char32)' ');
using (g.PushColor(GetSelectionColor(flags)))
g.FillRect(selStartX, curY, selEndX - selStartX, lineSpacing);
}
float nextX = curX;
nextX = DrawText(g, sectionText, curX, curY, curTypeIdAndFlags);
DrawSectionFlagsOver(g, curX, curY, nextX - curX, flags);
//int32 lineDrawStartColumn = lineDrawStart - lineStart;
//int32 lineDrawEndColumn = lineDrawEnd - lineStart;
if ((mEditWidget.mHasFocus) && (!drewCursor))
{
float aX = -1;
if (mVirtualCursorPos != null)
{
if ((lineIdx == mVirtualCursorPos.Value.mLine) && (lineDrawEnd == lineEnd))
{
aX = mVirtualCursorPos.Value.mColumn * mCharWidth;
}
}
else if (mCursorTextPos >= lineDrawStart)
{
bool isInside = mCursorTextPos < lineDrawEnd;
if ((mCursorTextPos == lineDrawEnd) && (lineDrawEnd == lineEnd))
{
if (lineDrawEnd == mData.mTextLength)
isInside = true;
if (mWordWrap)
{
if ((mShowCursorAtLineEnd) || (lineEnd >= mData.mTextFlags.Count) || (mData.mTextFlags[lineEnd] & (int32)TextFlags.Wrap) == 0)
isInside = true;
}
else
isInside = true;
}
if (isInside)
{
String subText = scope String(mCursorTextPos - lineDrawStart);
subText.Append(sectionText, 0, mCursorTextPos - lineDrawStart);
aX = GetTabbedWidth(subText, curX);
}
}
if (aX != -1)
{
float brightness = (float)Math.Cos(Math.Max(0.0f, mCursorBlinkTicks - 20) / 9.0f);
brightness = Math.Max(0, Math.Min(1.0f, brightness * 2.0f + 1.6f));
if (mEditWidget.mVertPos.IsMoving)
brightness = 0; // When we animate a pgup or pgdn, it's weird seeing the cursor scrolling around
if (mOverTypeMode)
{
if (mCharWidth <= 2)
{
using (g.PushColor(Color.Get(brightness * 0.75f)))
g.FillRect(aX, curY, GS!(2), lineSpacing);
}
else
{
using (g.PushColor(Color.Get(brightness * 0.30f)))
g.FillRect(aX, curY, mCharWidth, lineSpacing);
}
}
else
{
using (g.PushColor(Color.Get(brightness)))
g.FillRect(aX, curY, Math.Max(1.0f, GS!(1)), lineSpacing);
}
drewCursor = true;
}
}
lineDrawStart = lineDrawEnd;
curX = nextX;
if (lineDrawStart >= lineEnd)
break;
}
}
g.PopMatrix();
/*using (g.PushColor(0x4000FF00))
g.FillRect(-8, -8, mWidth + 16, mHeight + 16);*/
/*if (mDbgX != -1)
g.FillRect(mDbgX - 1, mDbgY - 1, 3, 3);*/
}
public override void AddWidget(Widget widget)
{
base.AddWidget(widget);
}
public override bool AllowChar(char32 theChar)
{
if ((int)theChar < 32)
return (theChar == '\n') || (mIsMultiline && (theChar == '\t'));
return mFont.HasChar(theChar);
}
public override void InsertAtCursor(String theString, InsertFlags insertFlags)
{
scope AutoBeefPerf("DarkEditWidgetContent.InsertAtCursor");
base.InsertAtCursor(theString, insertFlags);
}
public override void GetTextCoordAtLineChar(int line, int lineChar, out float x, out float y)
{
String lineText = scope String(256);
GetLineText(line, lineText);
if (lineChar > lineText.Length)
x = GetTabbedWidth(lineText, 0) + (mFont.GetWidth((char32)' ') * (lineChar - (int32)lineText.Length)) + mTextInsets.mLeft;
else
{
String subText = scope String(Math.Min(lineChar, 256));
subText.Append(lineText, 0, lineChar);
x = GetTabbedWidth(subText, 0, true) + mTextInsets.mLeft;
}
y = mTextInsets.mTop + line * mFont.GetLineSpacing();
}
public override void GetTextCoordAtLineAndColumn(int line, int column, out float x, out float y)
{
Debug.Assert((mCharWidth != -1) || (column == 0));
String lineText = scope String(256);
GetLineText(line, lineText);
x = mTextInsets.mLeft + column * mCharWidth;
y = mTextInsets.mTop + line * mFont.GetLineSpacing();
}
public override bool GetLineCharAtCoord(float x, float y, out int line, out int char8Idx, out float overflowX)
{
line = (int) ((y - mTextInsets.mTop) / mFont.GetLineSpacing() + 0.001f);
int lineCount = GetLineCount();
if (line < 0)
line = 0;
if (line >= lineCount)
line = lineCount - 1;
String lineText = scope String(256);
GetLineText(line, lineText);
int32 char8Count = GetTabbedCharCountToLength(lineText, x - mTextInsets.mLeft);
char8Idx = char8Count;
if (char8Count < lineText.Length)
{
String subString = scope String(char8Count);
subString.Append(lineText, 0, char8Count);
float subWidth = GetTabbedWidth(subString, 0);
var utf8enumerator = lineText.DecodedChars(char8Count);
if (utf8enumerator.MoveNext())
{
char32 c = utf8enumerator.Current;
float checkCharWidth = 0;
if (c == '\t')
checkCharWidth = mTabSize * 0.5f;
else
{
checkCharWidth = mFont.GetWidth(c) * 0.5f;
}
if (x >= subWidth + mTextInsets.mLeft + checkCharWidth)
char8Idx = (int32)utf8enumerator.NextIndex;
}
}
else
{
overflowX = (x - mTextInsets.mLeft) - (GetTabbedWidth(lineText, 0) + 0.001f);
return overflowX <= 0;
}
overflowX = 0;
return true;
}
public override bool GetLineAndColumnAtCoord(float x, float y, out int line, out int column)
{
line = (int32)((y - mTextInsets.mTop) / mFont.GetLineSpacing() + 0.001f);
if (line >= GetLineCount())
line = GetLineCount() - 1;
line = Math.Max(0, line);
column = Math.Max(0, (int32)((x - mTextInsets.mLeft + 1) / mCharWidth + 0.6f));
return mCharWidth != -1;
}
void RecalcSize(int32 startLineNum, int32 endLineNum, bool forceAccurate = false)
{
scope AutoBeefPerf("DEWC.RecalcSize");
String line = scope String();
for (int32 lineIdx = startLineNum; lineIdx < endLineNum; lineIdx++)
{
line.Clear();
GetLineText(lineIdx, line);
mRecalcSizeCurMaxWidth = Math.Max(mRecalcSizeCurMaxWidth, GetTabbedWidth(line, 0, forceAccurate) + mHorzJumpSize);
Debug.Assert(!mRecalcSizeCurMaxWidth.IsNaN);
}
}
public override void CursorToLineEnd()
{
//int32 line;
//int32 lineChar;
//GetCursorLineChar(out line, out lineChar);
/*RecalcSize(line, line + 1, true);
if (mRecalcSizeCurMaxWidth > mWidth)
{
mRecalcSizeLineNum = -1;
}*/
mRecalcSizeLineNum = -1;
RecalcSize(true);
base.CursorToLineEnd();
}
public void RecalcSize(bool forceAccurate = false)
{
mMaximalScrollAddedHeight = 0;
if (mRecalcSizeLineNum == -1)
{
mRecalcSizeCurMaxWidth = 0;
mHasQueuedRecalcSize = false;
}
else // We need to recalc again after our current pass
mHasQueuedRecalcSize = true;
if (!mIsReadOnly)
{
float cursorX;
float cursorY;
GetTextCoordAtCursor(out cursorX, out cursorY);
mRecalcSizeCurMaxWidth = Math.Max(mRecalcSizeCurMaxWidth, cursorX + mHorzJumpSize);
}
if (mUpdateCnt == 0)
{
RecalcSize(0, GetLineCount());
mWidth = mRecalcSizeCurMaxWidth + mTextInsets.mLeft + mTextInsets.mRight;
Debug.Assert(!mWidth.IsNaN);
}
else if (mRecalcSizeLineNum == -1)
{
mRecalcSizeLineNum = 0;
// The actual recalculation will take 16 ticks so just make sure we have enough width for
// the current line for now
var lineAndCol = CursorLineAndColumn;
RecalcSize(lineAndCol.mLine, lineAndCol.mLine + 1, forceAccurate);
mWidth = Math.Max(mWidth, mRecalcSizeCurMaxWidth + mTextInsets.mLeft + mTextInsets.mRight);
Debug.Assert(!mWidth.IsNaN);
}
mHeight = GetLineCount() * mFont.GetLineSpacing() + mTextInsets.mTop + mTextInsets.mBottom;
UpdateMaximalScroll();
base.RecalcSize();
}
public override void RecalcSize()
{
RecalcSize(false);
}
public override void ContentChanged()
{
base.ContentChanged();
mRecalcSizeLineNum = -1;
}
public override void TextAppended(String str)
{
if ((mData.mLineStarts != null) && (mIsReadOnly))
{
int32 recalcSizeLineNum = Math.Max((int32)mData.mLineStarts.Count - 2, 0);
if ((mRecalcSizeLineNum == -1) || (recalcSizeLineNum < mRecalcSizeLineNum))
mRecalcSizeLineNum = recalcSizeLineNum;
}
base.TextAppended(str);
}
void UpdateMaximalScroll()
{
if (mAllowMaximalScroll)
{
let prevHeight = mHeight;
mHeight -= mMaximalScrollAddedHeight;
mMaximalScrollAddedHeight = mEditWidget.mScrollContentContainer.mHeight - mFont.GetLineSpacing();
mHeight += mMaximalScrollAddedHeight;
if (mHeight != prevHeight)
mEditWidget.UpdateScrollbars();
}
}
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
UpdateMaximalScroll();
}
public override float GetLineHeight(int line)
{
return mFont.GetLineSpacing();
}
public override float GetPageScrollTextHeight()
{
float numLinesVisible = mEditWidget.mScrollContentContainer.mHeight / mFont.GetLineSpacing();
if (numLinesVisible - (int32)numLinesVisible < 0.90f)
numLinesVisible = (int32) numLinesVisible;
float val = numLinesVisible * mFont.GetLineSpacing();
if (val <= 0)
return base.GetPageScrollTextHeight();
return val;
}
public void CheckRecordScrollTop()
{
if (mWantsCheckScrollPosition)
{
if (mTopCharId != -1)
{
int textIdx = mData.mTextIdData.GetPrepared().GetIndexFromId(mTopCharId);
if (textIdx != -1)
{
int line;
int lineChar;
GetLineCharAtIdx(textIdx, out line, out lineChar);
var vertPos = mEditWidget.mVertPos.mDest;
var offset = vertPos % mFont.GetLineSpacing();
mEditWidget.mVertScrollbar.ScrollTo(line * mFont.GetLineSpacing() + offset);
}
else
{
mTopCharId = -1;
}
}
mWantsCheckScrollPosition = false;
}
if (mEditWidget.mHasFocus)
{
mTopCharId = -1;
}
else
{
var vertPos = mEditWidget.mVertPos.mDest;
if ((mTopCharId == -1) || (mTopCharIdVertPos != vertPos))
{
float lineNum = (float)(vertPos / mFont.GetLineSpacing());
int lineStart;
int lineEnd;
GetLinePosition((int32)lineNum, out lineStart, out lineEnd);
int idAtStart = mData.mTextIdData.GetIdAtIndex((int32)lineStart);
if (idAtStart == -1)
idAtStart = 0;
mTopCharId = (int32)idAtStart;
mTopCharIdVertPos = vertPos;
}
}
}
public override void Update()
{
base.Update();
if ((mRecalcSizeLineNum != -1) && (BFApp.sApp.mIsUpdateBatchStart))
{
int32 lineCount = GetLineCount();
int32 toLine = Math.Min(lineCount, mRecalcSizeLineNum + Math.Max(1, lineCount / 16) + 80);
RecalcSize(mRecalcSizeLineNum, toLine);
if (toLine == lineCount)
{
mRecalcSizeLineNum = -1;
mWidth = mRecalcSizeCurMaxWidth + mTextInsets.mLeft + mTextInsets.mRight;
base.RecalcSize();
}
else
mRecalcSizeLineNum = toLine;
}
if ((mRecalcSizeLineNum == -1) && (mHasQueuedRecalcSize))
RecalcSize();
CheckRecordScrollTop();
}
}
public class DarkEditWidget : EditWidget
{
public bool mDrawBox = true;
public this(DarkEditWidgetContent content = null)
{
mEditWidgetContent = content;
if (mEditWidgetContent == null)
mEditWidgetContent = new DarkEditWidgetContent();
mEditWidgetContent.mEditWidget = this;
mScrollContent = mEditWidgetContent;
mScrollContentContainer.AddWidget(mEditWidgetContent);
SetupInsets();
//mScrollbarInsets.Set(18, 1, 0, 0);
mHorzPos.mSpeed = 0.2f;
mVertPos.mSpeed = 0.2f;
mScrollbarBaseContentSizeOffset = GS!(3);
}
protected virtual void SetupInsets()
{
mScrollContentInsets.Set(GS!(3), GS!(3), GS!(3), GS!(3));
}
protected override void HandleWindowMouseDown(Beefy.events.MouseEvent event)
{
base.HandleWindowMouseDown(event);
// If we got closed as part of this click, don't propagate the click through
if (mParent == null)
{
event.mHandled = true;
}
}
public override void RehupScale(float oldScale, float newScale)
{
base.RehupScale(oldScale, newScale);
SetupInsets();
}
public override void DefaultDesignInit()
{
base.DefaultDesignInit();
mWidth = GS!(80);
mHeight = GS!(20);
SetText("Edit Text");
}
public override void InitScrollbars(bool wantHorz, bool wantVert)
{
SetupInsets();
base.InitScrollbars(wantHorz, wantVert);
float scrollIncrement = ((DarkEditWidgetContent) mEditWidgetContent).mFont.GetLineSpacing() * GS!(3);
if (mHorzScrollbar != null)
mHorzScrollbar.mScrollIncrement = scrollIncrement;
if (mVertScrollbar != null)
mVertScrollbar.mScrollIncrement = scrollIncrement;
}
public override void Draw(Graphics g)
{
base.Draw(g);
if (mDrawBox)
{
g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.EditBox), 0, 0, mWidth, mHeight);
if (mHasFocus)
{
using (g.PushColor(DarkTheme.COLOR_SELECTED_OUTLINE))
g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Outline), 0, 0, mWidth, mHeight);
}
}
/*using (g.PushColor(0x40FF0000))
g.FillRect(0, 0, mWidth, mHeight);*/
}
public override void LostFocus()
{
base.LostFocus();
var darkEditWidgetContent = (DarkEditWidgetContent)mEditWidgetContent;
darkEditWidgetContent.CheckRecordScrollTop();
if (darkEditWidgetContent.mScrollToStartOnLostFocus)
HorzScrollTo(0);
}
}
}

View file

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
using Beefy.gfx;
namespace Beefy.theme.dark
{
public class DarkIconButton : ButtonWidget
{
public Image mIcon;
public float mIconOfsX;
public float mIconOfsY;
public override void Draw(Graphics g)
{
base.Draw(g);
g.Draw(mIcon, mIconOfsX, mIconOfsY);
}
}
}

View file

@ -0,0 +1,160 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.gfx;
using Beefy.widgets;
using Beefy.geom;
namespace Beefy.theme.dark
{
public class DarkInfiniteScrollbar : InfiniteScrollbar
{
/*public class DarkThumb : InfiniteScrollbar.Thumb
{
public override void Draw(Graphics g)
{
base.Draw(g);
DarkInfiniteScrollbar scrollbar = (DarkInfiniteScrollbar)mScrollbar;
g.DrawButtonVert(scrollbar.GetImage((mMouseOver || mMouseDown) ? DarkTheme.ImageIdx.ScrollbarThumb : DarkTheme.ImageIdx.ScrollbarThumbOver), 0, 0, mHeight);
}
}*/
public class DarkArrow : InfiniteScrollbar.Arrow
{
public this(bool isBack)
{
mBack = isBack;
}
public override void Draw(Graphics g)
{
base.Draw(g);
DarkInfiniteScrollbar scrollbar = (DarkInfiniteScrollbar)mScrollbar;
if (mMouseOver && mMouseDown)
g.Draw(scrollbar.GetImage(DarkTheme.ImageIdx.ShortButtonDown));
else if (mMouseOver)
g.Draw(scrollbar.GetImage(DarkTheme.ImageIdx.ShortButton));
if (mBack)
{
g.PushScale(1, -1);
g.Draw(scrollbar.GetImage(DarkTheme.ImageIdx.ScrollbarArrow), 0, -DarkTheme.sUnitSize);
g.PopMatrix();
}
else
{
g.Draw(scrollbar.GetImage(DarkTheme.ImageIdx.ScrollbarArrow));
}
}
}
public override void RehupScale(float oldScale, float newScale)
{
mBaseSize = DarkTheme.sUnitSize - 1;
base.RehupScale(oldScale, newScale);
}
public this()
{
mBaseSize = DarkTheme.sUnitSize - 1;
mDualBarSizeOffset = -2;
/*mThumb = new DarkThumb();
mThumb.mScrollbar = this;
AddWidget(mThumb);*/
mStartArrow = new DarkArrow(true);
mStartArrow.mScrollbar = this;
AddWidget(mStartArrow);
mEndArrow = new DarkArrow(false);
mEndArrow.mScrollbar = this;
AddWidget(mEndArrow);
}
public Image GetImage(DarkTheme.ImageIdx image)
{
return DarkTheme.sDarkTheme.GetImage((DarkTheme.ImageIdx)((int32)image + (int32)DarkTheme.ImageIdx.VertScrollbar - (int32)DarkTheme.ImageIdx.Scrollbar));
}
public override Beefy.geom.Rect GetThumbPos()
{
float btnMargin = GS!(18);
float sizeLeft = (mHeight - btnMargin * 2);
float pagePct = 0.125f;
float thumbSize = Math.Min(sizeLeft, Math.Max(GS!(16), sizeLeft * pagePct));
bool wasNeg = mScrollThumbFrac < 0;
float trackPct = (float)Math.Pow(Math.Abs(mScrollThumbFrac) * 1000, 0.5f) / 200;
if (wasNeg)
trackPct = 0.5f - trackPct;
else
trackPct = 0.5f + trackPct;
float thumbPos = Math.Clamp(btnMargin + trackPct*sizeLeft - thumbSize/2, btnMargin, mHeight - btnMargin - thumbSize);
return Rect(0, thumbPos, mWidth, thumbSize);
}
public override void Draw(Graphics g)
{
base.Draw(g);
g.DrawButtonVert(GetImage(DarkTheme.ImageIdx.Scrollbar), 0, 0, mHeight);
let thumbPos = GetThumbPos();
bool isOver = mMouseOver && thumbPos.Contains(mLastMouseX, mLastMouseY);
using (g.PushColor(0x40000000))
{
float y0 = mHeight / 2;
float y1 = thumbPos.mY + thumbPos.mHeight / 2;
g.FillRect(GS!(6), Math.Min(y0, y1), mWidth - GS!(12), Math.Abs(y0 - y1));
}
g.DrawButtonVert(GetImage(isOver ? DarkTheme.ImageIdx.ScrollbarThumb : DarkTheme.ImageIdx.ScrollbarThumbOver), 0, thumbPos.mY, thumbPos.mHeight);
//mThumb.mVisible = true;
//mThumb.Resize(0, btnMargin + thumbPos - (int)(thumbSize*0.5f), mBaseSize, thumbSize);
}
public override float GetAccelFracAt(float dx, float dy)
{
float btnMargin = GS!(18);
float sizeLeft = (mHeight - btnMargin * 2);
float trackSize = sizeLeft - GS!(20);
return dy / trackSize * 2.0f;
}
public override void ResizeContent()
{
mStartArrow.Resize(0, 0, mBaseSize, mBaseSize);
mEndArrow.Resize(0, mHeight - mBaseSize, mBaseSize, mBaseSize);
//float btnMargin = GS!(18);
//float sizeLeft = (mHeight - btnMargin * 2);
/*float pagePct = 0.125f;
float thumbSize = Math.Min(sizeLeft, Math.Max(GS!(12), sizeLeft * pagePct));
float trackSize = sizeLeft + 1; // sizeLeft - ((thumbSize) - (sizeLeft * pagePct)) + 1;
float trackPct = ((float)mScrollThumbFrac + 1.0f) * 0.5f;*/
//float thumbPos = Utils.Lerp(thumbSize * 0.5f, trackSize - (thumbSize * 0.5f), trackPct);
//mThumb.mVisible = true;
//mThumb.Resize(0, btnMargin + thumbPos - (int)(thumbSize*0.5f), mBaseSize, thumbSize);
}
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
ResizeContent();
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,408 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
using Beefy.gfx;
using System.Diagnostics;
namespace Beefy.theme.dark
{
public class DarkMenuItem : MenuItemWidget
{
int32 mSelectedTicks;
int32 mDeselectedTicks;
public this(Menu menuItem) : base(menuItem)
{
if (mMenuItem.mDisabled)
mMouseVisible = false;
}
public override void Draw(Graphics g)
{
base.Draw(g);
if (mMenuItem.mLabel == null)
g.DrawButton(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.MenuSepHorz), GS!(28), 0, mWidth - GS!(32));
else
{
let darkMenuWidget = (DarkMenuWidget)mMenuWidget;
g.SetFont(mMenuItem.mBold ? darkMenuWidget.mBoldFont : darkMenuWidget.mFont);
if (mMenuItem.mDisabled)
{
using (g.PushColor(0xFFA8A8A8))
g.DrawString(mMenuItem.mLabel, GS!(36), 0);
}
else
g.DrawString(mMenuItem.mLabel, GS!(36), 0);
if (mMenuItem.mIconImage != null)
g.Draw(mMenuItem.mIconImage, GS!(4), 0);
}
if (mMenuItem.mItems.Count > 0)
{
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.RightArrow), mWidth - GS!(16), 0);
}
}
public void CloseSubMenu()
{
mSubMenu.Close();
}
void SubMenuClosed(Menu menu, Menu selectedItem)
{
mSubMenu.mMenu.mOnMenuClosed.Remove(scope => SubMenuClosed, true);
mSubMenu = null;
if ((!mMouseOver) && (mMenuWidget.mSelectIdx == mIndex))
mMenuWidget.SetSelection(-1);
if (selectedItem != null)
{
mMenuWidget.mItemSelected = (Menu)selectedItem;
mMenuWidget.Close();
}
}
public void OpenSubMenu(bool setFocus)
{
if (mWidgetWindow.mHasClosed)
return;
mMenuWidget.mOpeningSubMenu = true;
mSubMenu = new DarkMenuWidget(mMenuItem);
if (setFocus)
mSubMenu.mSelectIdx = 0;
else
mSubMenu.mWindowFlags = .ClientSized | .NoActivate | .DestAlpha | .FakeFocus;
mSubMenu.Init(mWidgetWindow.mRootWidget, mX + mWidth + GS!(10), mY);
mSubMenu.mMenu.mOnMenuClosed.Add(new => SubMenuClosed);
mSubMenu.mParentMenuItemWidget = this;
mMenuWidget.mOpeningSubMenu = false;
}
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
{
base.MouseDown(x, y, btn, btnCount);
if ((mMenuItem.mItems.Count > 0) && (mSubMenu == null))
{
OpenSubMenu(true);
}
}
public override void Update()
{
base.Update();
if (mMenuItem.mItems.Count > 0)
{
if (mIndex == mMenuWidget.mSelectIdx)
{
mSelectedTicks++;
mDeselectedTicks = 0;
if ((mSelectedTicks == 10) && (mSubMenu == null))
{
for (DarkMenuItem item in mMenuWidget.mItemWidgets)
{
if ((item != this) && (item.mSubMenu != null))
item.CloseSubMenu();
}
OpenSubMenu(false);
}
}
else
{
mDeselectedTicks++;
mSelectedTicks = 0;
if ((mDeselectedTicks > 20) && (mSubMenu != null))
CloseSubMenu();
}
}
}
public override void Submit()
{
mMenuWidget.mItemSelected = mMenuItem;
mMenuWidget.Close();
if (mMenuItem.mOnMenuItemSelected.HasListeners)
mMenuItem.mOnMenuItemSelected(mMenuItem);
}
public override void MouseUp(float x, float y, int32 btn)
{
if (mMenuItem.mItems.Count > 0)
return;
if ((btn == 0) && (mMouseOver))
{
Submit();
}
base.MouseUp(x, y, btn);
}
}
public class DarkMenuContainer : MenuContainer
{
public float mShowPct = 1.0f;
public float mDrawHeight;
public float mDrawY;
public void DrawSelf(Graphics g)
{
base.Draw(g);
using (g.PushColor(0x80000000))
g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.DropShadow), GS!(2), mDrawY + GS!(2), mWidth - GS!(2), mDrawHeight - GS!(2));
base.Draw(g);
using (g.PushColor(0xFFFFFFFF))
g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Menu), 0, mDrawY, mWidth - GS!(8), mDrawHeight - GS!(8));
}
public override void DrawAll(Graphics g)
{
float toDeg = Math.PI_f * 0.4f;
float toVal = Math.Sin(toDeg);
float curvedOpenPct = Math.Min(1.0f, (float)Math.Sin(mShowPct * toDeg) / toVal + 0.01f);
mDrawHeight = Math.Min(curvedOpenPct * mHeight + GS!(20), mHeight);
if (mReverse)
{
mDrawY = mHeight - mDrawHeight;
}
else
{
mDrawY = 0;
}
using (g.PushClip(0, mDrawY, mWidth, mDrawHeight))
{
DrawSelf(g);
}
using (g.PushClip(0, mDrawY, mWidth, mDrawHeight - GS!(10)))
{
//using (g.PushColor(Color.Get(Math.Min(1.0f, curvedOpenPct * 1.5f))))
base.DrawAll(g);
}
}
public override void Update()
{
base.Update();
var darkMenuWidget = (DarkMenuWidget)mScrollContent;
if (mShowPct < 1.0f)
{
float openSpeed = 0.08f + (0.15f / (darkMenuWidget.mItemWidgets.Count + 1));
mShowPct = Math.Min(1.0f, mShowPct + openSpeed);
MarkDirty();
}
}
}
public class DarkMenuWidget : MenuWidget
{
public float mItemSpacing;
public Font mFont;
public Font mBoldFont;
public bool mHasDrawn;
public this(Menu menu) :
base(menu)
{
mFont = DarkTheme.sDarkTheme.mSmallFont;
mBoldFont = DarkTheme.sDarkTheme.mSmallBoldFont;
mItemSpacing = mFont.GetLineSpacing();
mWindowFlags |= BFWindow.Flags.DestAlpha;
mPopupInsets.Set(GS!(2), GS!(2), GS!(10), GS!(10));
}
public override MenuContainer CreateMenuContainer()
{
DarkMenuContainer menuContainer = new DarkMenuContainer();
menuContainer.mScrollbarInsets.Set(GS!(2), 0, GS!(10), GS!(10));
//menuContainer.mScrollContentInsets = new Insets(0, 0, 0, 0);
return menuContainer;
}
public override MenuItemWidget CreateMenuItemWidget(Menu menuItem)
{
return new DarkMenuItem(menuItem);
}
public override float GetReverseAdjust()
{
return GS!(10);
}
ScrollableWidget GetScrollableParent()
{
ScrollableWidget scrollableWidget = mParent as ScrollableWidget;
if (scrollableWidget != null)
return scrollableWidget;
if (mParent != null)
{
scrollableWidget = mParent.mParent as ScrollableWidget;
if (scrollableWidget != null)
return scrollableWidget;
}
return null;
}
public override void EnsureItemVisible(int itemIdx)
{
base.EnsureItemVisible(itemIdx);
if (itemIdx == -1)
return;
var item = mItemWidgets[itemIdx];
float aX;
float aY;
item.SelfToOtherTranslate(this, 0, 0, out aX, out aY);
float topInsets = 0;
float lineHeight = item.mHeight;
ScrollableWidget scrollableWidget = GetScrollableParent();
if (scrollableWidget == null)
return;
float bottomInset = GS!(8);
if (aY < scrollableWidget.mVertPos.mDest + topInsets)
{
float scrollPos = aY - topInsets;
scrollableWidget.VertScrollTo(scrollPos);
}
else if (aY + lineHeight + bottomInset >= scrollableWidget.mVertPos.mDest + scrollableWidget.mScrollContentContainer.mHeight)
{
float scrollPos = aY + lineHeight + bottomInset - scrollableWidget.mScrollContentContainer.mHeight;
scrollableWidget.VertScrollTo(scrollPos);
}
}
public override void Draw(Graphics g)
{
/*using (g.PushColor(0xFFFF0000))
g.FillRect(0, 0, mWidth, mHeight);*/
float mDrawHeight = mHeight;
g.DrawButtonVert(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.MenuSepVert), GS!(18), GS!(2), mDrawHeight - GS!(4));
g.SetFont(mFont);
for (int32 itemIdx = 0; itemIdx < mItemWidgets.Count; itemIdx++)
{
#unwarn
MenuItemWidget item = (MenuItemWidget)mItemWidgets[itemIdx];
float curY = GS!(2) + mItemSpacing * itemIdx;
if (itemIdx == mSelectIdx)
{
using (g.PushColor(DarkTheme.COLOR_MENU_FOCUSED))
g.DrawButton(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.MenuSelect), GS!(4), curY, mWidth - GS!(6));
}
//if (item.mMenu.mLabel != null)
//g.Draw(DarkTheme.mDarkTheme.GetImage(DarkTheme.ImageIdx.Check), 6, curY + 1);
}
}
public void SetShowPct(float showPct)
{
DarkMenuContainer darkMenuContainer = (DarkMenuContainer)mParent.mParent;
darkMenuContainer.mShowPct = showPct;
}
public override void MouseLeave()
{
base.MouseLeave();
mSelectIdx = -1;
}
public override void ResizeComponents()
{
float maxWidth = 0;
float curY = GS!(2);
for (MenuItemWidget item in mItemWidgets)
{
if (item.mMenuItem.mLabel != null)
maxWidth = Math.Max(maxWidth, mFont.GetWidth(item.mMenuItem.mLabel));
item.Resize(0, curY, mWidth - GS!(8), mItemSpacing);
item.mMouseInsets = new Insets(0, GS!(6), 0, 0);
curY += mItemSpacing;
}
}
public override void CalcSize()
{
float maxWidth = 0;
for (MenuItemWidget item in mItemWidgets)
{
if (item.mMenuItem.mLabel != null)
maxWidth = Math.Max(maxWidth, mFont.GetWidth(item.mMenuItem.mLabel));
}
mWidth = Math.Max(mWidth, GS!(25) + maxWidth + GS!(40));
mHeight = mMenu.mItems.Count * mItemSpacing + GS!(6);
}
public override void Update()
{
base.Update();
}
public override void KeyDown(KeyCode keyCode, bool isRepeat)
{
base.KeyDown(keyCode, isRepeat);
switch (keyCode)
{
case .Right:
if (mSelectIdx != -1)
{
var darkMenuItem = (DarkMenuItem)mItemWidgets[mSelectIdx];
if (darkMenuItem.mSubMenu == null)
{
if (darkMenuItem.mMenuItem.mItems.Count > 0)
darkMenuItem.OpenSubMenu(true);
}
else
{
mOpeningSubMenu = true;
darkMenuItem.mSubMenu.SetFocus();
if (darkMenuItem.mSubMenu.mSelectIdx == -1)
{
darkMenuItem.mSubMenu.mSelectIdx = 0;
darkMenuItem.mSubMenu.MarkDirty();
}
darkMenuItem.mSubMenu.mWidgetWindow.SetForeground();
mOpeningSubMenu = false;
}
}
case .Left:
if (mParentMenuItemWidget != null)
{
var darkMenuItem = (DarkMenuItem)mParentMenuItemWidget;
int32 selectIdx = darkMenuItem.mMenuWidget.mSelectIdx;
darkMenuItem.CloseSubMenu();
darkMenuItem.mMenuWidget.mSelectIdx = selectIdx;
}
default:
}
}
}
}

View file

@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.gfx;
using Beefy.widgets;
namespace Beefy.theme.dark
{
public class DarkScrollbar : Scrollbar
{
public class DarkThumb : Scrollbar.Thumb
{
public override void Draw(Graphics g)
{
base.Draw(g);
DarkScrollbar scrollbar = (DarkScrollbar)mScrollbar;
if (mScrollbar.mOrientation == Scrollbar.Orientation.Horz)
g.DrawButton(scrollbar.GetImage((mMouseOver || mMouseDown) ? DarkTheme.ImageIdx.ScrollbarThumb : DarkTheme.ImageIdx.ScrollbarThumbOver), 0, 0, mWidth);
else
g.DrawButtonVert(scrollbar.GetImage((mMouseOver || mMouseDown) ? DarkTheme.ImageIdx.ScrollbarThumb : DarkTheme.ImageIdx.ScrollbarThumbOver), 0, 0, mHeight);
}
}
public class DarkArrow : Scrollbar.Arrow
{
public this(bool isBack)
{
mBack = isBack;
}
public override void Draw(Graphics g)
{
base.Draw(g);
DarkScrollbar scrollbar = (DarkScrollbar)mScrollbar;
if (mMouseOver && mMouseDown)
g.Draw(scrollbar.GetImage(DarkTheme.ImageIdx.ShortButtonDown));
else if (mMouseOver)
g.Draw(scrollbar.GetImage(DarkTheme.ImageIdx.ShortButton));
if (mBack)
{
if (mScrollbar.mOrientation == Scrollbar.Orientation.Horz)
{
g.PushScale(-1.0f, 1);
g.Draw(scrollbar.GetImage(DarkTheme.ImageIdx.ScrollbarArrow), -DarkTheme.sUnitSize, 0);
g.PopMatrix();
}
else
{
g.PushScale(1, -1);
g.Draw(scrollbar.GetImage(DarkTheme.ImageIdx.ScrollbarArrow), 0, -DarkTheme.sUnitSize);
g.PopMatrix();
}
}
else
{
g.Draw(scrollbar.GetImage(DarkTheme.ImageIdx.ScrollbarArrow));
}
}
}
public this()
{
mBaseSize = DarkTheme.sUnitSize - 1;
mDualBarSizeOffset = -2;
mThumb = new DarkThumb();
mThumb.mScrollbar = this;
AddWidget(mThumb);
mStartArrow = new DarkArrow(true);
mStartArrow.mScrollbar = this;
AddWidget(mStartArrow);
mEndArrow = new DarkArrow(false);
mEndArrow.mScrollbar = this;
AddWidget(mEndArrow);
}
public override void RehupScale(float oldScale, float newScale)
{
mBaseSize = DarkTheme.sUnitSize - 1;
base.RehupScale(oldScale, newScale);
}
public Image GetImage(DarkTheme.ImageIdx image)
{
if (mOrientation == Orientation.Horz)
return DarkTheme.sDarkTheme.GetImage(image);
else
return DarkTheme.sDarkTheme.GetImage((DarkTheme.ImageIdx)((int32)image + (int32)DarkTheme.ImageIdx.VertScrollbar - (int32)DarkTheme.ImageIdx.Scrollbar));
}
public override void Draw(Graphics g)
{
base.Draw(g);
if (mOrientation == Orientation.Horz)
{
g.DrawButton(GetImage(DarkTheme.ImageIdx.Scrollbar), 0, 0, mWidth);
}
else
{
g.DrawButtonVert(GetImage(DarkTheme.ImageIdx.Scrollbar), 0, 0, mHeight);
}
}
public override void DrawAll(Graphics g)
{
if ((mWidth <= 0) || (mHeight <= 0))
return;
base.DrawAll(g);
}
public override double GetContentPosAt(float x, float y)
{
float btnMargin = GS!(18);
float sizeLeft = (mOrientation == Orientation.Horz) ? (mWidth - btnMargin * 2) : (mHeight - btnMargin * 2);
if (mOrientation == Orientation.Horz)
{
float trackSize = sizeLeft - mThumb.mWidth;
float trackPct = (x - btnMargin) / trackSize;
double contentPos = (mContentSize - mPageSize) * trackPct;
return contentPos;
}
else
{
float trackSize = sizeLeft - mThumb.mHeight;
float trackPct = (y - btnMargin) / trackSize;
double contentPos = (mContentSize - mPageSize) * trackPct;
return contentPos;
}
}
public override void ResizeContent()
{
mStartArrow.Resize(0, 0, mBaseSize, mBaseSize);
if (mOrientation == Orientation.Horz)
mEndArrow.Resize(mWidth - mBaseSize, 0, mBaseSize, mBaseSize);
else
mEndArrow.Resize(0, mHeight - mBaseSize, mBaseSize, mBaseSize);
float btnMargin = GS!(18);
float sizeLeft = (mOrientation == Orientation.Horz) ? (mWidth - btnMargin * 2) : (mHeight - btnMargin * 2);
if ((mPageSize < mContentSize) && (mContentSize > 0))
{
double pagePct = mPageSize / mContentSize;
mThumb.mVisible = true;
if (sizeLeft >= GS!(12))
{
mThumb.mVisible = true;
mStartArrow.mVisible = true;
mEndArrow.mVisible = true;
}
else
{
mThumb.mVisible = false;
mStartArrow.mVisible = false;
mEndArrow.mVisible = false;
/*sizeLeft = 0;
sizeLeft = (mOrientation == Orientation.Horz) ? (mWidth) : (mHeight);
btnMargin = 0;*/
}
double thumbSize = Math.Max(Math.Round(Math.Min(sizeLeft, Math.Max(GS!(12), sizeLeft * pagePct))), 0);
double trackSize = Math.Max(sizeLeft - ((thumbSize) - (sizeLeft * pagePct)) + 1, 0);
if (mOrientation == Orientation.Horz)
mThumb.Resize((float)(btnMargin + (float)Math.Round(mContentPos / mContentSize * trackSize)), 0, (float)thumbSize, mBaseSize);
else
mThumb.Resize(0, (float)(btnMargin + (float)Math.Round(mContentPos / mContentSize * trackSize)), mBaseSize, (float)thumbSize);
}
else
{
mThumb.mVisible = false;
}
}
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
ResizeContent();
}
}
}

View file

@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy;
using Beefy.widgets;
using Beefy.events;
using Beefy.gfx;
namespace Beefy.theme.dark
{
public class DarkSmartEdit : Widget
{
public String mText;
public bool mAllowEdit = true;
public Object mValue;
public List<Widget> mMoveWidgets;
public Action<DarkSmartEdit> mValueChangedAction;
bool mCancelingEdit;
float mMouseDownX;
float mMouseDownY;
Object mMouseDownValue;
bool mDidDragEdit;
EditWidget mCurEditWidget;
public void SetValue(float value)
{
mValue = value;
mText.AppendF("{0:0.0}", value);
UpdateWidth();
}
public void SetValue(String value)
{
mValue = value;
mText = value;
UpdateWidth();
}
public void SetDisplay(String value)
{
mText = value;
UpdateWidth();
}
public void NudgeMoveWidgets(float offset)
{
if (mMoveWidgets != null)
{
for (Widget moveWidget in mMoveWidgets)
moveWidget.mX += offset;
}
}
void UpdateWidth()
{
float newWidth;
if (mCurEditWidget != null)
newWidth = mCurEditWidget.mWidth + 2;
else
newWidth = DarkTheme.sDarkTheme.mSmallFont.GetWidth(mText);
float adjust = newWidth - mWidth;
NudgeMoveWidgets(adjust);
mWidth = newWidth;
}
public override void Draw(Graphics g)
{
base.Draw(g);
if (mText == null)
return;
g.SetFont(DarkTheme.sDarkTheme.mSmallFont);
if ((mMouseDown) && (mMouseDownValue is float))
{
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.LeftArrowDisabled), -mX - 11, 0);
float endX = mWidth;
if (mMoveWidgets != null)
endX = mMoveWidgets[mMoveWidgets.Count - 1].mX + mMoveWidgets[mMoveWidgets.Count - 1].mWidth - mX;
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.RightArrowDisabled), endX - 5, 0);
}
using (g.PushColor(0xFFCC9600))
g.DrawString(mText, 0, 0);
}
void HandleEditLostFocus(Widget widget)
{
EditWidget editWidget = (EditWidget)widget;
editWidget.mOnLostFocus.Remove(scope => HandleEditLostFocus, true);
editWidget.mOnSubmit.Remove(scope => HandleEditSubmit, true);
editWidget.mOnCancel.Remove(scope => HandleEditCancel, true);
if (!mCancelingEdit)
{
mText.Clear();
editWidget.GetText(mText);
if (mValue is float)
{
float aValue = 0;
aValue = float.Parse(mText);
SetValue(aValue);
if (mValueChangedAction != null)
mValueChangedAction(this);
}
}
editWidget.RemoveSelf();
mCurEditWidget = null;
UpdateWidth();
}
void HandleEditCancel(EditEvent theEvent)
{
mCancelingEdit = true;
HandleEditLostFocus((EditWidget)theEvent.mSender);
}
void HandleEditSubmit(EditEvent theEvent)
{
HandleEditLostFocus((EditWidget)theEvent.mSender);
}
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
{
base.MouseDown(x, y, btn, btnCount);
mMouseDownX = x;
mMouseDownY = y;
mMouseDownValue = mValue;
mDidDragEdit = false;
}
public override void MouseMove(float x, float y)
{
base.MouseMove(x, y);
if (mMouseDown)
{
if (mMouseDownValue is float)
{
float delta = (float)Math.Round(x - mMouseDownX + y - mMouseDownY);
// First drag must be at least 5 pixels to avoid accidentally dragging when trying to click
if ((mDidDragEdit) || (Math.Abs(delta) >= 4))
{
mDidDragEdit = true;
float aValue = (float)mMouseDownValue + delta;
SetValue(aValue);
if (mValueChangedAction != null)
mValueChangedAction(this);
}
}
}
}
public override void MouseUp(float x, float y, int32 btn)
{
base.MouseUp(x, y, btn);
if ((mMouseOver) && (!mDidDragEdit) && (mValue != null))
{
mCancelingEdit = false;
EditWidget editWidget = new DarkEditWidget();
String numString = scope String();
numString.AppendF("{0}", mValue);
editWidget.SetText(numString);
editWidget.Content.SelectAll();
float aX;
float aY;
SelfToParentTranslate(0, 0, out aX, out aY);
float width = mWidth + 8;
editWidget.Resize(aX, aY, width, 20);
mParent.AddWidget(editWidget);
editWidget.mOnLostFocus.Add(new => HandleEditLostFocus);
editWidget.mOnSubmit.Add(new => HandleEditSubmit);
editWidget.mOnCancel.Add(new => HandleEditCancel);
editWidget.SetFocus();
mCurEditWidget = editWidget;
UpdateWidth();
}
}
}
}

View file

@ -0,0 +1,755 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
using Beefy.gfx;
using Beefy.events;
using System.Diagnostics;
namespace Beefy.theme.dark
{
public class DarkTabbedView : TabbedView
{
public DarkTabEnd mTabEnd;
public DarkTabButton mRightTab; // Shows between tabs and tabEnd
public float mLeftObscure;
float mAllowRightSpace;
float cMinTabSize = 5.0f;
public class DarkTabButtonClose : ButtonWidget
{
public override void Draw(Graphics g)
{
base.Draw(g);
if (mMouseOver)
{
using (g.PushColor(mMouseDown ? 0xFFFF0000 : Color.White))
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.CloseOver), GS!(-4), GS!(-4));
}
else
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Close), GS!(-4), GS!(-4));
}
public override void MouseClicked(float x, float y, int32 btn)
{
base.MouseClicked(x, y, btn);
var tabButton = (DarkTabButton)mParent;
if (tabButton.mCloseClickedEvent.HasListeners)
tabButton.mCloseClickedEvent();
}
}
public class DarkTabButton : TabbedView.TabButton
{
public Action mForceCloseEvent;
public DarkTabButtonClose mCloseButton;
public bool mIsEndTab;
public bool mIsRightTab;
public float mObscuredDir; // <0 = left, >0 = right
public uint32 mTextColor = Color.White;
public float mTabWidthOffset = 30;
public this(bool isEnd = false)
{
mContentInsets.Set(0, GS!(1), GS!(1), GS!(1));
mIsEndTab = isEnd;
if (!mIsEndTab)
{
mCloseButton = new DarkTabButtonClose();
AddWidget(mCloseButton);
}
mDragHelper.mMinDownTicks = 15;
mDragHelper.mTriggerDist = GS!(2);
}
public override void RehupScale(float oldScale, float newScale)
{
base.RehupScale(oldScale, newScale);
mContentInsets.Set(0, GS!(1), GS!(1), GS!(1));
mDragHelper.mTriggerDist = GS!(2);
if (mLabel != null)
mWantWidth = DarkTheme.sDarkTheme.mSmallFont.GetWidth(mLabel) + GS!(mTabWidthOffset);
//mHeight = DarkTheme.sUnitSize;
}
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
{
base.MouseDown(x, y, btn, btnCount);
mDragHelper.mAllowDrag = mObscuredDir == 0;
}
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
if (mCloseButton != null)
mCloseButton.Resize(mWidth - GS!(13), GS!(4), GS!(12), GS!(12));
}
public override void Draw(Graphics g)
{
base.Draw(g);
if (mIsEndTab)
return;
/*float drawWidth = mDrawWidth;
if (drawWidth == 0)
drawWidth = mWidth;*/
float drawWidth = mWidth;
Image image = null;
if (mIsActive)
image = (mMouseOver || mMouseDown) ? DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.TabActiveOver] : DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.TabActive];
else
image = ((!mIsEndTab) && (mMouseOver || mMouseDown)) ? DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.TabInactiveOver] : DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.TabInactive];
g.DrawButton(image, 0, 0, drawWidth + 1);
if ((mIsActive) && (DarkTheme.sScale != 1.0f))
{
// When scaling, we can end up with a subpixel we don't want
//using (g.PushColor(0xFFFF0000))
g.DrawButton(DarkTheme.sDarkTheme.mWindowTopImage, GS!(2), (float)Math.Ceiling(DarkTheme.sScale * (20)) - 1, drawWidth - GS!(4));
}
g.SetFont(DarkTheme.sDarkTheme.mSmallFont);
if ((mLabel != null) && (drawWidth > GS!(16)))
{
//using (g.PushColor(((DarkTabbedView)mParent).mTextColor))
using (g.PushColor(mTextColor))
{
float textWidth = g.mFont.GetWidth(mLabel);
float useWidth = mWidth - GS!(12)*2;
if (textWidth < useWidth)
g.DrawString(mLabel, GS!(9) + (useWidth - textWidth)/2, 0, .Left, useWidth, .Truncate);
else
g.DrawString(mLabel, GS!(12), 0, .Left, useWidth, .Truncate);
}
}
}
public override void DrawDockPreview(Graphics g)
{
using (g.PushTranslate(-mX - mDragHelper.mMouseDownX, -mY - mDragHelper.mMouseDownY))
{
if (IsTotalWindowContent())
((DarkTabbedView)mTabbedView).DrawDockPreview(g);
else
((DarkTabbedView)mTabbedView).DrawDockPreview(g, this);
}
}
}
public class DarkTabDock : ICustomDock
{
public TabbedView mTabbedView;
public bool mAlreadyContains;
public this(TabbedView tabbedView, bool alreadyContains)
{
mTabbedView = tabbedView;
mAlreadyContains = alreadyContains;
}
public void Draw(Graphics g)
{
if (!mAlreadyContains)
{
using (g.PushColor(0x60FFFFFF))
g.DrawBox(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.WhiteCircle], mTabbedView.mX - GS!(6), mTabbedView.mY - GS!(6), mTabbedView.mWidth + GS!(6) * 2, GS!(32));
}
}
public void Dock(IDockable dockable)
{
dockable.Dock(mTabbedView.mParentDockingFrame, mTabbedView, DockingFrame.WidgetAlign.Inside);
}
}
public class DarkTabMenuButton : ButtonWidget
{
public override void Draw(Graphics g)
{
base.Draw(g);
if (mMouseOver || mMouseDown)
{
using (g.PushColor(0xFFF7A900))
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.DropMenuButton), GS!(-4), GS!(-4));
}
else
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.DropMenuButton), GS!(-4), GS!(-4));
}
}
public class DarkTabEnd : DarkTabButton
{
public DarkTabMenuButton mMenuButton;
public int32 mMenuClosedTick;
public this()
: base(true)
{
mMenuButton = new DarkTabMenuButton();
AddWidget(mMenuButton);
mMenuButton.mOnMouseDown.Add(new => MenuClicked);
}
void ShowMenu(float x, float y)
{
Menu menu = new Menu();
/*menu.AddItem("Item 1");
menu.AddItem("Item 2");
menu.AddItem();
menu.AddItem("Item 3");*/
var menuItem = menu.AddItem("Frame Type");
var subItem = menuItem.AddItem("Static");
subItem.mOnMenuItemSelected.Add(new (evt) =>
{
mTabbedView.mIsFillWidget = false;
mTabbedView.mSizePriority = 0;
mTabbedView.mRequestedWidth = mTabbedView.mWidth;
mTabbedView.GetRootDockingFrame().Rehup();
mTabbedView.GetRootDockingFrame().ResizeContent();
});
if (!mTabbedView.mIsFillWidget)
subItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
subItem = menuItem.AddItem("Documents");
subItem.mOnMenuItemSelected.Add(new (evt) =>
{
/*for (var tabSibling in mTabbedView.mParentDockingFrame.mDockedWidgets)
{
tabSibling.mSizePriority = 0;
if (mTabbedView.mParentDockingFrame.mSplitType == .Horz)
tabSibling.mRequestedWidth = tabSibling.mWidth;
else
tabSibling.mRequestedHeight = tabSibling.mHeight;
}*/
mTabbedView.mIsFillWidget = true;
mTabbedView.GetRootDockingFrame().Rehup();
mTabbedView.GetRootDockingFrame().ResizeContent();
});
if (mTabbedView.mIsFillWidget)
subItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
menuItem = menu.AddItem("Permanent");
if (!mTabbedView.mAutoClose)
menuItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
menuItem.mOnMenuItemSelected.Add(new (evt) =>
{
mTabbedView.mAutoClose = !mTabbedView.mAutoClose;
});
menuItem = menu.AddItem("Close");
menuItem.mOnMenuItemSelected.Add(new (evt) =>
{
let prevAutoClose = mTabbedView.mAutoClose;
mTabbedView.mAutoClose = true;
var tabs = scope List<TabButton>();
for (var tab in mTabbedView.mTabs)
tabs.Add(tab);
if (tabs.IsEmpty)
{
if (var dockingFrame = mTabbedView.mParent as DockingFrame)
{
dockingFrame.RemoveDockedWidget(mTabbedView);
BFApp.sApp.DeferDelete(mTabbedView);
}
}
else
{
for (var tab in tabs)
tab.mCloseClickedEvent();
}
mTabbedView.mAutoClose = prevAutoClose;
});
menu.AddItem();
for (var tab in mTabbedView.mTabs)
{
menuItem = menu.AddItem(tab.mLabel);
menuItem.mOnMenuItemSelected.Add(new (selMenuItem) =>
{
TabbedView.TabButton activateTab = tab;
activateTab.Activate();
});
}
if (mTabbedView.mPopulateMenuEvent != null)
mTabbedView.mPopulateMenuEvent(menu);
if (menu.mItems.Count > 0)
{
MenuWidget menuWidget = DarkTheme.sDarkTheme.CreateMenuWidget(menu);
menuWidget.Init(this, x, y, true);
menuWidget.mWidgetWindow.mOnWindowClosed.Add(new => MenuClosed);
}
else
delete menu;
}
void MenuClicked(MouseEvent theEvent)
{
if (mMenuClosedTick != mUpdateCnt)
{
ShowMenu(mMenuButton.mX + GS!(14), mMenuButton.mY + GS!(6));
}
}
void MenuClosed(BFWindow window)
{
mMenuClosedTick = mUpdateCnt;
}
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
{
base.MouseDown(x, y, btn, btnCount);
if (btn == 1)
ShowMenu(x, y);
}
public override void Dock(DockingFrame frame, DockedWidget refWidget, DockingFrame.WidgetAlign align)
{
mTabbedView.Dock(frame, refWidget, align);
}
public override void Draw(Graphics g)
{
base.Draw(g);
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Grabber), mWidth - DarkTheme.sUnitSize, 0);
/*if (mMouseOver)
{
using (g.PushColor(0x80FF0000))
g.FillRect(0, 0, mWidth, mHeight);
}*/
}
public override void Activate(bool setFocus)
{
}
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
if (mMenuButton != null)
mMenuButton.Resize(mWidth - GS!(30), GS!(3), GS!(14), GS!(12));
}
public override bool IsTotalWindowContent()
{
return (mTabbedView.mParentDockingFrame.mParentDockingFrame == null) &&
(mTabbedView.mParentDockingFrame.GetDockedWindowCount() == 1);
}
}
public this(SharedData sharedData = null) : base(sharedData)
{
mTabHeight = DarkTheme.sUnitSize;
mTabEnd = new DarkTabEnd();
mTabEnd.mTabbedView = this;
AddWidget(mTabEnd);
Object obj = this;
obj.[Friend]GCMarkMembers();
}
public ~this()
{
if (mRightTab != null)
{
Widget.RemoveAndDelete(mRightTab);
mRightTab = null;
}
}
public override void RehupScale(float oldScale, float newScale)
{
base.RehupScale(oldScale, newScale);
mTabHeight = DarkTheme.sUnitSize;
}
public override int GetTabCount()
{
int tabCount = base.GetTabCount();
if (mRightTab != null)
tabCount++;
return tabCount;
}
public override void WithTabs(Action<TabbedView.TabButton> func)
{
for (var tab in mTabs)
func(tab);
if (mRightTab != null)
func(mRightTab);
}
public override TabButton AddTab(String label, float width, Widget content, bool ownsContent)
{
float useWidth = width;
if (useWidth == 0)
useWidth = DarkTheme.sDarkTheme.mSmallFont.GetWidth(label) + GS!(30);
return base.AddTab(label, useWidth, content, ownsContent);
}
public override void RemoveTab(TabButton tabButton, bool deleteTab = true)
{
if (mRightTab == tabButton)
SetRightTab(null, deleteTab);
else
base.RemoveTab(tabButton, deleteTab);
}
protected override TabButton CreateTabButton()
{
return new DarkTabButton();
}
public override void Draw(Graphics g)
{
base.Draw(g);
using (g.PushColor(0x80FFFFFF))
g.DrawButton(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.TabInactive], 0, 0, mWidth);
g.DrawBox(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.Window], 0, mTabHeight - GS!(2), mWidth, mHeight - mTabHeight + GS!(2));
}
protected override void ResizeTabs(bool immediate)
{
if (mWidgetWindow == null)
return;
List<Widget> afterTabWidgets = scope List<Widget>(8);
// Remove tabs, then them back
for (int childIdx = mChildWidgets.Count - 1; childIdx >= 0; childIdx--)
{
var widget = mChildWidgets[childIdx];
if ((widget is TabButton) /*&& (widget != mTabEnd) && (widget != mRightTab)*/)
{
mChildWidgets.RemoveAt(childIdx);
}
else
{
afterTabWidgets.Add(widget);
mChildWidgets.RemoveAt(childIdx);
}
}
if (mRightTab != null)
mRightTab.mWidth = mRightTab.mWantWidth;
float maxAreaWidth = mWidth - GS!(36);
if (mRightTab != null)
maxAreaWidth -= mRightTab.mWidth + GS!(2);
float leftObscure = mLeftObscure;
int32 maxStackedDocs = 16;
float curX = 0;
int32 tabIdx = 0;
// Before active tab button
bool foundActiveTab = false;
for (tabIdx = 0; tabIdx < mTabs.Count; tabIdx++)
{
var tabButton = (DarkTabButton)mTabs[tabIdx];
float useWidth = tabButton.mWantWidth;
if (curX + useWidth > mWidth - GS!(36))
useWidth = Math.Max(mWidth - GS!(36), 0);
useWidth = (float)Math.Round(useWidth);
tabButton.Resize(curX, tabButton.mY, useWidth, tabButton.mHeight);
//float offset = tabIdx - leftObscure;
float widthSubtract = Math.Max(0, leftObscure);
leftObscure -= tabButton.mWantWidth;
float showWidth = 0;
tabButton.mVisible = leftObscure < 1536.0f;
if (tabButton.mVisible)
showWidth = (float)Math.Round(Math.Max(tabButton.mWantWidth - widthSubtract, GS!(cMinTabSize)));
if (widthSubtract > 0)
{
tabButton.mObscuredDir = -widthSubtract;
}
else
tabButton.mObscuredDir = 0;
if (mTabs.Count > 1)
{
// Truncate drawing so we don't have the right side of the button showing from under the right side of the
// next tab (if next tab is shorter and on top of the previous one)
if (tabIdx < mTabs.Count - 1)
{
tabButton.mWidth = (float)Math.Round(Math.Min(tabButton.mWantWidth, showWidth + GS!(8)));
tabButton.mCloseButton.mVisible = tabButton.mWidth >= tabButton.mWantWidth;
}
else
{
tabButton.mWidth = (float)Math.Round(tabButton.mWantWidth);
tabButton.mCloseButton.mVisible = true;
}
}
mChildWidgets.Add(tabButton);
float pixelsOffscreen = curX + tabButton.mWidth + Math.Min(maxStackedDocs, mTabs.Count - tabIdx - 1) * GS!(cMinTabSize) - maxAreaWidth;
curX += showWidth;
if ((pixelsOffscreen > 0) && (leftObscure <= 0))
{
if (tabButton.mObscuredDir != 0)
{
tabButton.mObscuredDir = 0;
}
else
{
tabButton.mObscuredDir = pixelsOffscreen;
}
}
tabButton.mVisible = true;
foundActiveTab |= tabButton.mIsActive;
if ((mRightTab != null) && (mRightTab.mIsActive))
foundActiveTab = true;
if ((foundActiveTab) && (tabButton.mObscuredDir >= -2))
{
tabIdx++;
break;
}
}
int32 numRightObscuredButtons = 0;
bool foundEnd = false;
float stackedSize = 0;
int selInsertPos = mChildWidgets.Count;
// After the active button
for (; tabIdx < mTabs.Count; tabIdx++)
{
var tabButton = (DarkTabButton)mTabs[tabIdx];
float showWidth = (float)Math.Round(tabButton.mWantWidth);
if (!foundEnd)
stackedSize = Math.Min(maxStackedDocs, mTabs.Count - tabIdx - 1) * GS!(cMinTabSize);
float maxX = (float)Math.Round(maxAreaWidth - showWidth - stackedSize);
tabButton.mWidth = showWidth;
tabButton.mVisible = true;
if (maxX < curX)
{
curX = maxX;
tabButton.mObscuredDir = 1;
if (numRightObscuredButtons > maxStackedDocs)
{
//int a = 0;
tabButton.mVisible = false;
}
numRightObscuredButtons++;
foundEnd = true;
stackedSize -= GS!(cMinTabSize);
var prevButton = (DarkTabbedView.DarkTabButton)mTabs[tabIdx - 1];
if (prevButton.mWidth < prevButton.mWantWidth - 1)
{
// Super-squished, fix for small label, make small enough that the label doesn't draw
prevButton.mWidth = GS!(16);
}
}
else
tabButton.mObscuredDir = 0;
tabButton.mCloseButton.mVisible = tabButton.mObscuredDir == 0;
mChildWidgets.Insert(0, tabButton);
tabButton.Resize(curX, tabButton.mY, tabButton.mWidth, tabButton.mHeight);
curX += showWidth;
}
if ((curX < maxAreaWidth) && (mLeftObscure > 0))
{
var activeTab = (DarkTabButton)GetActiveTab();
float pixelsLeft = maxAreaWidth - curX;
if ((activeTab != null) && (pixelsLeft > mAllowRightSpace))
activeTab.mObscuredDir = -pixelsLeft;
}
float tabX = 0;
if (mTabs.Count > 0)
tabX = Math.Min(mWidth - GS!(36), mTabs[mTabs.Count - 1].mX + mTabs[mTabs.Count - 1].mWidth);
if (mRightTab != null)
{
if (mRightTab.mIsActive)
selInsertPos = mChildWidgets.Count;
//tabX = Math.Min(tabX, maxAreaWidth);
//tabX += 2;
mRightTab.Resize(maxAreaWidth, 0, mRightTab.mWidth, DarkTheme.sUnitSize);
//tabX += mRightTab.mWidth;
mChildWidgets.Insert(selInsertPos, mRightTab);
}
for (int afterTabIdx = afterTabWidgets.Count - 1; afterTabIdx >= 0; afterTabIdx--)
{
mChildWidgets.Add(afterTabWidgets[afterTabIdx]);
}
mTabEnd.Resize(tabX, 0, mWidth - tabX - GS!(1), DarkTheme.sUnitSize);
mChildWidgets.Insert(selInsertPos, mTabEnd);
mNeedResizeTabs = false;
if (immediate)
UpdateTabView(true);
}
public void SetRightTab(DarkTabButton tabButton, bool deletePrev = true)
{
bool hadFocus = mWidgetWindow.mFocusWidget != null;
bool needsNewFocus = false;
mNeedResizeTabs = true;
if (mRightTab != null)
{
if (mRightTab.mIsActive)
{
needsNewFocus = true;
mRightTab.Deactivate();
}
mRightTab.mIsRightTab = false;
RemoveWidget(mRightTab);
mTabs.Remove(mRightTab);
/*if ((GetActiveTab() == null) && (mTabs.Count > 0))
mTabs[0].Activate((hadFocus) && (mWidgetWindow.mFocusWidget == null));*/
mRightTab.mTabbedView = null;
if (deletePrev)
BFApp.sApp.DeferDelete(mRightTab);
}
mRightTab = tabButton;
if (tabButton != null)
{
tabButton.mIsRightTab = true;
tabButton.mTabbedView = this;
AddWidgetAtIndex(0, mRightTab);
if (needsNewFocus)
tabButton.Activate((hadFocus) && (mWidgetWindow.mFocusWidget == null));
}
else
{
if (mTabs.Count > 0)
mTabs[0].Activate((hadFocus) && (mWidgetWindow.mFocusWidget == null));
}
}
void UpdateTabView(bool immediate)
{
var darkTabButton = (DarkTabButton)GetActiveTab();
if (darkTabButton != null)
{
if (darkTabButton.mObscuredDir != 0)
{
float obscureAdd = darkTabButton.mObscuredDir * 0.2f;
obscureAdd += Math.Sign(obscureAdd) * 1.5f;
if ((Math.Abs(obscureAdd) > Math.Abs(darkTabButton.mObscuredDir)) || (immediate))
{
obscureAdd = darkTabButton.mObscuredDir;
darkTabButton.mObscuredDir = 0;
}
mLeftObscure = Math.Max(0, mLeftObscure + obscureAdd);
if (mLeftObscure == 0)
darkTabButton.mObscuredDir = 0;
if (obscureAdd > 0)
mAllowRightSpace = GS!(cMinTabSize) + 0.1f; // To remove oscillations
ResizeTabs(false);
mAllowRightSpace = 0;
MarkDirty();
}
}
}
public override void Update()
{
base.Update();
UpdateTabView(false);
}
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
ResizeTabs(true);
}
public override ICustomDock GetCustomDock(IDockable dockable, float x, float y)
{
if (y < mTabHeight)
{
bool alreadyContains = false;
var tabButton = dockable as TabButton;
if ((tabButton != null) && (mTabs.Contains(tabButton)))
{
// Resizing our own tabs...
// We do this twice so it switches back if our new mouse location doesn't contain ourselves.
// This avoids rapidly switching position back and foreth on edges of unequally-sized tabs
for (int32 pass = 0; pass < 2; pass++)
{
TabButton foundTab = FindWidgetByCoords(x, y) as TabButton;
if ((foundTab != null) && (foundTab != dockable))
{
int32 foundIndex = mTabs.IndexOf(foundTab);
if (foundIndex != -1)
{
int32 dragIndex = mTabs.IndexOf((TabButton)dockable);
mTabs[dragIndex] = mTabs[foundIndex];
mTabs[foundIndex] = (TabButton)dockable;
ResizeTabs(false);
}
}
}
alreadyContains = true;
}
return new DarkTabDock(this, alreadyContains);
}
return null;
}
public virtual void DrawDockPreview(Graphics g, TabButton tabButton)
{
using (g.PushColor(0x80FFFFFF))
{
g.DrawBox(DarkTheme.sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.Window], 0, mTabHeight - GS!(2), mWidth, mHeight - mTabHeight + GS!(2));
using (g.PushTranslate(tabButton.mX, tabButton.mY))
tabButton.Draw(g);
}
}
}
}

View file

@ -0,0 +1,530 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.widgets;
using Beefy.gfx;
namespace Beefy.theme.dark
{
public class DarkTheme : ThemeFactory
{
public enum ImageIdx
{
Bkg,
Window,
Dots,
RadioOn,
RadioOff,
MainBtnUp,
MainBtnDown,
BtnUp,
BtnOver,
BtnDown,
Seperator,
TabActive,
TabActiveOver,
TabInactive,
TabInactiveOver,
EditBox,
Checkbox,
CheckboxOver,
CheckboxDown,
Check,
Close,
CloseOver,
DownArrow,
GlowDot,
ArrowRight,
WhiteCircle,
DropMenuButton,
ListViewHeader,
ListViewSortArrow,
Outline,
Scrollbar,
ScrollbarThumbOver,
ScrollbarThumb,
ScrollbarArrow,
ShortButton,
ShortButtonDown,
VertScrollbar,
VertScrollbarThumbOver,
VertScrollbarThumb,
VertScrollbarArrow,
VertShortButton,
VertShortButtonDown,
Grabber,
DropShadow,
Menu,
MenuSepVert,
MenuSepHorz,
MenuSelect,
TreeArrow,
UIPointer,
UIImage,
UIComposition,
UILabel,
UIButton,
UIEdit,
UICombobox,
UICheckbox,
UIRadioButton,
UIListView,
UITabView,
EditCorners,
EditCircle,
EditPathNode,
EditPathNodeSelected,
EditAnchor,
UIBone,
UIBoneJoint,
VisibleIcon,
LockIcon,
LeftArrow,
KeyframeMakeOff,
RightArrow,
LeftArrowDisabled,
KeyframeMakeOn,
RightArrowDisabled,
TimelineSelector,
TimelineBracket,
KeyframeOff,
KeyframeOn,
LinkedIcon,
CheckboxLarge,
ComboBox,
ComboEnd,
ComboSelectedIcon,
LinePointer,
RedDot,
Document,
ReturnPointer,
RefreshArrows,
MoveDownArrow,
IconObject,
IconObjectDeleted,
IconObjectAppend,
IconObjectStack,
IconValue,
IconPointer,
IconType,
IconError,
IconBookmark,
ProjectFolder,
Project,
ArrowMoveDown,
Workspace,
MemoryArrowSingle,
MemoryArrowDoubleTop,
MemoryArrowDoubleBottom,
MemoryArrowTripleTop,
MemoryArrowTripleMiddle,
MemoryArrowTripleBottom,
MemoryArrowRainbow,
Namespace,
ResizeGrabber,
AsmArrow,
AsmArrowRev,
AsmArrowShadow,
MenuNonFocusSelect,
StepFilter,
WaitSegment,
FindCaseSensitive,
FindWholeWord,
RedDotUnbound,
MoreInfo,
Interface,
Property,
Field,
Method,
Variable,
Constant,
Type_ValueType,
Type_Class,
LinePointer_Prev,
LinePointer_Opt,
RedDotEx,
RedDotExUnbound,
RedDotDisabled,
RedDotExDisabled,
RedDotRunToCursor,
GotoButton,
YesJmp,
NoJmp,
WhiteBox,
UpDownArrows,
EventInfo,
WaitBar,
HiliteOutline,
HiliteOutlineThin,
IconPayloadEnum,
StepFilteredDefault,
ThreadBreakpointMatch,
ThreadBreakpointNoMatch,
ThreadBreakpointUnbound,
Search,
CheckIndeterminate,
COUNT
};
public const uint32 COLOR_WINDOW = 0xFF595959;
public const uint32 COLOR_BKG = 0xFF262626;
public const uint32 COLOR_SELECTED_OUTLINE = 0xFFE6A800;
public const uint32 COLOR_MENU_FOCUSED = 0xFFFFA000;
public const uint32 COLOR_MENU_SELECTED = 0xFFD0A070;
public const uint32 COLOR_TIMELINE_SEP = 0xFF202020;
public const uint32 COLOR_TIMELINE_RULE = 0xFF4A4A4A;
public static float sScale = 1.0f;
public static int32 sSrcImgScale = 1;
public static int32 sSrcImgUnitSize = 20;
public static int32 sUnitSize = 20;
public static DarkTheme sDarkTheme ~ delete _;
Image mThemeImage ~ delete _;
public Image[] mImages = new Image[(int32) ImageIdx.COUNT] ~ delete _;
public Font mHeaderFont ~ delete _;
public Font mSmallFont ~ delete _;
public Font mSmallBoldFont ~ delete _;
public Image mTreeArrow ~ delete _;
public Image mWindowTopImage ~ delete _;
public Image mIconWarning ~ delete _;
public Image mIconError ~ delete _;
public static DesignToolboxEntry[] GetDesignToolboxEntries()
{
Get();
DesignToolboxEntry [] entries = new DesignToolboxEntry []
{
new DesignToolboxEntry("ButtonWidget", typeof(DarkButton), sDarkTheme.mImages[(int32)ImageIdx.UIButton]),
new DesignToolboxEntry("LabelWidget", null, sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.UILabel]),
new DesignToolboxEntry("EditWidget", typeof(DarkEditWidget), sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.UIEdit]),
new DesignToolboxEntry("ComboBox", null, sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.UICombobox]),
new DesignToolboxEntry("CheckBox", typeof(DarkCheckBox), sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.UICheckbox]),
new DesignToolboxEntry("RadioButton", null, sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.UIRadioButton]),
new DesignToolboxEntry("ListView", typeof(DarkListView), sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.UIListView]),
new DesignToolboxEntry("TabView", typeof(DarkTabbedView), sDarkTheme.mImages[(int32)DarkTheme.ImageIdx.UITabView])
};
for (DesignToolboxEntry entry in entries)
entry.mGroupName = "DarkTheme";
return entries;
}
public static DarkTheme Get()
{
if (sDarkTheme != null)
return sDarkTheme;
sDarkTheme = new DarkTheme();
sDarkTheme.Init();
return sDarkTheme;
}
public static int GetScaled(int val)
{
return (int)(val * sScale);
}
public static float GetScaled(float val)
{
return (val * sScale);
}
public static void SetScale(float scale)
{
sScale = scale;
sSrcImgScale = (int32)Math.Clamp((int)Math.Ceiling(scale), 1, 4);
if (sSrcImgScale == 3)
sSrcImgScale = 4;
sSrcImgUnitSize = (int32)(20.0f * sSrcImgScale);
sUnitSize = (int32)(sScale * 20);
if (sDarkTheme != null)
sDarkTheme.Rehup();
}
Image LoadSizedImage(StringView baseName)
{
var fileName = scope String();
fileName.Append(BFApp.sApp.mInstallDir, "images/");
fileName.Append(baseName);
if (sSrcImgScale > 1)
fileName.AppendF("_{0}", sSrcImgScale);
fileName.Append(".png");
var image = Image.LoadFromFile(fileName);
image.Scale(GS!(48) / image.mWidth);
return image;
}
public override void Init()
{
sDarkTheme = this;
//SetScale(2);
//String tempStr = scope String();
/*mIconError = Image.LoadFromFile(StringAppend!(tempStr, BFApp.sApp.mInstallDir, "images/IconError.png"));
mIconWarning = Image.LoadFromFile(StringAppend!(tempStr, BFApp.sApp.mInstallDir, "images/IconWarning.png"));*/
for (int32 i = 0; i < (int32)ImageIdx.COUNT; i++)
{
mImages[i] = new Image();
}
mHeaderFont = new Font();
mSmallFont = new Font();
mSmallBoldFont = new Font();
//SetScale(2.2f);
SetScale(sScale);
}
public void Rehup()
{
String tempStr = scope String();
if (mThemeImage != null)
{
delete mIconError;
delete mIconWarning;
delete mThemeImage;
delete mTreeArrow;
delete mWindowTopImage;
}
String uiFileName = null;
switch (sSrcImgScale)
{
case 1:
uiFileName = "DarkUI.png";
case 2:
uiFileName = "DarkUI_2.png";
case 4:
uiFileName = "DarkUI_4.png";
default:
Runtime.FatalError("Invalid scale");
}
mIconError = LoadSizedImage("IconError");
mIconWarning = LoadSizedImage("IconWarning");
mThemeImage = Image.LoadFromFile(scope String..Append(tempStr, BFApp.sApp.mInstallDir, "images/", uiFileName));
for (int32 i = 0; i < (int32)ImageIdx.COUNT; i++)
{
var image = mImages[i];
image.CreateImageSegment(mThemeImage, (i % 20) * sSrcImgUnitSize, (i / 20) * sSrcImgUnitSize, sSrcImgUnitSize, sSrcImgUnitSize);
image.SetDrawSize(sUnitSize, sUnitSize);
}
// Trim off outside pixels
mTreeArrow = mImages[(int32) ImageIdx.TreeArrow].CreateImageSegment(1, 1, DarkTheme.sSrcImgUnitSize - 2, DarkTheme.sSrcImgUnitSize - 2);
mWindowTopImage = mImages[(int32)ImageIdx.Window].CreateImageSegment(2 * DarkTheme.sSrcImgScale, 2 * DarkTheme.sSrcImgScale, 16 * DarkTheme.sSrcImgScale, (int)Math.Ceiling(sScale));
//mIconError.Scale(sScale);
//mIconWarning.Scale(sScale);
mTreeArrow.SetDrawSize((int)(18 * sScale), (int)(18 * sScale));
mHeaderFont.Dispose(true);
/*mHeaderFont.Load(StringAppend!(tempStr, BFApp.sApp.mInstallDir, "fonts/segoeui.ttf"), 11.7f * sScale); //8.8
mHeaderFont.AddAlternate(scope String(BFApp.sApp.mInstallDir, "fonts/segoeui.ttf"), 11.7f * sScale);
mHeaderFont.AddAlternate(scope String(BFApp.sApp.mInstallDir, "fonts/seguisym.ttf"), 11.7f * sScale);
mHeaderFont.AddAlternate(scope String(BFApp.sApp.mInstallDir, "fonts/seguihis.ttf"), 11.7f * sScale);*/
mHeaderFont.Load("Segoe UI", 11.7f * sScale); //8.8
mHeaderFont.AddAlternate("Segoe UI Symbol", 11.7f * sScale);
mHeaderFont.AddAlternate("Segoe UI Historic", 11.7f * sScale);
mHeaderFont.AddAlternate("Segoe UI Emoji", 11.7f * sScale);
mSmallFont.Dispose(true);
mSmallFont.Load("Segoe UI", 12.8f * sScale); // 10.0
mSmallFont.AddAlternate("Segoe UI Symbol", 12.8f * sScale);
mSmallFont.AddAlternate("Segoe UI Historic", 12.8f * sScale);
mSmallFont.AddAlternate("Segoe UI Emoji", 12.8f * sScale);
mSmallBoldFont.Dispose(true);
mSmallBoldFont.Dispose(true);
mSmallBoldFont.Load("Segoe UI Bold", 12.8f * sScale); // 10.0
mSmallBoldFont.AddAlternate("Segoe UI Symbol", 12.8f * sScale);
mSmallBoldFont.AddAlternate("Segoe UI Historic", 12.8f * sScale);
mSmallBoldFont.AddAlternate("Segoe UI Emoji", 12.8f * sScale);
/*mSmallBoldFont.Load(StringAppend!(tempStr, BFApp.sApp.mInstallDir, "fonts/segoeuib.ttf"), 12.8f * sScale); // 10.0
mSmallBoldFont.AddAlternate(scope String(BFApp.sApp.mInstallDir, "fonts/segoeui.ttf"), 12.8f * sScale);
mSmallBoldFont.AddAlternate(scope String(BFApp.sApp.mInstallDir, "fonts/seguisym.ttf"), 12.8f * sScale);
mSmallBoldFont.AddAlternate(scope String(BFApp.sApp.mInstallDir, "fonts/seguihis.ttf"), 12.8f * sScale);*/
}
public override void Update()
{
base.Update();
DarkTooltipManager.UpdateTooltip();
DarkTooltipManager.UpdateMouseover();
}
public ~this()
{
for (var image in mImages)
delete image;
}
public Image GetImage(ImageIdx idx)
{
return mImages[(int32)idx];
}
public override ButtonWidget CreateButton(Widget parent, String label, float x, float y, float width, float height)
{
DarkButton button = new DarkButton();
button.Resize(x, y, width, height);
button.Label = label;
if (parent != null)
parent.AddWidget(button);
return button;
}
public override EditWidget CreateEditWidget(Widget parent, float x = 0, float y = 0, float width = 0, float height = 0)
{
DarkEditWidget editWidget = new DarkEditWidget();
editWidget.Resize(x, y, width, height);
if (parent != null)
parent.AddWidget(editWidget);
return editWidget;
}
public override TabbedView CreateTabbedView(TabbedView.SharedData sharedData, Widget parent, float x, float y, float width, float height)
{
DarkTabbedView tabbedView = new DarkTabbedView(sharedData);
tabbedView.Resize(x, y, width, height);
if (parent != null)
parent.AddWidget(tabbedView);
return tabbedView;
}
public override DockingFrame CreateDockingFrame(DockingFrame parent)
{
DarkDockingFrame dockingFrame = new DarkDockingFrame();
if (parent == null)
dockingFrame.mWindowMargin = 1;
else if (var darkParent = parent as DarkDockingFrame)
{
dockingFrame.mDrawBkg = darkParent.mDrawBkg;
}
return dockingFrame;
}
public override ListView CreateListView()
{
return new DarkListView();
}
public override Scrollbar CreateScrollbar(Scrollbar.Orientation orientation)
{
DarkScrollbar scrollbar = new DarkScrollbar();
scrollbar.mOrientation = orientation;
return scrollbar;
}
public override InfiniteScrollbar CreateInfiniteScrollbar()
{
return new DarkInfiniteScrollbar();
}
public override CheckBox CreateCheckbox(Widget parent, float x = 0, float y = 0, float width = 0, float height = 0)
{
DarkCheckBox checkbox = new DarkCheckBox();
checkbox.Resize(x, y, width, height);
if (parent != null)
parent.AddWidget(checkbox);
return checkbox;
}
public override MenuWidget CreateMenuWidget(Menu menu)
{
return new DarkMenuWidget(menu);
}
public override Dialog CreateDialog(String title = null, String text = null, Image icon = null)
{
return new DarkDialog(title, text, icon);
}
public static bool CheckUnderlineKeyCode(StringView label, KeyCode keyCode)
{
int underlinePos = label.IndexOf('&');
if (underlinePos == -1)
return false;
char32 underlineC = label.GetChar32(underlinePos + 1).0;
underlineC = underlineC.ToUpper;
return ((char32)keyCode == underlineC);
}
public static void DrawUnderlined(Graphics g, StringView str, float x, float y, FontAlign alignment = FontAlign.Left, float width = 0, Beefy.gfx.FontOverflowMode overflowMode = .Overflow)
{
int underlinePos = str.IndexOf('&');
if ((underlinePos != -1) && (underlinePos < str.Length - 1))
{
String label = scope String();
label.Append(str, 0, underlinePos);
float underlineX = g.mFont.GetWidth(label);
char32 underlineC = str.GetChar32(underlinePos + 1).0;
float underlineWidth = g.mFont.GetWidth(underlineC);
FontMetrics fm = .();
label.Append(str, underlinePos + 1);
g.DrawString(label, x, y, alignment, width, overflowMode, &fm);
float drawX;
switch (alignment)
{
case .Centered:
drawX = x + underlineX + (width - fm.mMaxWidth) / 2;
default:
drawX = x + underlineX;
}
g.FillRect(drawX, y + g.mFont.GetAscent() + GS!(1), underlineWidth, (int)GS!(1.2f));
}
else
{
g.DrawString(str, x, y, alignment, width, overflowMode);
}
}
}
static
{
public static mixin GS(int32 val)
{
(int32)(val * DarkTheme.sScale)
}
public static mixin GS(int64 val)
{
(int64)(val * DarkTheme.sScale)
}
public static mixin GS(float val)
{
float fVal = val * DarkTheme.sScale;
fVal
}
}
}

View file

@ -0,0 +1,398 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Beefy;
using Beefy.events;
using Beefy.gfx;
using Beefy.theme.dark;
using Beefy.widgets;
using System.Diagnostics;
using Beefy.geom;
using Beefy.utils;
namespace Beefy.theme.dark
{
public class DarkTooltipContainer : Widget
{
public DarkTooltip mTooltip;
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
mTooltip.Resize(0, GS!(4), width - GS!(DarkTooltip.cShadowSize), height - GS!(DarkTooltip.cShadowSize) - GS!(4));
}
}
public class DarkTooltip : Widget
{
public Event<Action> mCloseEvent ~ _.Dispose();
public Widget mRelWidget;
public Font mFont;
public String mText ~ delete _;
public bool mAllowResize;
public bool mHasClosed;
public Insets mRelWidgetMouseInsets ~ delete _;
public bool mAllowMouseInsideSelf;
public const float cShadowSize = 8;
public this(String text, Widget relWidget, float x, float y, float minWidth, float minHeight, bool allowResize, bool mouseVisible)
{
DarkTooltipContainer container = new DarkTooltipContainer();
container.mTooltip = this;
container.AddWidget(this);
Attach(relWidget);
mFont = DarkTheme.sDarkTheme.mSmallFont;
mText = new String(text);
mAllowResize = allowResize;
FontMetrics fontMetrics = .();
float height = mFont.Draw(null, mText, x, y, 0, 0, FontOverflowMode.Overflow, &fontMetrics);
mWidth = Math.Max(minWidth, fontMetrics.mMaxWidth + GS!(32));
mHeight = Math.Max(minHeight, height + GS!(16));
float screenX;
float screenY;
relWidget.SelfToRootTranslate(x, y, out screenX, out screenY);
screenX += relWidget.mWidgetWindow.mClientX;
screenY += relWidget.mWidgetWindow.mClientY;
//screenX -= 2;
//screenY += 14;
BFWindow.Flags windowFlags = BFWindow.Flags.ClientSized | BFWindow.Flags.PopupPosition | BFWindow.Flags.NoActivate | BFWindow.Flags.DestAlpha;
WidgetWindow widgetWindow = new WidgetWindow(relWidget.mWidgetWindow,
"Tooltip",
(int32)(screenX), (int32)(screenY),
(int32)(mWidth +GS!(cShadowSize)), (int32)(mHeight + GS!(cShadowSize)),
windowFlags,
container);
widgetWindow.SetMinimumSize((int32)widgetWindow.mWindowWidth, (int32)widgetWindow.mWindowHeight);
if (!mouseVisible)
widgetWindow.SetMouseVisible(mouseVisible);
if (allowResize)
widgetWindow.mOnHitTest.Add(new => HitTest);
WidgetWindow.sOnMouseDown.Add(new => HandleMouseDown);
WidgetWindow.sOnMouseWheel.Add(new => HandleMouseWheel);
WidgetWindow.sOnMenuItemSelected.Add(new => HandleSysMenuItemSelected);
WidgetWindow.sOnKeyDown.Add(new => HandleKeyDown);
}
public ~this()
{
Detach();
}
void Attach(Widget widget)
{
if (mRelWidget != null)
Detach();
mRelWidget = widget;
if (mRelWidget != null)
mRelWidget.mOnRemovedFromParent.Add(new => WidgetRemoved);
}
void Detach()
{
if (mRelWidget != null)
{
mRelWidget.mOnRemovedFromParent.Remove(scope => WidgetRemoved, true);
mRelWidget = null;
}
}
void WidgetRemoved(Widget widget, Widget prevParent, WidgetWindow widgetWindow)
{
Detach();
Close();
}
public void Reinit(String text, Widget relWidget, float x, float y, float minWidth, float minHeight, bool allowResize, bool mouseVisible)
{
mRelWidget = relWidget;
mFont = DarkTheme.sDarkTheme.mSmallFont;
mText.Set(text);
mAllowResize = allowResize;
FontMetrics fontMetrics = .();
float height = mFont.Draw(null, mText, x, y, 0, 0, FontOverflowMode.Overflow, &fontMetrics);
mWidth = Math.Max(minWidth, fontMetrics.mMaxWidth + GS!(32));
mHeight = Math.Max(minHeight, height + GS!(16));
float screenX;
float screenY;
relWidget.SelfToRootTranslate(x, y, out screenX, out screenY);
screenX += relWidget.mWidgetWindow.mClientX;
screenY += relWidget.mWidgetWindow.mClientY;
mWidgetWindow.Resize((int32)(screenX), (int32)(screenY),
(int32)(mWidth + GS!(cShadowSize)), (int32)(mHeight + GS!(cShadowSize)));
}
void HandleKeyDown(KeyDownEvent keyboardEvent)
{
mOnKeyDown(keyboardEvent);
if (keyboardEvent.mHandled)
return;
if (keyboardEvent.mKeyCode == KeyCode.Escape)
{
Close();
keyboardEvent.mHandled = true;
}
}
BFWindow.HitTestResult HitTest(int32 x, int32 y)
{
int32 relX = x - mWidgetWindow.mX;
int32 relY = y - mWidgetWindow.mY;
if ((relX >= mWidgetWindow.mWindowWidth - GS!(18)) && (relY >= mWidgetWindow.mWindowHeight - GS!(18)))
return BFWindowBase.HitTestResult.BottomRight;
return BFWindowBase.HitTestResult.Client;
}
public override void Draw(Graphics g)
{
base.Draw(g);
using (g.PushColor(0x80000000))
g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.DropShadow), 0, 0, mWidth + cShadowSize, mHeight + cShadowSize);
using (g.PushColor(0xFFFFFFFF))
g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Menu), 0, 0, mWidth, mHeight);
g.SetFont(mFont);
g.DrawString(mText, 0, GS!(5), FontAlign.Centered, mWidth);
if (mAllowResize)
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.ResizeGrabber), mWidth - GS!(22), mHeight - GS!(22));
}
public override void ParentDeleted()
{
Close();
base.ParentDeleted();
}
public void Close()
{
if (mHasClosed)
return;
mHasClosed = true;
if (mWidgetWindow != null)
{
WidgetWindow.sOnMouseDown.Remove(scope => HandleMouseDown, true);
WidgetWindow.sOnMouseWheel.Remove(scope => HandleMouseWheel, true);
WidgetWindow.sOnMenuItemSelected.Remove(scope => HandleSysMenuItemSelected, true);
WidgetWindow.sOnKeyDown.Remove(scope => HandleKeyDown, true);
mWidgetWindow.Close();
}
mCloseEvent();
}
void HandleMouseWheel(MouseEvent evt)
{
WidgetWindow widgetWindow = (WidgetWindow)evt.mSender;
if (widgetWindow == mWidgetWindow)
return;
Close();
}
void HandleMouseDown(MouseEvent evt)
{
WidgetWindow widgetWindow = (WidgetWindow)evt.mSender;
if (widgetWindow == mWidgetWindow)
return;
//if ((!(widgetWindow.mRootWidget is HoverWatch)) && (!(widgetWindow.mRootWidget is MenuWidget)))
Close();
}
void HandleSysMenuItemSelected(IMenu sysMenu)
{
Close();
}
public override void Update()
{
base.Update();
if (mWidgetWindow == null)
return;
/*var lastMouseWidget = IDEApp.sApp.sLastMouseWidget;
if ((lastMouseWidget != null) && (lastMouseWidget != mRelWidget) && (lastMouseWidget.mWidgetWindow != mWidgetWindow))
Close();*/
float rootX;
float rootY;
mRelWidget.SelfToRootTranslate(0, 0, out rootX, out rootY);
Rect checkRect = Rect(rootX, rootY, mRelWidget.mWidth, mRelWidget.mHeight);
mRelWidgetMouseInsets?.ApplyTo(ref checkRect);
if ((mRelWidget.mWidgetWindow != null) && (mRelWidget.mWidgetWindow.mHasMouseInside))
{
//checkRect.Inflate(8, 8);
if (checkRect.Contains(mRelWidget.mWidgetWindow.mClientMouseX, mRelWidget.mWidgetWindow.mClientMouseY))
return;
}
if ((mWidgetWindow.mHasMouseInside) && (mAllowMouseInsideSelf))
return;
Close();
}
}
static class DarkTooltipManager
{
public static DarkTooltip sTooltip;
public static Widget sLastMouseWidget;
public static int32 sMouseStillTicks;
public static Point sLastAbsMousePos;
public static Point sLastRelMousePos;
public static bool sWantsRefireMouseOver;
public static bool IsTooltipShown(Widget relWidget)
{
return (sTooltip != null) && (sTooltip.mRelWidget == relWidget);
}
public static DarkTooltip ShowTooltip(String text, Widget relWidget, float x, float y, float minWidth = 0, float minHeight = 0, bool allowResize = false, bool mouseVisible = false)
{
scope AutoBeefPerf("DarkTooltipManager.ShowTooltip");
if (sTooltip != null)
{
if (relWidget == sTooltip.mRelWidget)
{
sTooltip.Reinit(text, relWidget, x, y, minWidth, minHeight, allowResize, mouseVisible);
return null; // Only return the tooltip when a new one has been allocated
}
sTooltip.Close();
}
sTooltip = new DarkTooltip(text, relWidget, x, y, minWidth, minHeight, allowResize, mouseVisible);
sTooltip.mCloseEvent.Add(new () => {sTooltip = null; });
return sTooltip;
}
public static void CloseTooltip()
{
if (sTooltip != null)
sTooltip.Close();
}
public static void UpdateTooltip()
{
if (sTooltip == null)
return;
}
public static bool CheckMouseover(Widget checkWidget, int wantTicks, out Point mousePoint, bool continuous = false)
{
mousePoint = Point(Int32.MinValue, Int32.MinValue);
if (checkWidget != sLastMouseWidget)
return false;
for (var childWindow in checkWidget.mWidgetWindow.mChildWindows)
{
var childWidgetWindow = childWindow as WidgetWindow;
if (childWidgetWindow == null)
continue;
if (childWidgetWindow.mRootWidget is MenuContainer)
return false;
}
checkWidget.RootToSelfTranslate(sLastRelMousePos.x, sLastRelMousePos.y, out mousePoint.x, out mousePoint.y);
if ((continuous) && (sMouseStillTicks > wantTicks))
return true;
if (sWantsRefireMouseOver)
{
sWantsRefireMouseOver = false;
return true;
}
return sMouseStillTicks == wantTicks;
}
static void LastMouseWidgetDeleted(Widget widget)
{
if (sLastMouseWidget == widget)
sLastMouseWidget = null;
}
public static void RefireMouseOver()
{
sWantsRefireMouseOver = true;
}
static void SetLastMouseWidget(Widget newWidget)
{
if (sLastMouseWidget != null)
sLastMouseWidget.mOnDeleted.Remove(scope => LastMouseWidgetDeleted, true);
sLastMouseWidget = newWidget;
if (sLastMouseWidget != null)
sLastMouseWidget.mOnDeleted.Add(new => LastMouseWidgetDeleted);
}
public static void UpdateMouseover()
{
if (sMouseStillTicks != -1)
sMouseStillTicks++;
Widget overWidget = null;
int32 numOverWidgets = 0;
for (var window in BFApp.sApp.mWindows)
{
var widgetWindow = window as WidgetWindow;
widgetWindow.RehupMouse(false);
var windowOverWidget = widgetWindow.mCaptureWidget ?? widgetWindow.mOverWidget;
if ((windowOverWidget != null) && (widgetWindow.mAlpha == 1.0f) && (widgetWindow.mCaptureWidget == null))
{
overWidget = windowOverWidget;
numOverWidgets++;
if (overWidget != sLastMouseWidget)
{
SetLastMouseWidget(overWidget);
sMouseStillTicks = -1;
}
float actualX = widgetWindow.mClientX + widgetWindow.mMouseX;
float actualY = widgetWindow.mClientY + widgetWindow.mMouseY;
if ((sLastAbsMousePos.x != actualX) || (sLastAbsMousePos.y != actualY))
{
sMouseStillTicks = 0;
sLastAbsMousePos.x = actualX;
sLastAbsMousePos.y = actualY;
}
sLastRelMousePos.x = widgetWindow.mMouseX;
sLastRelMousePos.y = widgetWindow.mMouseY;
}
}
if (overWidget == null)
{
SetLastMouseWidget(null);
sMouseStillTicks = -1;
}
if (numOverWidgets > 1)
{
//int a = 0;
Debug.WriteLine("numOverWidgets > 1");
}
//Debug.Assert(numOverWidgets <= 1);
}
}
}

View file

@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Beefy.theme.dark;
using Beefy.widgets;
using System.Diagnostics;
namespace Beefy.theme.dark
{
public class DarkVirtualListViewItem : DarkListViewItem
{
public DarkVirtualListViewItem mVirtualHeadItem;
public int32 mVirtualCount; // Including head item
public int32 mVirtualIdx;
public bool mDisabled = false;
public bool mUpdating = false;
public ~this()
{
Debug.Assert(!mUpdating);
}
public override void Update()
{
mUpdating = true;
defer { mUpdating = false; }
base.Update();
if (mParentItem == null)
return;
var virtualListView = (DarkVirtualListView)mListView;
if (mParentItem.mChildAreaHeight != 0)
{
float itemHeight = virtualListView.mFont.GetLineSpacing();
if (mVirtualHeadItem == this)
{
float ofsX;
float ofsY;
mParent.SelfToOtherTranslate(mListView, 0, 0, out ofsX, out ofsY);
ofsY -= (float)(mListView.mVertPos.mDest + mListView.mScrollContent.mY);
int32 curMemberIdx = 0;
DarkVirtualListViewItem prevVirtualListViewItem = null;
DarkVirtualListViewItem nextVirtualListViewItem = (DarkVirtualListViewItem)mParentItem.mChildItems[curMemberIdx];
int32 showCount = mVirtualCount;
float curY = mY;
float prevY = curY;
float lastBottomPadding = 0;
for (int32 idx = 0; idx < showCount; idx++)
{
DarkVirtualListViewItem curVirtualListViewItem = null;
if ((nextVirtualListViewItem != null) && (idx == nextVirtualListViewItem.mVirtualIdx))
{
curVirtualListViewItem = nextVirtualListViewItem;
curMemberIdx++;
if (curMemberIdx < mParentItem.mChildItems.Count)
{
nextVirtualListViewItem = (DarkVirtualListViewItem)mParentItem.mChildItems[curMemberIdx];
if (nextVirtualListViewItem.mVirtualHeadItem != this)
nextVirtualListViewItem = null;
if (nextVirtualListViewItem != null)
lastBottomPadding = nextVirtualListViewItem.mBottomPadding;
}
else
nextVirtualListViewItem = null;
}
bool wantsFillIn = (curY + ofsY + itemHeight >= 0) && (curY + ofsY < mListView.mHeight);
bool wantsDelete = !wantsFillIn;
if (mDisabled)
{
wantsFillIn = false;
wantsDelete = false;
}
if ((curVirtualListViewItem == null) && (wantsFillIn))
{
prevVirtualListViewItem.mBottomPadding = (curY - prevVirtualListViewItem.mY) - prevVirtualListViewItem.mSelfHeight - prevVirtualListViewItem.mChildAreaHeight;
curVirtualListViewItem = (DarkVirtualListViewItem)mParentItem.CreateChildItemAtIndex(curMemberIdx);
curVirtualListViewItem.mVisible = false;
curVirtualListViewItem.mX = mX;
curVirtualListViewItem.mVirtualHeadItem = this;
curVirtualListViewItem.mVirtualIdx = idx;
virtualListView.PopulateVirtualItem(curVirtualListViewItem);
curMemberIdx++;
}
if ((wantsDelete) && (idx != 0) && (curVirtualListViewItem != null) && (curVirtualListViewItem.mChildAreaHeight == 0))
{
curMemberIdx--;
mParentItem.RemoveChildItem(curVirtualListViewItem);
curVirtualListViewItem = null;
}
if (prevVirtualListViewItem != null)
{
if (mDisabled)
prevVirtualListViewItem.mBottomPadding = 0;
else
prevVirtualListViewItem.mBottomPadding = (curY - prevY) - prevVirtualListViewItem.mSelfHeight - prevVirtualListViewItem.mChildAreaHeight;
}
if (curVirtualListViewItem != null)
prevY = curY;
curY += itemHeight;
if (curVirtualListViewItem != null)
{
curY += curVirtualListViewItem.mChildAreaHeight;
prevVirtualListViewItem = curVirtualListViewItem;
}
}
if (prevVirtualListViewItem != null)
{
if (mDisabled)
prevVirtualListViewItem.mBottomPadding = 0;
else
prevVirtualListViewItem.mBottomPadding = (curY - prevY) - prevVirtualListViewItem.mSelfHeight - prevVirtualListViewItem.mChildAreaHeight;
if (prevVirtualListViewItem.mBottomPadding != lastBottomPadding)
mListView.mListSizeDirty = true;
}
while ((curMemberIdx > 0) && (curMemberIdx < mParentItem.mChildItems.Count))
{
var curVirtualListViewItem = (DarkVirtualListViewItem)mParentItem.mChildItems[curMemberIdx];
if (curVirtualListViewItem.mVirtualHeadItem != this)
break;
mParentItem.RemoveChildItem(curVirtualListViewItem);
if (mParentItem == null) // Last item
return;
}
}
}
}
}
public class DarkVirtualListView : DarkListView
{
protected override ListViewItem CreateListViewItem()
{
var anItem = new DarkVirtualListViewItem();
return anItem;
}
public virtual void PopulateVirtualItem(DarkVirtualListViewItem item)
{
}
}
}

View file

@ -0,0 +1,105 @@
using System;
using System.Runtime.InteropServices;
namespace Beefy.utils
{
static class BeefPerf
{
[StdCall, CLink]
extern static void BpInit(char8* severName, char8* sessionName);
[StdCall, CLink]
extern static void BpShutdown();
[StdCall, CLink]
extern static void BpRetryConnect();
[StdCall, CLink]
extern static void BpPause();
[StdCall, CLink]
extern static void BpUnpause();
[StdCall, CLink]
extern static void BpSetThreadName(char8* threadName);
[StdCall, CLink]
extern static void BpEnter(char8* name);
[StdCall, CLink]
extern static void BpLeave();
[StdCall, CLink]
extern static void BpEvent(char8* name, char8* details);
[StdCall, CLink]
extern static char8* BpDynStr(char8* string);
public static void Init(StringView serverName, StringView sessionName)
{
BpInit(serverName.ToScopeCStr!(), sessionName.ToScopeCStr!());
}
public static void RetryConnect()
{
BpRetryConnect();
}
public static void Shutdown()
{
BpShutdown();
}
public static void Pause()
{
BpPause();
}
public static void Unpause()
{
BpUnpause();
}
public static void SetThreadName(StringView threadName)
{
BpSetThreadName(threadName.ToScopeCStr!());
}
[Inline]
public static void Enter(char8* name)
{
BpEnter(name);
}
[Inline]
public static void Leave()
{
BpLeave();
}
[Inline]
public static void Event(char8* name, char8* details)
{
BpEvent(name, details);
}
[Inline]
public static char8* DynStr(char8* string)
{
return BpDynStr(string);
}
}
class AutoBeefPerf
{
public this(char8* name)
{
BeefPerf.Enter(name);
}
public ~this()
{
BeefPerf.Leave();
}
}
}

View file

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.utils
{
public delegate void DisposeProxyDelegate();
public class DisposeProxy : IDisposable
{
public DisposeProxyDelegate mDisposeProxyDelegate;
public this(DisposeProxyDelegate theDelegate = null)
{
mDisposeProxyDelegate = theDelegate;
}
public ~this()
{
delete mDisposeProxyDelegate;
}
public void Dispose()
{
mDisposeProxyDelegate();
}
}
}

View file

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.utils
{
public interface ISerializable
{
//TODO: void Serialize(StructuredData data);
//TODO: void Deserialize(StructuredData data);
}
}

View file

@ -0,0 +1,899 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
namespace Beefy.utils
{
public struct IdSpan
{
enum Change
{
case Insert(int32 index, int32 id, int16 length);
case Remove(int32 index, int16 length);
public int32 GetIndex()
{
int32 index;
switch (this)
{
case .Insert(out index, ?, ?):
case .Remove(out index, ?):
}
return index;
}
}
enum ChangeKind
{
case None;
case Insert;
case Remove;
}
static uint8[] sEmptyData = new uint8[] { 0 } ~ delete _;
public uint8[] mData;
public int32 mLength;
List<Change> mChangeList;
public static int32 sId;
public int32 mId = ++sId;
public bool mAlwaysPrepare = false;
/*public uint8[] mData
{
get
{
Debug.Assert(mChangeList == null);
return mData;
}
}*/
public this()
{
mData = sEmptyData;
mLength = 0;
mChangeList = null;
}
public this(uint8[] data, int32 length)
{
mData = data;
mLength = length;
mChangeList = null;
}
bool HasChangeList
{
get
{
return mChangeList != null;
}
}
public bool IsEmpty
{
get
{
return mLength == 0;
}
}
struct Span
{
public int32 mIndex;
public int32 mId;
public int32 mLength;
public int32 mNext;
}
public void PrepareReverse() mut
{
PrepareReverse(0, mChangeList.Count);
DeleteAndNullify!(mChangeList);
}
// Decode change lists, move backwards through it applying changes, the reencode it.
// Repeats as necessary if items aren't in reverse order
void PrepareReverse(int startChangeIdx, int endChangeIdx) mut
{
int changeIdx = startChangeIdx;
List<Span> spans = scope List<Span>();
while (changeIdx < endChangeIdx)
{
spans.Clear();
int encodeIdx = 0;
int32 charId = 1;
int32 charIdx = 0;
while (true)
{
int32 cmd = Utils.DecodeInt(mData, ref encodeIdx);
if (cmd > 0)
{
charId = cmd;
}
else
{
int32 spanSize = -cmd;
if (cmd == 0)
break;
Span span;
span.mId = charId;
span.mIndex = charIdx;
span.mLength = spanSize;
span.mNext = -1;
spans.Add(span);
charId += spanSize;
charIdx += spanSize;
if (spans.Count > 1)
spans[spans.Count - 2].mNext = (int32)spans.Count - 1;
}
}
// Initialize to something so we can pick up the insert
if (spans.Count == 0)
{
Span span;
span.mId = 1;
span.mIndex = 0;
span.mLength = 0;
span.mNext = -1;
spans.Add(span);
}
int32 index = -1;
int32 length = -1;
int32 curId = -1;
ChangeKind changeKind = .None;
int32 checkIdx = (int32)spans.Count - 1;
int32 headSpanIdx = 0;
// Reverse find the first span
while ((checkIdx >= 0) && (changeIdx < endChangeIdx))
{
if (changeKind == .None)
{
switch (mChangeList[changeIdx])
{
case .Insert(out index, out curId, out length):
changeKind = .Insert;
case .Remove(out index, out length):
changeKind = .Remove;
}
}
var checkSpan = ref spans[checkIdx];
if ((index >= checkSpan.mIndex) && (index <= checkSpan.mIndex + checkSpan.mLength))
{
if (changeKind == .Insert)
{
if (index == checkSpan.mIndex)
{
if (checkSpan.mLength == 0)
{
checkSpan.mLength = length;
checkSpan.mId = curId;
}
else
{
int32 newSpanIdx = (.)spans.Count;
// Insert before span
Span span;
span.mIndex = index;
span.mId = curId;
span.mLength = length;
span.mNext = (.)checkIdx;
spans.Add(span);
if (checkIdx > 0)
{
Debug.Assert(spans[checkIdx - 1].mNext == checkIdx);
spans[checkIdx - 1].mNext = newSpanIdx;
}
else
headSpanIdx = newSpanIdx;
// Since we remapped the previous entries mNext, we are no longer in order and can't be reused this pass
checkIdx = checkIdx - 1;
}
}
else
{
var checkSpan;
// Split span
int32 leftLength = index - checkSpan.mIndex;
int32 newSpanId = (.)spans.Count;
int32 newRightId = (.)spans.Count + 1;
@checkSpan.mNext = newSpanId;
@checkSpan.mLength = leftLength;
Span span;
span.mIndex = index;
span.mId = curId;
span.mLength = length;
span.mNext = newRightId;
spans.Add(span);
Span rightSpan;
rightSpan.mIndex = index + span.mLength;
rightSpan.mId = checkSpan.mId + leftLength;
rightSpan.mLength = checkSpan.mLength - leftLength;
rightSpan.mNext = checkSpan.mNext;
spans.Add(rightSpan);
}
}
else // Remove
{
int removeSpanIdx = checkIdx;
if (index == checkSpan.mIndex)
{
// Removing from front of span. Handled in loop below.
}
else if (index + length >= checkSpan.mIndex + checkSpan.mLength)
{
// Removing up to or past end of span
int32 removeCount = Math.Min(length, checkSpan.mLength - (index - checkSpan.mIndex));
checkSpan.mLength -= removeCount;
length -= removeCount;
removeSpanIdx = checkSpan.mNext;
}
else
{
var checkSpan;
int32 splitIdx = index - checkSpan.mIndex;
int32 splitOfs = splitIdx + length;
int32 newRightId = (.)spans.Count;
@checkSpan.mNext = newRightId;
@checkSpan.mLength = index - checkSpan.mIndex;
Span rightSpan;
rightSpan.mIndex = checkSpan.mIndex + splitIdx;
rightSpan.mId = checkSpan.mId + splitOfs;
rightSpan.mLength = checkSpan.mLength - splitOfs;
rightSpan.mNext = checkSpan.mNext;
spans.Add(rightSpan);
length = 0;
if (newRightId == checkIdx + 1)
checkIdx = newRightId; // rightSpan index is valid now and it is next in sequence
}
while (length > 0)
{
var removeSpan = ref spans[removeSpanIdx];
// Remove from start of span
int32 removeCount = Math.Min(removeSpan.mLength, length);
removeSpan.mId += removeCount;
removeSpan.mLength -= removeCount;
length -= removeCount;
removeSpanIdx = removeSpan.mNext;
}
}
changeIdx++;
changeKind = .None;
continue;
}
checkIdx--;
}
curId = 1;
int32 spanIdx = headSpanIdx;
int curEncodeIdx = 0;
if (mData != sEmptyData)
delete mData;
mData = new uint8[spans.Count * 8];
while (spanIdx != -1)
{
var span = ref spans[spanIdx];
if (span.mLength == 0)
{
spanIdx = span.mNext;
continue;
}
if (span.mId != curId)
{
Utils.EncodeInt(mData, ref curEncodeIdx, span.mId);
curId = span.mId;
}
Utils.EncodeInt(mData, ref curEncodeIdx, -span.mLength);
curId += span.mLength;
spanIdx = span.mNext;
}
Utils.EncodeInt(mData, ref curEncodeIdx, 0);
mLength = (int32)curEncodeIdx;
}
}
void MaybePrepare() mut
{
// For sanity - only queue up so many changes
if (mChangeList.Count >= 8192)
{
Prepare();
}
}
public void Prepare() mut
{
if (mChangeList == null)
return;
scope AutoBeefPerf("IdSpan.Prepare");
int changeIdx = 0;
while (changeIdx < mChangeList.Count)
{
// Check to see if we have a reverse-order encoding. This can occur when undoing forward-ordered changes (for example)
bool hasReverse = false;
int reverseLastIdx = changeIdx;
int32 prevIndex = mChangeList[changeIdx].GetIndex();
for (int checkIdx = changeIdx + 1; checkIdx < mChangeList.Count; checkIdx++)
{
int32 nextIndex = mChangeList[checkIdx].GetIndex();
if (nextIndex > prevIndex)
break;
if (nextIndex < prevIndex)
hasReverse = true;
reverseLastIdx = checkIdx;
prevIndex = nextIndex;
}
if (hasReverse)
{
PrepareReverse(changeIdx, reverseLastIdx + 1);
changeIdx = reverseLastIdx + 1;
continue;
}
// We need space to encode '-length', the new span ID,
// reverting back to the original ID, and a split span length
uint8[] textIdData = new uint8[mLength + mChangeList.Count*16];
int prevCharIdx = 0;
int prevEncodeIdx = 0;
int prevLastSpanLength = 0;
int prevLastSpanIdStart = 1;
int curEncodeIdx = 0;
int curSpanIdStart = 1;
bool foundSpan = false;
int ignoreLength = 0;
int32 index;
int32 length;
int32 curId = -1;
ChangeKind changeKind;
switch (mChangeList[changeIdx++])
{
case .Insert(out index, out curId, out length):
changeKind = .Insert;
case .Remove(out index, out length):
changeKind = .Remove;
}
while (prevLastSpanIdStart != -1)
{
if (ignoreLength > 0)
{
int handleLength = Math.Min(prevLastSpanLength, ignoreLength);
ignoreLength -= handleLength;
prevLastSpanIdStart += handleLength;
prevLastSpanLength -= handleLength;
}
if ((curSpanIdStart != prevLastSpanIdStart) && (prevLastSpanLength > 0) && (ignoreLength == 0))
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, prevLastSpanIdStart);
curSpanIdStart = prevLastSpanIdStart;
}
if ((prevCharIdx + prevLastSpanLength >= index) && (!foundSpan) && (ignoreLength == 0))
{
foundSpan = true;
if (curSpanIdStart != prevLastSpanIdStart)
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, prevLastSpanIdStart);
curSpanIdStart = prevLastSpanIdStart;
}
if (changeKind case .Insert)
{
// Time to insert
int leftSplitLen = index - prevCharIdx;
if (leftSplitLen > 0)
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, -leftSplitLen);
curSpanIdStart += leftSplitLen;
prevLastSpanIdStart += leftSplitLen;
prevCharIdx += leftSplitLen;
prevLastSpanLength -= leftSplitLen;
}
if (curSpanIdStart != curId)
{
curSpanIdStart = curId;
Utils.EncodeInt(textIdData, ref curEncodeIdx, curSpanIdStart);
}
curId += length;
if (length > 0)
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, -length);
curSpanIdStart += length;
prevCharIdx += length;
}
}
else
{
ignoreLength = length;
// Time to insert
int leftSplitLen = index - prevCharIdx;
if (leftSplitLen > 0)
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, -leftSplitLen);
curSpanIdStart += leftSplitLen;
prevLastSpanIdStart += leftSplitLen;
prevCharIdx += leftSplitLen;
prevLastSpanLength -= leftSplitLen;
}
}
if (changeIdx < mChangeList.Count)
{
switch (mChangeList[changeIdx])
{
case .Insert(out index, out curId, out length):
changeKind = .Insert;
case .Remove(out index, out length):
changeKind = .Remove;
}
if (index >= prevCharIdx)
{
// We are inserting into a just-removed location
foundSpan = false;
changeIdx++;
}
}
continue;
}
int cmd = Utils.DecodeInt(mData, ref prevEncodeIdx);
if (cmd >= 0)
{
if (prevLastSpanLength > 0)
{
Utils.EncodeInt(textIdData, ref curEncodeIdx, -prevLastSpanLength);
curSpanIdStart += prevLastSpanLength;
prevLastSpanIdStart += prevLastSpanLength;
prevCharIdx += prevLastSpanLength;
prevLastSpanLength = 0;
}
Debug.Assert(prevLastSpanLength == 0);
prevLastSpanIdStart = cmd;
if (cmd == 0)
break;
}
else
prevLastSpanLength += -cmd;
}
Utils.EncodeInt(textIdData, ref curEncodeIdx, 0);
mLength = (int32)curEncodeIdx;
if (mData != sEmptyData)
delete mData;
mData = textIdData;
}
DeleteAndNullify!(mChangeList);
}
public IdSpan GetPrepared() mut
{
Prepare();
return this;
}
public void Dispose() mut
{
if (mData != sEmptyData)
delete mData;
delete mChangeList;
mData = sEmptyData;
mLength = 0;
}
public void DuplicateFrom(ref IdSpan span) mut
{
Dispose();
this = span.Duplicate();
}
public static readonly IdSpan Empty = IdSpan(sEmptyData, 1);
public void Insert(int index, int length, ref int32 curId) mut
{
var index;
var length;
if (mChangeList == null)
mChangeList = new .();
else if (mChangeList.Count > 0)
{
var change = ref mChangeList.Back;
if (change case .Insert(let prevIndex, let prevId, var ref prevLength))
{
if ((prevIndex + prevLength == index) && (prevId + prevLength == curId))
{
int16 curLen = (int16)Math.Min(length, 0x7FFF - prevLength);
prevLength += curLen;
curId += curLen;
index += curLen;
length -= curLen;
}
}
}
while (length > 0)
{
int16 curLen = (int16)Math.Min(length, 0x7FFF);
mChangeList.Add(.Insert((int32)index, curId, curLen));
curId += curLen;
index += curLen;
length -= curLen;
}
if (mAlwaysPrepare)
Prepare();
else
MaybePrepare();
}
public void Remove(int index, int length) mut
{
var index;
var length;
if (mChangeList == null)
mChangeList = new .();
else if (mChangeList.Count > 0)
{
var change = ref mChangeList.Back;
if (change case .Remove(let prevIndex, var ref prevLength))
{
if (prevIndex == index)
{
int16 curLen = (int16)Math.Min(length, 0x7FFF - prevLength);
prevLength += curLen;
length -= curLen;
}
}
}
while (length > 0)
{
int16 curLen = (int16)Math.Min(length, 0x7FFF);
mChangeList.Add(.Remove((int32)index, curLen));
length -= curLen;
}
if (mAlwaysPrepare)
Prepare();
else
MaybePrepare();
}
public int GetIndexFromId(int32 findCharId)
{
Debug.Assert(!HasChangeList);
int encodeIdx = 0;
int charId = 1;
int charIdx = 0;
while (true)
{
int cmd = Utils.DecodeInt(mData, ref encodeIdx);
if (cmd > 0)
charId = cmd;
else
{
int spanSize = -cmd;
if ((findCharId >= charId) && (findCharId < charId + spanSize))
return charIdx + (findCharId - charId);
charId += spanSize;
charIdx += spanSize;
if (cmd == 0)
return -1;
}
}
}
public int32 GetIdAtIndex(int findIndex)
{
int encodeIdx = 0;
int32 charId = 1;
int charIdx = 0;
while (true)
{
int32 cmd = Utils.DecodeInt(mData, ref encodeIdx);
if (cmd > 0)
charId = cmd;
else
{
int32 spanSize = -cmd;
if ((findIndex >= charIdx) && (findIndex < charIdx + spanSize))
return charId + (int32)(findIndex - charIdx);
charId += spanSize;
charIdx += spanSize;
if (cmd == 0)
return -1;
}
}
}
public IdSpan Duplicate()
{
Debug.Assert(!HasChangeList);
IdSpan idSpan = IdSpan();
if (mData != null)
{
idSpan.mData = new uint8[mLength];
mData.CopyTo(idSpan.mData, 0, 0, mLength);
idSpan.mLength = mLength;
}
return idSpan;
}
public bool Equals(IdSpan idData2)
{
Debug.Assert(!HasChangeList);
Debug.Assert(!idData2.HasChangeList);
if ((mLength == 0) || (idData2.mLength == 0))
return (mLength == 0) && (idData2.mLength == 0);
int encodeIdx1 = 0;
int encodeIdx2 = 0;
int curSpanId1 = 1;
int curSpanId2 = 1;
int spanLen1 = 0;
int spanLen2 = 0;
while (true)
{
while (spanLen1 == 0)
{
int cmd = Utils.DecodeInt(mData, ref encodeIdx1);
if (cmd < 0)
{
spanLen1 = -cmd;
}
else
{
curSpanId1 = cmd;
if (cmd == 0)
break;
}
}
while (spanLen2 == 0)
{
int32 cmd = Utils.DecodeInt(idData2.mData, ref encodeIdx2);
if (cmd < 0)
{
spanLen2 = -cmd;
}
else
{
curSpanId2 = cmd;
if (cmd == 0)
{
// They are equal if both spans are at the end
return spanLen1 == 0;
}
}
}
if (curSpanId1 != curSpanId2)
return false;
int minLen = Math.Min(spanLen1, spanLen2);
curSpanId1 += minLen;
spanLen1 -= minLen;
curSpanId2 += minLen;
spanLen2 -= minLen;
}
}
public int GetTotalLength()
{
int len = 0;
int encodeIdx = 0;
while (true)
{
int cmd = Utils.DecodeInt(mData, ref encodeIdx);
if (cmd == 0)
return len;
if (cmd < 0)
len += -cmd;
}
}
static bool FindId(uint8[] idData, ref int encodeIdx, ref int32 curSpanId, ref int32 spanLen, int32 findSpanId)
{
while (true)
{
int32 cmd = Utils.DecodeInt(idData, ref encodeIdx);
if (cmd < 0)
{
spanLen = -cmd;
if ((findSpanId >= curSpanId) && (findSpanId < curSpanId + spanLen))
{
int32 delta = findSpanId - curSpanId;
curSpanId += delta;
spanLen -= delta;
return true;
}
curSpanId += spanLen;
}
else
{
curSpanId = cmd;
if (cmd == 0)
return false;
}
}
}
public bool IsRangeEqual(IdSpan idData2, int32 startCharId, int32 endCharId)
{
int encodeIdx1 = 0;
int encodeIdx2 = 0;
int32 curSpanId1 = 1;
int32 curSpanId2 = 1;
int32 spanLen1 = 0;
int32 spanLen2 = 0;
if (!FindId(mData, ref encodeIdx1, ref curSpanId1, ref spanLen1, startCharId))
return false;
if (!FindId(idData2.mData, ref encodeIdx2, ref curSpanId2, ref spanLen2, startCharId))
return false;
while (true)
{
while (spanLen1 == 0)
{
int32 cmd = Utils.DecodeInt(mData, ref encodeIdx1);
if (cmd < 0)
{
spanLen1 = -cmd;
}
else
{
curSpanId1 = cmd;
if (cmd == 0)
break;
}
}
while (spanLen2 == 0)
{
int32 cmd = Utils.DecodeInt(idData2.mData, ref encodeIdx2);
if (cmd < 0)
{
spanLen2 = -cmd;
}
else
{
curSpanId2 = cmd;
if (cmd == 0)
{
// They are equal if both spans are at the end
return spanLen1 == 0;
}
}
}
if (curSpanId1 != curSpanId2)
return false;
if (curSpanId1 == endCharId)
return true;
int minLen = Math.Min(spanLen1, spanLen2);
if ((endCharId >= curSpanId1) && (endCharId < curSpanId1 + minLen))
minLen = Math.Min(minLen, endCharId - curSpanId1);
if ((endCharId >= curSpanId2) && (endCharId < curSpanId2 + minLen))
minLen = Math.Min(minLen, endCharId - curSpanId2);
curSpanId1 += (int32)minLen;
spanLen1 -= (.)minLen;
curSpanId2 += (int32)minLen;
spanLen2 -= (.)minLen;
}
}
public static IdSpan GetDefault(int32 length)
{
uint8[] idData = new uint8[8];
int encodeIdx = 0;
Utils.EncodeInt(idData, ref encodeIdx, (int32)-length);
Utils.EncodeInt(idData, ref encodeIdx, 0);
IdSpan idSpan = IdSpan();
idSpan.mData = idData;
idSpan.mLength = (int32)encodeIdx;
return idSpan;
}
public void Dump() mut
{
Prepare();
Debug.WriteLine("IdSpan Dump:");
int encodeIdx = 0;
int charId = 1;
int charIdx = 0;
while (true)
{
int32 cmd = Utils.DecodeInt(mData, ref encodeIdx);
if (cmd > 0)
{
charId = cmd;
Debug.WriteLine(" Id: {0}", charId);
}
else
{
int32 spanSize = -cmd;
charId += spanSize;
charIdx += spanSize;
if (cmd == 0)
return;
Debug.WriteLine(" Len: {0}", spanSize);
}
}
}
}
}

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime;
using System.Diagnostics;
namespace Beefy.utils
{
public static class ManualBreak
{
public static void Break()
{
ThrowUnimplemented();
//Debugger.Break();
}
}
}

View file

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace Beefy.utils
{
public abstract class PerfTimer
{
[StdCall, CLink]
extern static void PerfTimer_ZoneStart(char8* name);
[StdCall, CLink]
extern static void PerfTimer_ZoneEnd();
[StdCall, CLink]
extern static void PerfTimer_Message(char8* theString);
[StdCall, CLink]
extern static int32 PerfTimer_IsRecording();
[StdCall, CLink]
extern static void PerfTimer_StartRecording();
[StdCall, CLink]
extern static void PerfTimer_StopRecording();
[StdCall, CLink]
extern static void PerfTimer_DbgPrint();
static DisposeProxy mZoneEndDisposeProxy ~ delete _;
public static DisposeProxy ZoneStart(String name)
{
if (mZoneEndDisposeProxy == null)
mZoneEndDisposeProxy = new DisposeProxy(new => ZoneEnd);
PerfTimer_ZoneStart(name);
return mZoneEndDisposeProxy;
}
public static void ZoneEnd()
{
PerfTimer_ZoneEnd();
}
public static void Message(String theString)
{
PerfTimer_Message(theString);
}
public static void Message(String format, params Object[] theParams)
{
String outStr = scope String();
outStr.AppendF(format, params theParams);
Message(outStr);
}
public static bool IsRecording()
{
return PerfTimer_IsRecording() != 0;
}
public static void StartRecording()
{
PerfTimer_StartRecording();
}
public static void StopRecording()
{
PerfTimer_StopRecording();
}
public static void DbgPrint()
{
PerfTimer_DbgPrint();
}
}
}

View file

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.utils
{
public class SmoothValue
{
public double mSrc;
public double mDest;
public float mPct;
public float mSpeed = 1.0f;
public float mSpeedScale = 1.0f;
public double v
{
get
{
if (mPct == 1.0f)
return mDest;
return mSrc + (mDest - mSrc) * EasedPct;
}
}
public double EasedPct
{
get
{
if (mPct == 1.0f)
return 1.0f;
return Utils.EaseInAndOut(mPct);
}
}
public bool IsMoving
{
get { return mPct != 1.0f; }
}
public void Update()
{
mPct = Math.Min(1.0f, mPct + mSpeed * mSpeedScale);
}
public void Set(double val, bool immediate = false)
{
if ((!immediate) && (val == mDest))
return;
if ((mPct != 1.0f) && (mPct != 0.0f))
{
double cur = v;
if (mPct > 0.80f)
mPct = 0.80f;
mDest = val;
mSrc = -(cur - mDest * EasedPct) / (EasedPct - 1);
mSpeedScale = (1.0f - mPct);
}
else
{
mSrc = v;
mPct = 0.0f;
mSpeedScale = 1.0f;
mDest = val;
}
if (immediate)
mPct = 1.0f;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
namespace Beefy.utils
{
class TextSearcher
{
enum CmdKind
{
Contains,
NotContains,
Equals,
}
struct CmdElement
{
public CmdKind mKind;
public String mString;
}
List<CmdElement> mCmds = new List<CmdElement>() ~
{
for (var cmdElement in mCmds)
{
delete cmdElement.mString;
}
delete _;
};
Result<void> EndCmd(String findStr, ref char8 startChar, String outError, OperatorDelegate operatorHandler)
{
if (findStr.IsEmpty)
return .Ok;
CmdElement cmdElement;
if ((findStr.StartsWith(":")) && (operatorHandler != null))
{
int opIdx = -1;
for (int i < findStr.Length)
{
char8 c = findStr[i];
if ((c == '=') || (c == '>') || (c == '<'))
{
if (opIdx != -1)
{
outError.Append("Multiple operators cannot be defined in the same text segment");
return .Err;
}
opIdx = i;
}
}
if (opIdx != -1)
{
if (startChar != 0)
{
outError.Append("Multiple operators cannot be defined in the same text segment");
return .Err;
}
if ((operatorHandler == null) || (!operatorHandler(scope String(findStr, 0, opIdx), findStr[opIdx], scope String(findStr, opIdx + 1))))
{
outError.AppendF("Invalid expression: {0}", findStr);
return .Err;
}
return .Ok;
}
}
if (startChar == '=')
cmdElement.mKind = .Equals;
else if (startChar == '-')
cmdElement.mKind = .NotContains;
else
cmdElement.mKind = .Contains;
cmdElement.mString = new String(findStr);
mCmds.Add(cmdElement);
findStr.Clear();
startChar = 0;
return .Ok;
}
delegate bool OperatorDelegate(String lhs, char8 op, String rhs);
public Result<void> Init(String searchStr, String outError, OperatorDelegate operatorHandler = null)
{
bool inQuote = false;
char8 startChar = 0;
String findStr = scope String();
for (int i < searchStr.Length)
{
var c = searchStr[i];
if (c == '\"')
{
inQuote = !inQuote;
continue;
}
if (c == '\"')
{
c = searchStr[++i];
findStr.Append(c);
continue;
}
if ((c == ' ') && (!inQuote))
{
Try!(EndCmd(findStr, ref startChar, outError, operatorHandler));
continue;
}
if ((startChar == 0) && (findStr.IsEmpty) && (!inQuote))
{
if ((c == '=') || (c == '-'))
{
startChar = c;
continue;
}
}
findStr.Append(c);
}
Try!(EndCmd(findStr, ref startChar, outError, operatorHandler));
return .Ok;
}
public bool Matches(String checkStr)
{
for (var cmd in ref mCmds)
{
switch (cmd.mKind)
{
case .Contains:
if (checkStr.IndexOf(cmd.mString, true) == -1)
return false;
case .NotContains:
if (checkStr.IndexOf(cmd.mString, true) != -1)
return false;
case .Equals:
if (!String.Equals(checkStr, cmd.mString, .OrdinalIgnoreCase))
return false;
}
}
return true;
}
public bool IsEmpty
{
get
{
return mCmds.Count == 0;
}
}
}
}

View file

@ -0,0 +1,311 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace Beefy.utils
{
public class UndoAction
{
public virtual bool Merge(UndoAction nextAction)
{
return false;
}
public virtual bool Undo()
{
return true;
}
public virtual bool Redo()
{
return true;
}
public virtual int32 GetCost()
{
return 1;
}
}
public interface IUndoBatchStart
{
IUndoBatchEnd BatchEnd { get; }
String Name { get; }
}
public interface IUndoBatchEnd
{
IUndoBatchStart BatchStart { get; }
String Name { get; }
}
public class UndoBatchStart : UndoAction, IUndoBatchStart
{
public String mName;
public UndoBatchEnd mBatchEnd;
public int32 mBatchInsertIdx;
public int32 mBatchSize = 0; // Don't close out until we add the end
public String Name
{
get
{
return mName;
}
}
public this(String name)
{
mName = name;
mBatchEnd = new UndoBatchEnd();
mBatchEnd.mBatchStart = this;
}
public IUndoBatchEnd BatchEnd
{
get
{
return mBatchEnd;
}
}
public override int32 GetCost()
{
return Math.Min(mBatchSize, 256); // Don't allow a large batch (ie: rename) to cause us to pull too much out of the undo buffer
}
}
public class UndoBatchEnd : UndoAction, IUndoBatchEnd
{
public IUndoBatchStart mBatchStart;
public String Name
{
get
{
return mBatchStart.Name;
}
}
public IUndoBatchStart BatchStart
{
get
{
return mBatchStart;
}
}
}
public class UndoManager
{
List<UndoAction> mUndoList = new List<UndoAction>() ~ DeleteContainerAndItems!(_);
int32 mUndoIdx = 0;
int32 mMaxCost = 8192;
int32 mCurCost = 0;
bool mSkipNextMerge; // Don't merge after we do an undo or redo step
int32 mFreezeDeletes;
public ~this()
{
Clear();
}
public void WithActions(Action<UndoAction> func)
{
for (var action in mUndoList)
func(action);
}
public void Clear()
{
while (mUndoList.Count > 0)
{
var undoAction = mUndoList.PopBack();
delete undoAction;
}
mUndoIdx = 0;
mCurCost = 0;
}
public void Add(UndoAction action, bool allowMerge = true)
{
if (mFreezeDeletes == 0)
mCurCost += action.GetCost();
if (action is IUndoBatchStart)
{
mFreezeDeletes++;
if (var undoBatchStart = action as UndoBatchStart)
{
undoBatchStart.mBatchInsertIdx = GetActionCount();
}
}
else if (action is IUndoBatchEnd)
{
mFreezeDeletes--;
if (var undoBatchEnd = action as UndoBatchEnd)
{
if (var undoBatchStart = undoBatchEnd.mBatchStart as UndoBatchStart)
{
undoBatchStart.mBatchSize = GetActionCount() - undoBatchStart.mBatchInsertIdx;
int32 cost = undoBatchStart.GetCost();
Debug.Assert(cost >= 0);
mCurCost += cost;
}
}
}
if (mUndoIdx < mUndoList.Count)
{
int32 batchDepth = 0;
for (int checkIdx = mUndoIdx; checkIdx < mUndoList.Count; checkIdx++)
{
var checkAction = mUndoList[checkIdx];
if (batchDepth == 0)
mCurCost -= checkAction.GetCost();
if (checkAction is IUndoBatchStart)
batchDepth++;
else if (checkAction is IUndoBatchEnd)
batchDepth--;
delete checkAction;
}
Debug.Assert(batchDepth == 0);
mUndoList.RemoveRange(mUndoIdx, mUndoList.Count - mUndoIdx);
}
if ((allowMerge) && (!mSkipNextMerge))
{
UndoAction prevAction = GetLastUndoAction();
if (prevAction is UndoBatchStart)
{
var undoBatchStart = (UndoBatchStart)prevAction;
if (undoBatchStart.mBatchEnd == action)
{
// It's an empty batch!
mUndoList.PopBack();
delete prevAction;
delete action;
mUndoIdx--;
return;
}
}
if ((prevAction != null) && (prevAction.Merge(action)))
{
delete action;
return;
}
}
mSkipNextMerge = false;
mUndoList.Add(action);
mUndoIdx++;
if ((mCurCost > mMaxCost) && (mFreezeDeletes == 0))
{
int32 wantCost = (int32)(mMaxCost * 0.8f); // Don't just remove one item at a time
int32 checkIdx = 0;
int32 batchDepth = 0;
while (((mCurCost > wantCost) || (batchDepth > 0)) &&
(checkIdx < mUndoList.Count))
{
var checkAction = mUndoList[checkIdx];
if (batchDepth == 0)
mCurCost -= checkAction.GetCost();
if (checkAction is IUndoBatchStart)
batchDepth++;
else if (checkAction is IUndoBatchEnd)
batchDepth--;
delete checkAction;
checkIdx++;
}
mUndoList.RemoveRange(0, checkIdx);
mUndoIdx -= checkIdx;
}
}
public UndoAction GetLastUndoAction()
{
if (mUndoIdx == 0)
return null;
return mUndoList[mUndoIdx - 1];
}
public bool Undo()
{
mSkipNextMerge = true;
if (mUndoIdx == 0)
return false;
var undoAction = mUndoList[mUndoIdx - 1];
if (IUndoBatchEnd undoBatchEnd = undoAction as IUndoBatchEnd)
{
while (true)
{
if (!undoAction.Undo())
return false;
if (mUndoIdx == 0)
return false;
mUndoIdx--;
if ((undoAction == undoBatchEnd.BatchStart) || (mUndoIdx == 0))
return true;
undoAction = mUndoList[mUndoIdx - 1];
}
}
if (!undoAction.Undo())
return false;
mUndoIdx--;
return true;
}
public bool Redo()
{
mSkipNextMerge = true;
if (mUndoIdx >= mUndoList.Count)
return false;
int32 startUndoIdx = mUndoIdx;
var undoAction = mUndoList[mUndoIdx];
if (undoAction is UndoBatchStart)
{
UndoBatchStart undoBatchStart = (UndoBatchStart)undoAction;
while (true)
{
if (!undoAction.Redo())
{
mUndoIdx = startUndoIdx;
return false;
}
if (mUndoIdx >= mUndoList.Count)
return false;
mUndoIdx++;
if (undoAction == undoBatchStart.mBatchEnd)
return true;
undoAction = mUndoList[mUndoIdx];
}
}
if (!undoAction.Redo())
return false;
mUndoIdx++;
return true;
}
public int32 GetActionCount()
{
return mUndoIdx;
}
}
}

View file

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.gfx;
using System.Runtime.InteropServices;
namespace Beefy.widgets
{
public class ButtonWidget : Widget
{
public bool mDisabled;
public override void Draw(Graphics g)
{
}
public override void KeyDown(KeyCode keyCode, bool isRepeat)
{
base.KeyDown(keyCode, isRepeat);
if ((keyCode == KeyCode.Return) || (keyCode == KeyCode.Space))
MouseDown(0, 0, 3, 1);
else
mParent.KeyDown(keyCode, isRepeat);
}
public override void KeyUp(KeyCode keyCode)
{
base.KeyUp(keyCode);
if ((keyCode == KeyCode.Return) || (keyCode == KeyCode.Space))
{
if (mMouseFlags != 0)
MouseUp(0, 0, 3);
}
else
mParent.KeyUp(keyCode);
}
}
}

View file

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace Beefy.widgets
{
public abstract class CheckBox : Widget
{
public enum State
{
Unchecked,
Checked,
Indeterminate
}
[DesignEditable]
public abstract bool Checked { get; set; }
public virtual State State
{
get
{
return Checked ? .Checked : .Unchecked;
}
set
{
Debug.Assert(value != .Indeterminate);
Checked = value != .Unchecked;
}
}
public Event<Action> mOnValueChanged ~ _.Dispose();
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
{
base.MouseDown(x, y, btn, btnCount);
}
public override void MouseUp(float x, float y, int32 btn)
{
if (mMouseOver)
{
Checked = !Checked;
mOnValueChanged();
}
base.MouseUp(x, y, btn);
}
}
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.widgets
{
public class ComboBox : Widget
{
public bool mDisabled;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.widgets
{
public struct DesignEditableAttribute : Attribute
{
public String DisplayType { get; set; }
public String Group { get; set; }
public String DisplayName { get; set; }
public String SortName { get; set; }
public bool DefaultEditString { get; set; }
}
}

View file

@ -0,0 +1,383 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Beefy.gfx;
using Beefy.events;
namespace Beefy.widgets
{
public delegate void DialogEventHandler(DialogEvent theEvent);
interface IHotKeyHandler
{
bool Handle(KeyCode keyCode);
}
public abstract class Dialog : Widget
{
public bool mInPopupWindow;
public String mTitle ~ delete _;
public String mText ~ delete _;
public Image mIcon;
public BFWindowBase.Flags mWindowFlags = .ClientSized | .TopMost | .Caption | .Border | .SysMenu | .Modal;
public List<ButtonWidget> mButtons = new List<ButtonWidget>() ~ delete _;
public List<Widget> mTabWidgets = new List<Widget>() ~ delete _;
public Dictionary<ButtonWidget, DialogEventHandler> mHandlers = new Dictionary<ButtonWidget, DialogEventHandler>() ~ delete _;
public ButtonWidget mDefaultButton;
public ButtonWidget mEscButton;
public EditWidget mDialogEditWidget;
public bool mClosed;
public Event<Action> mOnClosed ~ _.Dispose();
static String STRING_OK = "Ok";
static String STRING_CANCEL = "Cancel";
static String STRING_YES = "Yes";
static String STRING_NO = "No";
static String STRING_CLOSE = "Close";
public String Title
{
get
{
return mTitle;
}
set
{
String.NewOrSet!(mTitle, value);
if (mWidgetWindow != null)
mWidgetWindow.SetTitle(mTitle);
}
}
public this(String title = null, String text = null, Image icon = null)
{
if (title != null)
mTitle = new String(title);
if (text != null)
mText = new String(text);
mIcon = icon;
}
public ~this()
{
for (var handler in mHandlers.Values)
delete handler;
}
public virtual void Close()
{
mClosed = true;
if (mWidgetWindow == null)
return;
if (mInPopupWindow)
{
BFWindow lastChildWindow = null;
if (mWidgetWindow.mParent.mChildWindows != null)
{
for (var checkWindow in mWidgetWindow.mParent.mChildWindows)
if (checkWindow != mWidgetWindow)
lastChildWindow = checkWindow;
if (lastChildWindow != null)
lastChildWindow.SetForeground();
}
if (lastChildWindow == null)
{
if (!mWidgetWindow.mParent.mHasClosed)
mWidgetWindow.mParent.SetForeground();
}
mWidgetWindow.mOnWindowKeyDown.Remove(scope => WindowKeyDown, true);
mWidgetWindow.Close(true);
mInPopupWindow = false;
if (mOnClosed.HasListeners)
mOnClosed();
}
}
public virtual ButtonWidget CreateButton(String label)
{
return null;
}
public virtual EditWidget CreateEditWidget()
{
return null;
}
void HandleMouseClick(MouseEvent theEvent)
{
ButtonWidget widget = (ButtonWidget) theEvent.mSender;
DialogEvent dialogEvent = scope DialogEvent();
dialogEvent.mButton = widget;
dialogEvent.mCloseDialog = true;
dialogEvent.mSender = this;
if (mHandlers[widget] != null)
mHandlers[widget](dialogEvent);
if (dialogEvent.mCloseDialog)
Close();
}
public virtual ButtonWidget AddButton(String label, DialogEventHandler handler = null)
{
Debug.AssertNotStack(handler);
ButtonWidget button = CreateButton(label);
mHandlers[button] = handler;
button.mOnMouseClick.Add(new => HandleMouseClick);
mButtons.Add(button);
mTabWidgets.Add(button);
AddWidget(button);
return button;
}
public virtual EditWidget AddEdit(String text, DialogEventHandler handler = null)
{
Debug.AssertNotStack(handler);
var editWidget = CreateEditWidget();
AddWidget(editWidget);
if (text != null)
{
editWidget.SetText(text);
editWidget.Content.SelectAll();
}
mTabWidgets.Add(editWidget);
if (mDialogEditWidget == null)
mDialogEditWidget = editWidget;
editWidget.mOnSubmit.Add(new => EditSubmitHandler);
editWidget.mOnCancel.Add(new => EditCancelHandler);
return editWidget;
}
public virtual EditWidget AddEdit(EditWidget editWidget, DialogEventHandler handler = null)
{
Debug.AssertNotStack(handler);
if (editWidget.mParent == null)
AddWidget(editWidget);
mTabWidgets.Add(editWidget);
if (mDialogEditWidget == null)
mDialogEditWidget = editWidget;
editWidget.mOnSubmit.Add(new => EditSubmitHandler);
editWidget.mOnCancel.Add(new => EditCancelHandler);
return editWidget;
}
public void AddDialogComponent(Widget widget)
{
mTabWidgets.Add(widget);
AddWidget(widget);
}
protected void EditSubmitHandler(EditEvent theEvent)
{
Submit();
}
protected void EditCancelHandler(EditEvent theEvent)
{
if (mEscButton != null)
mEscButton.MouseClicked(0, 0, 3);
}
public virtual void AddCloseButton(DialogEventHandler closeHandler, int32 theDefault = -1)
{
Debug.AssertNotStack(closeHandler);
#unwarn
ButtonWidget closeButton = AddButton(STRING_CLOSE, closeHandler);
}
public virtual void AddYesNoButtons(DialogEventHandler yesHandler = null, DialogEventHandler noHandler = null, int32 theDefault = -1, int32 escapeBtn = -1)
{
Debug.AssertNotStack(yesHandler);
Debug.AssertNotStack(noHandler);
ButtonWidget yesButton = AddButton(STRING_YES, yesHandler);
ButtonWidget noButton = AddButton(STRING_NO, noHandler);
mDefaultButton = (theDefault == 0) ? yesButton : (theDefault == 1) ? noButton : null;
mEscButton = (escapeBtn == 0) ? yesButton : (escapeBtn == 1) ? noButton : null;
}
public virtual void AddOkCancelButtons(DialogEventHandler okHandler = null, DialogEventHandler cancelHandler = null, int32 theDefault = -1, int32 escapeBtn = -1)
{
Debug.AssertNotStack(okHandler);
Debug.AssertNotStack(cancelHandler);
ButtonWidget okButton = AddButton(STRING_OK, okHandler);
ButtonWidget cancelButton = AddButton(STRING_CANCEL, cancelHandler);
mDefaultButton = (theDefault == 0) ? okButton : (theDefault == 1) ? cancelButton : null;
mEscButton = (escapeBtn == 0) ? okButton : (escapeBtn == 1) ? cancelButton : null;
}
public virtual void PreShow()
{
}
public virtual void CalcSize()
{
}
public virtual void ResizeComponents()
{
}
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
ResizeComponents();
}
public override void AddedToParent()
{
if (mDialogEditWidget != null)
mDialogEditWidget.SetFocus();
else if (mDefaultButton != null)
mDefaultButton.SetFocus();
else
SetFocus();
}
public virtual void PopupWindow(WidgetWindow parentWindow, float offsetX = 0, float offsetY = 0)
{
if (mClosed)
return;
mInPopupWindow = true;
CalcSize();
ResizeComponents();
int desktopWidth;
int desktopHeight;
BFApp.sApp.GetDesktopResolution(out desktopWidth, out desktopHeight);
//TODO: Clip to desktop width / height
mWidth = Math.Min(desktopWidth - 32, mWidth);
mHeight = Math.Min(desktopHeight - 32, mHeight);
float aX = parentWindow.mClientX + (parentWindow.mClientWidth - mWidth) / 2 + offsetX;
float aY = parentWindow.mClientY + (parentWindow.mClientHeight - mHeight) / 2 + offsetY;
for (int32 i = 0; i < parentWindow.mChildWindows.Count; i++)
{
var otherChild = parentWindow.mChildWindows[i];
if (otherChild.mWindowFlags.HasFlag(BFWindowBase.Flags.Modal))
{
aX = Math.Max(aX, otherChild.mClientX + 16);
aY = Math.Max(aY, otherChild.mClientY + 16);
}
}
WidgetWindow widgetWindow = new WidgetWindow(parentWindow,
mTitle ?? "Dialog",
(int32)(aX), (int32)(aY),
(int32)mWidth, (int32)mHeight,
mWindowFlags,
this);
WindowCloseQueryHandler windowCloseHandler = new (evt) =>
{
Close();
return false;
};
widgetWindow.mOnWindowCloseQuery.Add(windowCloseHandler);
widgetWindow.mOnWindowKeyDown.Add(new => WindowKeyDown);
}
public virtual bool HandleTab(int dir)
{
return Widget.HandleTab(dir, mTabWidgets);
}
public virtual void Escape()
{
mEscButton.MouseClicked(0, 0, 3);
}
public virtual void Submit()
{
if ((mDefaultButton != null) && (!mDefaultButton.mDisabled))
mDefaultButton.MouseClicked(0, 0, 3);
}
void WindowKeyDown(KeyDownEvent evt)
{
if ((evt.mKeyCode != .Alt) && (mWidgetWindow.IsKeyDown(.Alt)) && (!mWidgetWindow.IsKeyDown(.Control)))
{
if (mChildWidgets != null)
{
for (var widget in mChildWidgets)
{
if (let hotKeyHandler = widget as IHotKeyHandler)
{
if (hotKeyHandler.Handle(evt.mKeyCode))
{
evt.mHandled = true;
return;
}
}
}
}
}
if (evt.mKeyCode == .Escape)
{
if (mWidgetWindow.mFocusWidget != null)
{
let widgetWindow = mWidgetWindow;
let focusWidget = widgetWindow.mFocusWidget;
widgetWindow.mFocusWidget.KeyDown(evt);
if (focusWidget != widgetWindow.mFocusWidget)
evt.mHandled = true; // Infers we handled the event
if (evt.mHandled)
return;
evt.mHandled = true;
}
if (mEscButton != null)
{
if ((mDefaultButton != null) && (mDefaultButton.mMouseDown))
{
mDefaultButton.mMouseFlags = default;
mDefaultButton.mMouseDown = false;
}
else
Escape();
evt.mHandled = true;
}
}
if ((evt.mKeyCode == .Return) && (mDefaultButton != null))
{
if ((!(mWidgetWindow.mFocusWidget is EditWidget)) &&
(!(mWidgetWindow.mFocusWidget is ButtonWidget)))
{
Submit();
}
}
if (evt.mKeyCode == KeyCode.Tab)
{
int32 dir = mWidgetWindow.IsKeyDown(KeyCode.Shift) ? -1 : 1;
if (HandleTab(dir))
{
evt.mHandled = true;
}
}
}
}
}

View file

@ -0,0 +1,185 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.gfx;
using System.Diagnostics;
namespace Beefy.widgets
{
public interface IDockable
{
bool CanDock(DockingFrame frame, DockedWidget refWidget, DockingFrame.WidgetAlign align);
void Dock(DockingFrame frame, DockedWidget refWidget, DockingFrame.WidgetAlign align);
void DrawDockPreview(Graphics g);
}
public interface ICustomDock
{
void Draw(Graphics g);
void Dock(IDockable dockingWidget);
}
public class DockedWidget : Widget, IDockable
{
public bool mHasFillWidget;
public bool mIsFillWidget;
public bool mAutoClose = true; // Close when last tab is removed
public float mRequestedWidth; // Set when we drag a sizer
public float mRequestedHeight; // Set when we drag a sizer
public float mSizePriority;
public DockingFrame mParentDockingFrame;
public bool mAllowInterpolate;
public float mInterpolatePct = 1.0f;
public float mStartRootX;
public float mStartRootY;
public float mStartWidth;
public float mStartHeight;
public float mEndX;
public float mEndY;
public float mEndWidth;
public float mEndHeight;
public this()
{
mClipMouse = true;
mClipGfx = true;
}
public virtual DockingFrame GetRootDockingFrame()
{
var parentFrame = mParentDockingFrame;
while (parentFrame != null)
{
if (parentFrame.mParentDockingFrame == null)
break;
parentFrame = parentFrame.mParentDockingFrame;
}
return parentFrame;
}
public virtual void Rehup()
{
mHasFillWidget = mIsFillWidget;
}
public virtual void SetRequestedSize(float width, float height)
{
mRequestedWidth = width;
mRequestedHeight = height;
}
public virtual ICustomDock GetCustomDock(IDockable dockable, float x, float y)
{
return null;
}
public bool CanDock(DockingFrame frame, DockedWidget refWidget, DockingFrame.WidgetAlign align)
{
return true;
}
public virtual void Dock(DockingFrame frame, DockedWidget refWidget, DockingFrame.WidgetAlign align)
{
if (mParentDockingFrame != null) // TODO: Undock
{
}
}
public virtual void DrawDockPreview(Graphics g)
{
using (g.PushColor(0x80FFFFFF))
DrawAll(g);
}
public void StartInterpolate(float rootX, float rootY, float width, float height)
{
mInterpolatePct = 0;
mStartRootX = rootX;
mStartRootY = rootY;
mStartWidth = mWidth;
mStartHeight = mHeight;
}
public void StartInterpolate()
{
if ((mAllowInterpolate) && (mInterpolatePct == 1.0f))
{
mInterpolatePct = 0;
mParent.SelfToRootTranslate(mX, mY, out mStartRootX, out mStartRootY);
mStartWidth = mWidth;
mStartHeight = mHeight;
mEndX = mX;
mEndY = mY;
mEndWidth = mWidth;
mEndHeight = mHeight;
}
}
void UpdateInterpolation()
{
if (mInterpolatePct != 1.0f)
{
mInterpolatePct = Math.Min(mInterpolatePct + 0.1f, 1.0f);
float startX;
float startY;
mParent.RootToSelfTranslate(mStartRootX, mStartRootY, out startX, out startY);
Resize(
Utils.Lerp(startX, mEndX, mInterpolatePct),
Utils.Lerp(startY, mEndY, mInterpolatePct),
Utils.Lerp(mStartWidth, mEndWidth, mInterpolatePct),
Utils.Lerp(mStartHeight, mEndHeight, mInterpolatePct));
}
}
public override void Update()
{
base.Update();
UpdateInterpolation();
Debug.Assert((mParent == mParentDockingFrame) || (mParentDockingFrame == null));
// Allow to interpolate after first update
mAllowInterpolate = true;
}
public virtual void ResizeDocked(float x, float y, float width, float height)
{
if (mInterpolatePct != 1.0f)
{
mEndX = x;
mEndY = y;
mEndWidth = width;
mEndHeight = height;
UpdateInterpolation();
}
else
Resize(x, y, width, height);
}
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
}
}
public class DockingProxy : DockedWidget
{
Widget mWidget;
public this(Widget widget)
{
mWidget = widget;
AddWidget(mWidget);
}
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
mWidget.Resize(0, 0, width, height);
}
}
}

View file

@ -0,0 +1,989 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.theme;
using Beefy.gfx;
using System.Diagnostics;
using Beefy.geom;
namespace Beefy.widgets
{
public class DockingFrame : DockedWidget
{
public enum WidgetAlign
{
Inside,
Left,
Right,
Top,
Bottom
};
public enum SplitType
{
None,
Horz,
Vert
};
public List<DockedWidget> mDockedWidgets = new List<DockedWidget>() ~ delete _;
public SplitType mSplitType = SplitType.None;
public float mMinWindowSize = 32;
public float mDragMarginSize = 64;
public float mDragWindowMarginSize = 10;
public float mWindowMargin = 0;
public float mSplitterSize = 6.0f;
public float mWindowSpacing = 2.0f;
public int32 mDownSplitterNum = -1;
public IDockable mDraggingDock;
public DockedWidget mDraggingRef;
public WidgetAlign mDraggingAlign;
public ICustomDock mDraggingCustomDock ~ delete (Object)_;
public virtual void AddDockedWidget(DockedWidget widget, DockedWidget refWidget, WidgetAlign align)
{
SplitType wantSplitType = ((align == WidgetAlign.Left) || (align == WidgetAlign.Right)) ?
SplitType.Horz : SplitType.Vert;
if (mDockedWidgets.Count == 0)
wantSplitType = SplitType.None;
if ((wantSplitType != mSplitType) && (mSplitType != SplitType.None))
{
DockingFrame newChildFrame = ThemeFactory.mDefault.CreateDockingFrame(this);
bool hasFillWidget = mHasFillWidget;
if (refWidget != null)
{
newChildFrame.mRequestedWidth = refWidget.mRequestedWidth;
newChildFrame.mRequestedHeight = refWidget.mRequestedHeight;
ReplaceDockedWidget(refWidget, newChildFrame);
// Just split out the one referenced widget
newChildFrame.mParentDockingFrame = this;
refWidget.mParentDockingFrame = newChildFrame;
newChildFrame.mDockedWidgets.Add(refWidget);
newChildFrame.AddWidget(refWidget);
newChildFrame.AddDockedWidget(widget, null, align);
ResizeContent(true);
return;
}
else
{
newChildFrame.mRequestedWidth = 0;
newChildFrame.mRequestedHeight = 0;
for (DockedWidget aDockedWidget in mDockedWidgets)
{
if (mSplitType == SplitType.Horz)
{
newChildFrame.mRequestedWidth += aDockedWidget.mRequestedWidth;
newChildFrame.mRequestedHeight = Math.Max(newChildFrame.mRequestedHeight, aDockedWidget.mRequestedHeight);
}
else
{
newChildFrame.mRequestedWidth = Math.Max(mRequestedWidth, aDockedWidget.mRequestedWidth);
newChildFrame.mRequestedHeight += aDockedWidget.mRequestedHeight;
}
RemoveWidget(aDockedWidget);
newChildFrame.mDockedWidgets.Add(aDockedWidget);
newChildFrame.AddWidget(aDockedWidget);
aDockedWidget.mParentDockingFrame = newChildFrame;
hasFillWidget |= aDockedWidget.mHasFillWidget;
}
mDockedWidgets.Clear();
}
newChildFrame.mParentDockingFrame = this;
newChildFrame.mHasFillWidget = hasFillWidget;
newChildFrame.mSplitType = mSplitType;
newChildFrame.mWidth = newChildFrame.mRequestedWidth;
newChildFrame.mHeight = newChildFrame.mRequestedHeight;
mDockedWidgets.Add(newChildFrame);
AddWidget(newChildFrame);
}
widget.mParentDockingFrame = this;
//TODO:
/*if (fillWidget != null)
{
// Don't take more than half remaining space at a time
widget.mRequestedWidth = Math.Min(fillWidget.mWidth / 2, widget.mRequestedWidth);
widget.mRequestedHeight = Math.Min(fillWidget.mHeight / 2, widget.mRequestedHeight);
}*/
widget.mRequestedWidth = Math.Max(mMinWindowSize, widget.mRequestedWidth);
widget.mRequestedHeight = Math.Max(mMinWindowSize, widget.mRequestedHeight);
if ((align == WidgetAlign.Left) || (align == WidgetAlign.Top))
{
if (refWidget != null)
mDockedWidgets.Insert(mDockedWidgets.IndexOf(refWidget), widget);
else
mDockedWidgets.Insert(0, widget);
}
else
{
if (refWidget != null)
mDockedWidgets.Insert(mDockedWidgets.IndexOf(refWidget) + 1, widget);
else
mDockedWidgets.Add(widget);
}
AddWidget(widget);
mSplitType = wantSplitType;
if ((widget.mHasFillWidget) || (widget.mIsFillWidget))
widget.GetRootDockingFrame().Rehup();
ResizeContent(true);
}
public override void Rehup()
{
bool allHaveSizes = true;
bool didHaveFillWidget = mHasFillWidget;
base.Rehup();
for (var dockedWiget in mDockedWidgets)
{
dockedWiget.mHasFillWidget = dockedWiget.mIsFillWidget;
dockedWiget.Rehup();
if (dockedWiget.mHasFillWidget)
{
mHasFillWidget = true;
}
if ((dockedWiget.mWidth == 0) || (dockedWiget.mHeight == 0))
allHaveSizes = false;
}
// If we turn off mHasFillWidget and go to an all-non-fill situation then we reset the size priority
if (didHaveFillWidget != mHasFillWidget)
{
for (var dockedWiget in mDockedWidgets)
dockedWiget.mSizePriority = 0;
//if (!mHasFillWidget)
if (allHaveSizes)
{
for (var dockedWidget in mDockedWidgets)
{
if (mSplitType == .Horz)
dockedWidget.mRequestedWidth = dockedWidget.mWidth;
else
dockedWidget.mRequestedHeight = dockedWidget.mHeight;
}
}
}
for (var dockedWiget in mDockedWidgets)
{
// Reset the size priority to be whatever the current size is, it should stabilize sizes when
// toggling mIsFillWidget
if (dockedWiget.mHasFillWidget == mHasFillWidget)
{
if (dockedWiget.mSizePriority == 0)
{
if (mSplitType == .Horz)
dockedWiget.mSizePriority = dockedWiget.mWidth;
else
dockedWiget.mSizePriority = dockedWiget.mHeight;
}
}
else
dockedWiget.mSizePriority = 0;
}
}
public override DockingFrame GetRootDockingFrame()
{
var parentFrame = this;
while (parentFrame != null)
{
if (parentFrame.mParentDockingFrame == null)
break;
parentFrame = parentFrame.mParentDockingFrame;
}
return parentFrame;
}
public void WithAllDockedWidgets(Action<DockedWidget> func)
{
for (var dockedWidget in mDockedWidgets)
{
func(dockedWidget);
var dockingFrame = dockedWidget as DockingFrame;
if (dockingFrame != null)
{
dockingFrame.WithAllDockedWidgets(func);
}
}
}
public int GetDockedWindowCount()
{
return mDockedWidgets.Count;
}
public void Simplify()
{
if ((mDockedWidgets.Count == 0) && (mParentDockingFrame != null))
mParentDockingFrame.RemoveWidget(this);
else if ((mDockedWidgets.Count == 1) && (mParentDockingFrame != null))
{
// Just a single object, remove ourselves from the frame
DockedWidget aDockedWidget = mDockedWidgets[0];
mDockedWidgets.Clear();
RemoveWidget(aDockedWidget);
mParentDockingFrame.ReplaceDockedWidget(this, aDockedWidget);
BFApp.sApp.DeferDelete(this);
}
}
public virtual void RemoveDockedWidget(DockedWidget dockedWidget)
{
mDockedWidgets.Remove(dockedWidget);
RemoveWidget(dockedWidget);
if (!mIsFillWidget)
mHasFillWidget = GetHasFillWidget();
ResizeContent(true);
if ((mDockedWidgets.Count == 0) && (mParentDockingFrame == null))
{
// Automatically close when last docked widget is removed
// Should only happen on tool windows
mWidgetWindow.Close();
}
}
// Used when an embedded docking frame gets down to just a single widget
public virtual void ReplaceDockedWidget(DockedWidget dockedWidget, DockedWidget replaceWidget)
{
int32 index = mDockedWidgets.IndexOf(dockedWidget);
RemoveWidget(dockedWidget);
mDockedWidgets[index] = replaceWidget;
AddWidget(replaceWidget);
replaceWidget.mParentDockingFrame = this;
ResizeContent(true);
}
protected virtual bool GetHasFillWidget()
{
for (DockedWidget aDockedWidget in mDockedWidgets)
if (aDockedWidget.mHasFillWidget)
return true;
return false;
}
public virtual void StartContentInterpolate()
{
for (DockedWidget aDockedWidget in mDockedWidgets)
{
aDockedWidget.StartInterpolate();
}
}
public virtual void ResizeContent(bool interpolate = false)
{
float sizeLeft = (mSplitType == SplitType.Horz) ? (mWidth - mWindowMargin*2) : (mHeight - mWindowMargin*2);
sizeLeft -= (mDockedWidgets.Count - 1) * mWindowSpacing;
if (sizeLeft <= 0)
return;
List<DockedWidget> widgetsLeft = scope List<DockedWidget>();
for (DockedWidget aDockedWidget in mDockedWidgets)
{
widgetsLeft.Add(aDockedWidget);
if (interpolate)
aDockedWidget.StartInterpolate();
}
//DockedWidget fillWidget = GetFillWidget();
//if (fillWidget != null)
{
bool hasFillWidget = false;
for (int32 widgetIdx = 0; widgetIdx < widgetsLeft.Count; widgetIdx++)
{
DockedWidget aDockedWidget = widgetsLeft[widgetIdx];
if (aDockedWidget.mHasFillWidget)
{
hasFillWidget = true;
break;
}
}
if (hasFillWidget)
{
for (int32 widgetIdx = 0; widgetIdx < widgetsLeft.Count; widgetIdx++)
{
DockedWidget aDockedWidget = widgetsLeft[widgetIdx];
if (aDockedWidget.mHasFillWidget)
continue;
float requestedSize = (mSplitType == SplitType.Horz) ? (aDockedWidget.mRequestedWidth) : aDockedWidget.mRequestedHeight;
float size = Math.Round(Math.Max(mMinWindowSize, Math.Min(requestedSize, sizeLeft - (widgetsLeft.Count * mMinWindowSize))));
if (mSplitType == SplitType.Horz)
aDockedWidget.mWidth = size;
else
aDockedWidget.mHeight = size;
sizeLeft -= size;
widgetsLeft.RemoveAt(widgetIdx);
widgetIdx--;
}
}
//widgetsLeft.Add(fillWidget);
/*if (mSplitType == SplitType.Horz)
fillWidget.mWidth = sizeLeft;
else
fillWidget.mHeight = sizeLeft;*/
}
//if (fillWidget == null)
{
int32 totalPriCount = 0;
int32 newPriCounts = 0;
float totalPriAcc = 0.0f;
float avgPri = 0;
for (DockedWidget aDockedWidget in widgetsLeft)
{
totalPriAcc += aDockedWidget.mSizePriority;
if (aDockedWidget.mSizePriority == 0)
newPriCounts++;
else
totalPriCount++;
}
if (totalPriCount == 0)
{
// Totally uninitialized, possibly from having a document frame and then removing it
for (DockedWidget aDockedWidget in widgetsLeft)
if ((aDockedWidget.mSizePriority == 0) && (aDockedWidget.mWidth > 0) && (aDockedWidget.mHeight > 0))
{
aDockedWidget.mSizePriority = (mSplitType == .Horz) ? aDockedWidget.mWidth : aDockedWidget.mHeight;
totalPriCount++;
totalPriAcc += aDockedWidget.mSizePriority;
newPriCounts--;
}
}
if (newPriCounts > 0)
{
if (totalPriAcc > 0)
avgPri = totalPriAcc / totalPriCount;
else
avgPri = 1.0f / newPriCounts;
for (DockedWidget aDockedWidget in widgetsLeft)
if (aDockedWidget.mSizePriority == 0)
{
aDockedWidget.mSizePriority = avgPri;
totalPriCount++;
totalPriAcc += aDockedWidget.mSizePriority;
}
}
float sharedWidth = sizeLeft;
for (int32 widgetIdx = 0; widgetIdx < widgetsLeft.Count; widgetIdx++)
{
DockedWidget aDockedWidget = widgetsLeft[widgetIdx];
float size = (aDockedWidget.mSizePriority / totalPriAcc) * sharedWidth;
size = (float) Math.Round(size);
if (widgetIdx == widgetsLeft.Count - 1)
size = sizeLeft;
if (mSplitType == SplitType.Horz)
{
aDockedWidget.mWidth = size;
}
else
{
aDockedWidget.mHeight = size;
}
sizeLeft -= size;
widgetsLeft.RemoveAt(widgetIdx);
widgetIdx--;
}
}
/*DockedWidget fillWidget = GetFillWidget();
if (fillWidget == null)
{
int totalPriCount = 0;
int newPriCounts = 0;
float totalPriAcc = 0.0f;
float avgPri = 0;
foreach (DockedWidget aDockedWidget in widgetsLeft)
{
totalPriAcc += aDockedWidget.mSizePriority;
if (aDockedWidget.mSizePriority == 0)
newPriCounts++;
else
totalPriCount++;
}
if (newPriCounts > 0)
{
if (totalPriAcc > 0)
avgPri = totalPriAcc / totalPriCount;
else
avgPri = 1.0f / newPriCounts;
foreach (DockedWidget aDockedWidget in widgetsLeft)
if (aDockedWidget.mSizePriority == 0)
{
aDockedWidget.mSizePriority = avgPri;
totalPriCount++;
totalPriAcc += aDockedWidget.mSizePriority;
}
}
float sharedWidth = sizeLeft;
for (int widgetIdx = 0; widgetIdx < widgetsLeft.Count; widgetIdx++)
{
DockedWidget aDockedWidget = widgetsLeft[widgetIdx];
float size = (aDockedWidget.mSizePriority / totalPriAcc) * sharedWidth;
size = (float) Math.Round(size);
if (widgetIdx == widgetsLeft.Count - 1)
size = sizeLeft;
if (mSplitType == SplitType.Horz)
{
aDockedWidget.mWidth = size;
}
else
{
aDockedWidget.mHeight = size;
}
sizeLeft -= size;
widgetsLeft.RemoveAt(widgetIdx);
widgetIdx--;
}
}
else
{
widgetsLeft.Remove(fillWidget);
for (int widgetIdx = 0; widgetIdx < widgetsLeft.Count; widgetIdx++)
{
DockedWidget aDockedWidget = widgetsLeft[widgetIdx];
float requestedSize = (mSplitType == SplitType.Horz) ? (aDockedWidget.mRequestedWidth) : aDockedWidget.mRequestedHeight;
float size = Math.Max(mMinWindowSize, Math.Min(requestedSize, sizeLeft - (widgetsLeft.Count * mMinWindowSize)));
if (mSplitType == SplitType.Horz)
aDockedWidget.mWidth = size;
else
aDockedWidget.mHeight = size;
sizeLeft -= size;
widgetsLeft.RemoveAt(widgetIdx);
widgetIdx--;
}
if (mSplitType == SplitType.Horz)
fillWidget.mWidth = sizeLeft;
else
fillWidget.mHeight = sizeLeft;
}*/
float curPos = mWindowMargin;
for (DockedWidget aDockedWidget in mDockedWidgets)
{
float size = (mSplitType == SplitType.Horz) ? aDockedWidget.mWidth : aDockedWidget.mHeight;
if (mSplitType == SplitType.Horz)
{
aDockedWidget.ResizeDocked(curPos, mWindowMargin, size, mHeight - mWindowMargin*2);
}
else
{
aDockedWidget.ResizeDocked(mWindowMargin, curPos, mWidth - mWindowMargin*2, size);
}
curPos += size;
curPos += mWindowSpacing;
}
}
public override void Resize(float x, float y, float width, float height)
{
base.Resize(x, y, width, height);
ResizeContent();
}
public int32 FindSplitterAt(float x, float y)
{
if (!Contains(x, y))
return -1;
float curPos = 0;
float findPos = (mSplitType == SplitType.Horz) ? (x - mWindowMargin) : (y - mWindowMargin);
for (int32 widgetIdx = 0; widgetIdx < mDockedWidgets.Count; widgetIdx++)
{
DockedWidget aDockedWidget = mDockedWidgets[widgetIdx];
float size = (mSplitType == SplitType.Horz) ? aDockedWidget.mWidth : aDockedWidget.mHeight;
float diff = (findPos - curPos) + mWindowSpacing + (mSplitterSize - mWindowSpacing) / 2.0f;
if ((diff >= 0) && (diff < mSplitterSize))
return widgetIdx - 1;
curPos += size;
curPos += mWindowSpacing;
}
return -1;
}
DockingFrame GetDockingFrame(WidgetWindow widgetWindow)
{
if (widgetWindow == null)
return null;
DockingFrame dockingFrame = widgetWindow.mRootWidget as DockingFrame;
if (dockingFrame != null)
return dockingFrame;
for (var child in widgetWindow.mRootWidget.mChildWidgets)
{
dockingFrame = child as DockingFrame;
if (dockingFrame != null)
return dockingFrame;
}
return null;
}
public virtual void ShowDragTarget(IDockable draggingItem)
{
Debug.Assert(mParentDockingFrame == null);
for (BFWindow window in BFApp.sApp.mWindows)
{
if (window.mAlpha != 1.0f)
continue;
WidgetWindow widgetWindow = window as WidgetWindow;
var dockingFrame = GetDockingFrame(widgetWindow);
if (dockingFrame != null)
{
if ((widgetWindow.mHasMouseInside) || (widgetWindow.mHasProxyMouseInside))
dockingFrame.ShowDragTarget(draggingItem, widgetWindow.mMouseX, widgetWindow.mMouseY);
else
dockingFrame.HideDragTargets();
}
}
}
public virtual void HideDragTarget(IDockable draggingItem, bool executeDrag = false)
{
Debug.Assert(mParentDockingFrame == null);
for (int32 windowIdx = 0; windowIdx < BFApp.sApp.mWindows.Count; windowIdx++)
{
BFWindow window = BFApp.sApp.mWindows[windowIdx];
WidgetWindow widgetWindow = window as WidgetWindow;
if (widgetWindow != null)
{
DockingFrame dockingFrame = GetDockingFrame(widgetWindow);
if (dockingFrame != null)
dockingFrame.HideDragTargets(executeDrag);
}
}
}
void HideDragTargets(bool executeDrag = false)
{
if ((executeDrag) && (mDraggingDock != null))
{
if (mDraggingCustomDock != null)
mDraggingCustomDock.Dock(mDraggingDock);
else
mDraggingDock.Dock(this, mDraggingRef, mDraggingAlign);
}
mDraggingDock = null;
mDraggingRef = null;
delete (Object)mDraggingCustomDock;
mDraggingCustomDock = null;
for (int32 dockedWidgetIdx = 0; dockedWidgetIdx < mDockedWidgets.Count; dockedWidgetIdx++)
{
DockedWidget aDockedWidget = mDockedWidgets[dockedWidgetIdx];
DockingFrame childFrame = aDockedWidget as DockingFrame;
if (childFrame != null)
childFrame.HideDragTargets(executeDrag);
}
}
bool FindDragTarget(IDockable draggingItem, float x, float y, ref DockingFrame containingFrame, ref DockedWidget refWidget, ref WidgetAlign align, ref ICustomDock customDock, int32 minDist = -2)
{
//int foundMinDist = -1;
bool foundInSelf = false;
for (DockedWidget aDockedWidget in mDockedWidgets)
{
float childX;
float childY;
aDockedWidget.ParentToSelfTranslate(x, y, out childX, out childY);
var rect = Rect(-2, -2, aDockedWidget.mWidth + 4, aDockedWidget.mHeight + 4);
//if (aDockedWidget.Contains(childX, childY))
if (rect.Contains(childX, childY))
{
float leftDist = childX;
float topDist = childY;
float rightDist = aDockedWidget.mWidth - childX;
float botDist = aDockedWidget.mHeight - childY;
if (Math.Min(Math.Min(Math.Min(leftDist, topDist), rightDist), botDist) < minDist)
continue;
float marginX = Math.Min(mDragMarginSize, aDockedWidget.mWidth / 4);
float marginY = Math.Min(mDragMarginSize, aDockedWidget.mHeight / 4);
if ((marginX < Math.Min(leftDist, rightDist)) && (marginY < Math.Min(topDist, botDist)))
align = WidgetAlign.Inside;
else if (leftDist < Math.Min(topDist, Math.Min(rightDist, botDist)))
align = WidgetAlign.Left;
else if (topDist < Math.Min(rightDist, botDist))
align = WidgetAlign.Top;
else if (rightDist < botDist)
align = WidgetAlign.Right;
else
align = WidgetAlign.Bottom;
if (draggingItem.CanDock(this, aDockedWidget, align))
{
customDock = aDockedWidget.GetCustomDock(draggingItem, childX, childY);
containingFrame = this;
refWidget = aDockedWidget;
foundInSelf = true;
break;
}
}
}
int32 newMinDist = minDist;
if (foundInSelf)
newMinDist = Math.Max(minDist, 0) + 2;
for (DockedWidget aDockedWidget in mDockedWidgets)
{
float childX;
float childY;
aDockedWidget.ParentToSelfTranslate(x, y, out childX, out childY);
if (aDockedWidget.Contains(childX, childY))
{
DockingFrame childFrame = aDockedWidget as DockingFrame;
if (childFrame != null)
{
childFrame.FindDragTarget(draggingItem, childX, childY, ref containingFrame, ref refWidget, ref align, ref customDock, newMinDist);
break;
}
}
}
if ((mParentDockingFrame == null) && (customDock == null))
{
if (Contains(x, y))
{
float leftDist = x;
float topDist = y;
float rightDist = mWidth - x;
float botDist = mHeight - y;
float marginX = Math.Min(mDragWindowMarginSize, mWidth / 4);
float marginY = Math.Min(mDragWindowMarginSize, mHeight / 4);
WidgetAlign anAlign;
if ((marginX < Math.Min(leftDist, rightDist)) && (marginY < Math.Min(topDist, botDist)))
anAlign = WidgetAlign.Inside;
else if (leftDist < Math.Min(topDist, Math.Min(rightDist, botDist)))
anAlign = WidgetAlign.Left;
else if (topDist < Math.Min(rightDist, botDist))
anAlign = WidgetAlign.Top;
else if (rightDist < botDist)
anAlign = WidgetAlign.Right;
else
anAlign = WidgetAlign.Bottom;
if ((anAlign != WidgetAlign.Inside) && (draggingItem.CanDock(this, null, align)))
{
containingFrame = this;
refWidget = null;
customDock = null;
align = anAlign;
}
}
}
return containingFrame != null;
}
void ShowDragTarget(IDockable draggingItem, float x, float y)
{
DockingFrame containingFrame = null;
DockedWidget refWidget = null;
WidgetAlign align = .Inside;
ICustomDock customDock = null;
/*containingFrame = null;
refWidget = null;
align = WidgetAlign.Inside;
customDock = null;*/
MarkDirty();
HideDragTargets();
if ((y < 0) && (y >= -6) && (x >= 0) && (x < mWidgetWindow.mWindowWidth))
{
containingFrame = this;
containingFrame.mDraggingDock = draggingItem;
containingFrame.mDraggingRef = null;
containingFrame.mDraggingAlign = .Top;
delete (Object)containingFrame.mDraggingCustomDock;
containingFrame.mDraggingCustomDock = null;
return;
}
if (FindDragTarget(draggingItem, x, y, ref containingFrame, ref refWidget, ref align, ref customDock))
{
containingFrame.mDraggingDock = draggingItem;
containingFrame.mDraggingRef = refWidget;
containingFrame.mDraggingAlign = align;
delete (Object)containingFrame.mDraggingCustomDock;
containingFrame.mDraggingCustomDock = customDock;
}
}
public override Widget FindWidgetByCoords(float x, float y)
{
if (FindSplitterAt(x, y) != -1)
return this;
return base.FindWidgetByCoords(x, y);
}
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
{
base.MouseDown(x, y, btn, btnCount);
mDownSplitterNum = FindSplitterAt(x, y);
}
public override void MouseMove(float x, float y)
{
base.MouseMove(x, y);
if (mDownSplitterNum != -1)
{
float wantPos = (mSplitType == SplitType.Horz) ? x : y;
DockedWidget resizedWidget = null;
DockedWidget widget1 = mDockedWidgets[mDownSplitterNum];
DockedWidget widget2 = mDockedWidgets[mDownSplitterNum + 1];
List<DockedWidget> widgetsLeft = scope List<DockedWidget>();
float sizeLeft = (mSplitType == SplitType.Horz) ? (mWidth - mWindowMargin*2) : (mHeight - mWindowMargin*2);
if ((widget1.mHasFillWidget) && (widget2.mHasFillWidget))
{
bool foundWidget = false;
for (var dockedWidget in mDockedWidgets)
{
if (dockedWidget == widget1)
foundWidget = true;
if (dockedWidget.mHasFillWidget)
widgetsLeft.Add(dockedWidget);
else
{
float curSize = (mSplitType == SplitType.Horz) ? dockedWidget.mWidth : dockedWidget.mHeight;
if (!foundWidget)
wantPos -= curSize;
sizeLeft -= curSize;
}
}
}
else if (widget1.mHasFillWidget != widget2.mHasFillWidget)
{
if (widget2.mHasFillWidget)
{
if (mSplitType == .Horz)
widget1.mRequestedWidth = wantPos - widget1.mX;
else
widget1.mRequestedHeight = wantPos - widget1.mY;
}
else
{
if (mSplitType == .Horz)
{
float totalSize = widget1.mWidth + widget2.mWidth;
widget2.mRequestedWidth = Math.Max(0, widget2.mRequestedWidth + (widget2.mX - wantPos));
widget2.mRequestedWidth = Math.Min(widget2.mRequestedWidth, totalSize - mMinWindowSize * 2);
}
else
{
float totalSize = widget1.mHeight + widget2.mHeight;
widget2.mRequestedHeight = Math.Max(0, widget2.mRequestedHeight + (widget2.mY - wantPos));
widget2.mRequestedHeight = Math.Min(widget2.mRequestedHeight, totalSize - mMinWindowSize * 2);
}
resizedWidget = widget2;
//Debug.WriteLine("RW:{0} WH:{1}", widget2.mRequestedWidth, widget2.mRequestedHeight);
}
}
else
{
bool hasFillWidget = false;
for (var dockedWidget in mDockedWidgets)
{
if (dockedWidget.mHasFillWidget)
hasFillWidget = true;
}
if (hasFillWidget)
{
for (var dockedWidget in mDockedWidgets)
{
// Size prioritizes will get initialized later if we remove the fill widget
if (!dockedWidget.mHasFillWidget)
dockedWidget.mSizePriority = 0;
}
if (mSplitType == .Horz)
{
float totalSize = widget1.mWidth + widget2.mWidth;
widget2.mRequestedWidth = Math.Clamp(widget2.mRequestedWidth + (widget2.mX - wantPos), mMinWindowSize, totalSize - mMinWindowSize);
widget1.mRequestedWidth = totalSize - widget2.mRequestedWidth;
}
else
{
float totalSize = widget1.mHeight + widget2.mHeight;
widget2.mRequestedHeight = Math.Clamp(widget2.mRequestedHeight + (widget2.mY - wantPos), mMinWindowSize, totalSize - mMinWindowSize);
widget1.mRequestedHeight = totalSize - widget2.mRequestedHeight;
}
}
else
{
for (var dockedWidget in mDockedWidgets)
widgetsLeft.Add(dockedWidget);
}
}
if (widgetsLeft.Count > 0)
{
// First we normalize to 1.0
float sizePriTotal = 0.0f;
for (DockedWidget aDockedWidget in widgetsLeft)
sizePriTotal += aDockedWidget.mSizePriority;
for (DockedWidget aDockedWidget in widgetsLeft)
aDockedWidget.mSizePriority = aDockedWidget.mSizePriority / sizePriTotal;
float totalPrevSize = widget1.mSizePriority + widget2.mSizePriority;
float startCurPos = 0;
for (DockedWidget aDockedWidget in widgetsLeft)
{
if (aDockedWidget == widget1)
break;
startCurPos += aDockedWidget.mSizePriority * sizeLeft + mWindowSpacing;
}
float wantSize = Math.Max(mMinWindowSize, wantPos - startCurPos);
wantSize = Math.Min(wantSize, totalPrevSize * sizeLeft - mMinWindowSize);
wantSize /= sizeLeft;
widget1.mSizePriority = wantSize;
widget2.mSizePriority = totalPrevSize - wantSize;
}
ResizeContent();
// Set to actual used value
if (resizedWidget != null)
{
if (mSplitType == .Horz)
resizedWidget.mRequestedWidth = resizedWidget.mWidth;
else
resizedWidget.mRequestedHeight = resizedWidget.mHeight;
}
}
else
{
if (FindSplitterAt(x, y) != -1)
{
if (mSplitType == SplitType.Horz)
BFApp.sApp.SetCursor(Cursor.SizeWE);
else
BFApp.sApp.SetCursor(Cursor.SizeNS);
}
else
{
BFApp.sApp.SetCursor(Cursor.Pointer);
}
}
}
public override void MouseUp(float x, float y, int32 btn)
{
base.MouseUp(x, y, btn);
mDownSplitterNum = -1;
MouseMove(x, y);
}
public override void MouseLeave()
{
base.MouseLeave();
if (!mMouseDown)
BFApp.sApp.SetCursor(Cursor.Pointer);
}
public virtual void DrawDraggingDock(Graphics g)
{
}
public override void DrawAll(Graphics g)
{
base.DrawAll(g);
if (mDraggingDock != null)
DrawDraggingDock(g);
}
public override void Update()
{
base.Update();
Simplify();
}
}
}

View file

@ -0,0 +1,185 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Beefy.events;
namespace Beefy.widgets
{
public interface IDragInterface
{
void DragStart();
void DragEnd();
void MouseDrag(float x, float y, float dX, float dY);
}
public class DragHelper
{
public float mMouseX;
public float mMouseY;
public float mMouseDownX;
public float mMouseDownY;
public float mTriggerDist = 2.0f;
public int32 mMinDownTicks = 0;
public bool mAllowDrag = true;
public bool mIsDragging = false;
public MouseFlag mMouseFlags;
IDragInterface mDragInterface;
public Widget mWidget;
public bool mAborted;
public bool mPreparingForWidgetMove;
int32 mDownUpdateCnt;
public WidgetWindow mTrackingWindow;
//MouseEventHandler mMouseDownHandler;
public float RelX
{
get
{
return mMouseX - mMouseDownX;
}
}
public float RelY
{
get
{
return mMouseY - mMouseDownY;
}
}
public this(Widget widget, IDragInterface dragInterface)
{
mWidget = widget;
mDragInterface = dragInterface;
mWidget.mOnMouseDown.Add(new => HandleMouseDown);
mWidget.mOnMouseUp.Add(new => HandleMouseUp);
mWidget.mOnMouseMove.Add(new => HandleMouseMove);
}
public ~this()
{
if (mIsDragging)
CancelDrag();
//Debug.Assert(!mIsDragging);
mWidget.mOnMouseDown.Remove(scope => HandleMouseDown, true);
mWidget.mOnMouseUp.Remove(scope => HandleMouseUp, true);
mWidget.mOnMouseMove.Remove(scope => HandleMouseMove, true);
}
void HandleMouseDown(MouseEvent e)
{
MouseDown(e.mX, e.mY, e.mBtn, e.mBtnCount);
}
void HandleMouseUp(MouseEvent e)
{
MouseUp(e.mX, e.mY, e.mBtn);
}
void HandleMouseMove(MouseEvent e)
{
MouseMove(e.mX, e.mY);
}
public void HandleRemoved(Widget widget, Widget prevParent, WidgetWindow prevWindow)
{
CancelDrag();
}
public void HandleKeydown(KeyDownEvent theEvent)
{
if (theEvent.mKeyCode == KeyCode.Escape)
{
mAborted = true;
CancelDrag();
}
}
public void MouseDown(float x, float y, int32 btn, int32 btnCount)
{
mDownUpdateCnt = mWidget.mUpdateCnt;
mMouseFlags |= (MouseFlag)(1 << btn);
mMouseDownX = x;
mMouseDownY = y;
}
void SetHooks(bool doSet)
{
//Debug.WriteLine("SetHooks {0} {1}", this, doSet);
if (doSet)
{
mTrackingWindow = mWidget.mWidgetWindow;
mTrackingWindow.mOnWindowKeyDown.Add(new => HandleKeydown);
mWidget.mOnRemovedFromParent.Add(new => HandleRemoved);
}
else
{
mTrackingWindow.mOnWindowKeyDown.Remove(scope => HandleKeydown, true);
mWidget.mOnRemovedFromParent.Remove(scope => HandleRemoved, true);
}
}
public void SetPreparingForWidgetMove(bool prepare)
{
SetHooks(!prepare);
}
public void CancelDrag()
{
if (!mIsDragging)
return;
SetHooks(false);
mMouseFlags = default;
mIsDragging = false;
mDragInterface.DragEnd();
}
public void MouseUp(float x, float y, int32 btn)
{
mMouseFlags &= (MouseFlag)(~(1 << btn));
if (((mMouseFlags & MouseFlag.Left) == 0) && (mIsDragging))
{
CancelDrag();
}
}
public void Update()
{
int32 ticksDown = mWidget.mUpdateCnt - mDownUpdateCnt;
if (((mMouseFlags & MouseFlag.Left) != 0) && (ticksDown >= mMinDownTicks))
{
if ((!mIsDragging) && (mAllowDrag))
{
if ((Math.Abs(mMouseX - mMouseDownX) >= mTriggerDist) || (Math.Abs(mMouseY - mMouseDownY) >= mTriggerDist))
{
SetHooks(true);
mPreparingForWidgetMove = false;
mAborted = false;
mIsDragging = true;
mDragInterface.DragStart();
}
}
if (mIsDragging)
{
mIsDragging = true;
mDragInterface.MouseDrag(mMouseX, mMouseY, mMouseX - mMouseDownX, mMouseY - mMouseDownY);
}
}
}
public void MouseMove(float x, float y)
{
mMouseX = x;
mMouseY = y;
Update();
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Beefy.widgets
{
public delegate void MenuItemSelectedHandler(IMenu menu);
public delegate void MenuItemUpdateHandler(IMenu menu);
public interface IMenu
{
void SetDisabled(bool enable);
}
public interface IMenuContainer
{
}
}

View file

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.gfx;
namespace Beefy.widgets
{
public class ImageWidget : Widget
{
public IDrawable mImage;
public IDrawable mOverImage;
public IDrawable mDownImage;
public override void Draw(Graphics g)
{
if ((mMouseOver && mMouseDown) && (mDownImage != null))
g.Draw(mDownImage);
if ((mMouseOver) && (mOverImage != null))
g.Draw(mOverImage);
else
g.Draw(mImage);
}
}
}

View file

@ -0,0 +1,246 @@
using System;
using System.Collections.Generic;
using System.Text;
using Beefy.events;
using Beefy.geom;
using System.Diagnostics;
namespace Beefy.widgets
{
public delegate void InfiniteScrollEventHandler(double scrollDelta);
public abstract class InfiniteScrollbar : Widget, IDragInterface
{
/*public class Thumb : Widget, IDragInterface
{
public InfiniteScrollbar mScrollbar;
public DragHelper mDraggableHelper ~ delete _;
public this()
{
mDraggableHelper = new DragHelper(this, this);
}
public void DragStart()
{
}
public void DragEnd()
{
mScrollbar.ScrollSetLevel(0.0);
}
public void MouseDrag(float x, float y, float dX, float dY)
{
float parentX;
float parentY;
SelfToParentTranslate(x - mDraggableHelper.mMouseDownX, y - mDraggableHelper.mMouseDownY, out parentX, out parentY);
mScrollbar.ScrollSetLevel(mScrollbar.GetAccelFracAt(parentX, parentY));
}
}*/
public class Arrow : Widget
{
public InfiniteScrollbar mScrollbar;
public int32 mDownTick;
public bool mBack;
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
{
base.MouseDown(x, y, btn, btnCount);
DoScroll();
mDownTick = 0;
}
protected virtual void DoScroll()
{
mScrollbar.FixedScroll(mBack ? -1 : 1);
}
public override void Update()
{
base.Update();
if ((mMouseDown) && (mMouseOver))
{
mDownTick++;
if (mDownTick > 20)
DoScroll();
}
}
}
// configuration
public double mFixedScrollAmt; // base amount to scroll for fixed scroll events e.g arrow clicks
public double mScrollDeltaLevelAmount; // amount to change level during update while mouse is held down
//public double mScrollMaxAccel; // absolute value maximum of acceleration (transient accel will range from [-this,this])
public double mScrollMaxVelocity; // absolute value maximum of velocity; effective limit will be adjusted based on canonical acceleration
public double mScrollThumbFrac; // scaled canonical acceleration, [-1,1]
//public double mScrollAccel;
public double mScrollVelocity;
//public Thumb mThumb;
public Arrow mStartArrow;
public Arrow mEndArrow;
public float mBaseSize;
public float mDualBarSizeOffset;
public int32 mDownTick;
public float mLastMouseX;
public float mLastMouseY;
public Event<InfiniteScrollEventHandler> mOnInfiniteScrollEvent ~ _.Dispose();
public DragHelper mDraggableHelper ~ delete _;
public this()
{
mDraggableHelper = new DragHelper(this, this);
}
public void HandleScroll(double scrollDelta)
{
if (mOnInfiniteScrollEvent.HasListeners)
mOnInfiniteScrollEvent(scrollDelta);
}
public void DragStart()
{
let thumbPos = GetThumbPos();
if (thumbPos.Contains(mDraggableHelper.mMouseDownX, mDraggableHelper.mMouseDownY))
{
// Is dragging thumb now
}
else
{
mDraggableHelper.CancelDrag();
}
}
public void DragEnd()
{
ScrollSetLevel(0.0);
}
public void MouseDrag(float x, float y, float dX, float dY)
{
//float parentX;
//float parentY;
//SelfToParentTranslate(x - mDraggableHelper.mMouseDownX, y - mDraggableHelper.mMouseDownY, out parentX, out parentY);
//ScrollSetLevel(GetAccelFracAt(parentX, parentY));
float accelFrac = GetAccelFracAt(mDraggableHelper.RelX, mDraggableHelper.RelY);
ScrollSetLevel(accelFrac);
}
public virtual void FixedScroll(int32 delta)
{
HandleScroll(delta * mFixedScrollAmt);
}
public virtual void Init()
{
// test config values
mFixedScrollAmt = 1;
mScrollDeltaLevelAmount = 1.0;
//mScrollMaxAccel = 1000;
mScrollMaxVelocity = 250;
}
public virtual void ResizeContent()
{
}
public void UpdateScrollPosition()
{
if (Math.Abs(mScrollVelocity) > 0.0001)
HandleScroll(mScrollVelocity * 0.01);
}
public virtual void ScrollSetLevel(double scrollLevel)
{
double setScrollLevel = scrollLevel;
setScrollLevel = Math.Min(Math.Max(-1.0, setScrollLevel), 1.0);
mScrollThumbFrac = scrollLevel;
//double vel = Math.Exp(Math.Log(mScrollMaxVelocity)*Math.Abs(mScrollThumbFrac)) - 1.0;
double vel = Math.Pow(Math.Abs(mScrollThumbFrac) * 20, 1.8);
if (mScrollThumbFrac < 0)
vel = -vel;
mScrollVelocity = vel;
ResizeContent();
}
public virtual void ScrollDeltaLevel(double scrollAmount)
{
//ScrollSetLevel(mScrollThumbFrac + scrollAmount);
HandleScroll(scrollAmount); // clicking in the bar feels better as a fixed scroll rather than changing the acceleration
}
public virtual float GetAccelFracAt(float dx, float dy)
{
return 0;
}
public virtual Rect GetThumbPos()
{
return .();
}
public override void Update()
{
base.Update();
if ((mMouseDown) && (mMouseOver))
{
mDownTick++;
if ((mDownTick > 20) && (mUpdateCnt % 5 == 0) && (!mDraggableHelper.mIsDragging))
{
let thumbPos = GetThumbPos();
if (mLastMouseY < thumbPos.Top)
ScrollDeltaLevel(-mScrollDeltaLevelAmount);
else if (mLastMouseY > thumbPos.Bottom)
ScrollDeltaLevel(mScrollDeltaLevelAmount);
}
}
UpdateScrollPosition();
}
public override void MouseMove(float x, float y)
{
base.MouseMove(x, y);
mLastMouseX = x;
mLastMouseY = y;
}
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
{
mLastMouseX = x;
mLastMouseY = y;
let thumbPos = GetThumbPos();
base.MouseDown(x, y, btn, btnCount);
if (mLastMouseY < thumbPos.Top)
ScrollDeltaLevel(-mScrollDeltaLevelAmount);
else if (mLastMouseY > thumbPos.Bottom)
ScrollDeltaLevel(mScrollDeltaLevelAmount);
mDownTick = 0;
}
public override void MouseWheel(float x, float y, int32 delta)
{
FixedScroll(-delta);
}
}
}

Some files were not shown because too many files have changed in this diff Show more