mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
411
Beef.sln
Normal file
411
Beef.sln
Normal 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
93
BeefBoot/BeefBoot.cpp
Normal 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
180
BeefBoot/BeefBoot.h
Normal 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 = ⌖
|
||||
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
177
BeefBoot/BeefBoot.vcxproj
Normal 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>
|
33
BeefBoot/BeefBoot.vcxproj.filters
Normal file
33
BeefBoot/BeefBoot.vcxproj.filters
Normal 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
841
BeefBoot/BootApp.cpp
Normal 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
80
BeefBoot/BootApp.h
Normal 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
122
BeefBoot/CMakeLists.txt
Normal 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
92
BeefBuild/BeefProj.toml
Normal 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
92
BeefBuild/BeefSpace.toml
Normal 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
250
BeefBuild/src/BuildApp.bf
Normal 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
147
BeefBuild/src/Program.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
36
BeefLibs/Beefy2D/BeefProj.toml
Normal file
36
BeefLibs/Beefy2D/BeefProj.toml
Normal 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"
|
787
BeefLibs/Beefy2D/src/BFApp.bf
Normal file
787
BeefLibs/Beefy2D/src/BFApp.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
772
BeefLibs/Beefy2D/src/BFWindow.bf
Normal file
772
BeefLibs/Beefy2D/src/BFWindow.bf
Normal 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
|
||||
}
|
32
BeefLibs/Beefy2D/src/Rand.bf
Normal file
32
BeefLibs/Beefy2D/src/Rand.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
447
BeefLibs/Beefy2D/src/Utils.bf
Normal file
447
BeefLibs/Beefy2D/src/Utils.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
14
BeefLibs/Beefy2D/src/events/DialogEvent.bf
Normal file
14
BeefLibs/Beefy2D/src/events/DialogEvent.bf
Normal 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;
|
||||
}
|
||||
}
|
15
BeefLibs/Beefy2D/src/events/DragEvent.bf
Normal file
15
BeefLibs/Beefy2D/src/events/DragEvent.bf
Normal 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;
|
||||
}
|
||||
}
|
11
BeefLibs/Beefy2D/src/events/EditEvent.bf
Normal file
11
BeefLibs/Beefy2D/src/events/EditEvent.bf
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Beefy.events
|
||||
{
|
||||
public class EditEvent : Event
|
||||
{
|
||||
//string mText;
|
||||
}
|
||||
}
|
12
BeefLibs/Beefy2D/src/events/Event.bf
Normal file
12
BeefLibs/Beefy2D/src/events/Event.bf
Normal 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;
|
||||
}
|
||||
}
|
38
BeefLibs/Beefy2D/src/events/KeyboardEvent.bf
Normal file
38
BeefLibs/Beefy2D/src/events/KeyboardEvent.bf
Normal 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;
|
||||
}
|
||||
}
|
22
BeefLibs/Beefy2D/src/events/MouseEvent.bf
Normal file
22
BeefLibs/Beefy2D/src/events/MouseEvent.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
13
BeefLibs/Beefy2D/src/events/ScrollEvent.bf
Normal file
13
BeefLibs/Beefy2D/src/events/ScrollEvent.bf
Normal 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;
|
||||
}
|
||||
}
|
9
BeefLibs/Beefy2D/src/events/WidgetParentEvent.bf
Normal file
9
BeefLibs/Beefy2D/src/events/WidgetParentEvent.bf
Normal file
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Beefy.widgets;
|
||||
|
||||
namespace Beefy.events
|
||||
{
|
||||
|
||||
}
|
493
BeefLibs/Beefy2D/src/geom/Matrix4.bf
Normal file
493
BeefLibs/Beefy2D/src/geom/Matrix4.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
18
BeefLibs/Beefy2D/src/geom/Point.bf
Normal file
18
BeefLibs/Beefy2D/src/geom/Point.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
775
BeefLibs/Beefy2D/src/geom/Quaternion.bf
Normal file
775
BeefLibs/Beefy2D/src/geom/Quaternion.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
197
BeefLibs/Beefy2D/src/geom/Rect.bf
Normal file
197
BeefLibs/Beefy2D/src/geom/Rect.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
87
BeefLibs/Beefy2D/src/geom/Vector2.bf
Normal file
87
BeefLibs/Beefy2D/src/geom/Vector2.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
247
BeefLibs/Beefy2D/src/geom/Vector3.bf
Normal file
247
BeefLibs/Beefy2D/src/geom/Vector3.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
158
BeefLibs/Beefy2D/src/gfx/Color.bf
Normal file
158
BeefLibs/Beefy2D/src/gfx/Color.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
103
BeefLibs/Beefy2D/src/gfx/ConstantDataDefinition.bf
Normal file
103
BeefLibs/Beefy2D/src/gfx/ConstantDataDefinition.bf
Normal 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);
|
||||
} */
|
||||
}
|
||||
}
|
||||
}
|
19
BeefLibs/Beefy2D/src/gfx/ConstantDataMemberAttribute.bf
Normal file
19
BeefLibs/Beefy2D/src/gfx/ConstantDataMemberAttribute.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
25
BeefLibs/Beefy2D/src/gfx/DefaultVertex.bf
Normal file
25
BeefLibs/Beefy2D/src/gfx/DefaultVertex.bf
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
88
BeefLibs/Beefy2D/src/gfx/DrawLayer.bf
Normal file
88
BeefLibs/Beefy2D/src/gfx/DrawLayer.bf
Normal 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
|
||||
}
|
881
BeefLibs/Beefy2D/src/gfx/Font.bf
Normal file
881
BeefLibs/Beefy2D/src/gfx/Font.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
1223
BeefLibs/Beefy2D/src/gfx/Graphics.bf
Normal file
1223
BeefLibs/Beefy2D/src/gfx/Graphics.bf
Normal file
File diff suppressed because it is too large
Load diff
11
BeefLibs/Beefy2D/src/gfx/IDrawable.bf
Normal file
11
BeefLibs/Beefy2D/src/gfx/IDrawable.bf
Normal 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);
|
||||
}
|
||||
}
|
283
BeefLibs/Beefy2D/src/gfx/Image.bf
Normal file
283
BeefLibs/Beefy2D/src/gfx/Image.bf
Normal 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
|
||||
}
|
205
BeefLibs/Beefy2D/src/gfx/Matrix.bf
Normal file
205
BeefLibs/Beefy2D/src/gfx/Matrix.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
391
BeefLibs/Beefy2D/src/gfx/Model.bf
Normal file
391
BeefLibs/Beefy2D/src/gfx/Model.bf
Normal 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
|
||||
}
|
14
BeefLibs/Beefy2D/src/gfx/PixelSnapping.bf
Normal file
14
BeefLibs/Beefy2D/src/gfx/PixelSnapping.bf
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Beefy.gfx
|
||||
{
|
||||
public enum PixelSnapping
|
||||
{
|
||||
Never,
|
||||
Always,
|
||||
Auto,
|
||||
Default
|
||||
}
|
||||
}
|
23
BeefLibs/Beefy2D/src/gfx/RenderCmd.bf
Normal file
23
BeefLibs/Beefy2D/src/gfx/RenderCmd.bf
Normal 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
|
||||
}
|
175
BeefLibs/Beefy2D/src/gfx/RenderState.bf
Normal file
175
BeefLibs/Beefy2D/src/gfx/RenderState.bf
Normal 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
|
||||
}
|
83
BeefLibs/Beefy2D/src/gfx/Shader.bf
Normal file
83
BeefLibs/Beefy2D/src/gfx/Shader.bf
Normal 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
|
||||
}
|
21
BeefLibs/Beefy2D/src/gfx/TexCoords.bf
Normal file
21
BeefLibs/Beefy2D/src/gfx/TexCoords.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
29
BeefLibs/Beefy2D/src/gfx/Vertex3D.bf
Normal file
29
BeefLibs/Beefy2D/src/gfx/Vertex3D.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
166
BeefLibs/Beefy2D/src/gfx/VertexDefinition.bf
Normal file
166
BeefLibs/Beefy2D/src/gfx/VertexDefinition.bf
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
25
BeefLibs/Beefy2D/src/gfx/VertexElementUsage.bf
Normal file
25
BeefLibs/Beefy2D/src/gfx/VertexElementUsage.bf
Normal 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
|
||||
}
|
||||
}
|
11
BeefLibs/Beefy2D/src/gfx/VertexLayout.bf
Normal file
11
BeefLibs/Beefy2D/src/gfx/VertexLayout.bf
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Beefy.gfx
|
||||
{
|
||||
public class VertexLayout
|
||||
{
|
||||
}
|
||||
}
|
20
BeefLibs/Beefy2D/src/gfx/VertexMemberAttribute.bf
Normal file
20
BeefLibs/Beefy2D/src/gfx/VertexMemberAttribute.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
206
BeefLibs/Beefy2D/src/res/PSDReader.bf
Normal file
206
BeefLibs/Beefy2D/src/res/PSDReader.bf
Normal 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
|
||||
}
|
184
BeefLibs/Beefy2D/src/res/ResourceManager.bf
Normal file
184
BeefLibs/Beefy2D/src/res/ResourceManager.bf
Normal 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;*/
|
||||
}
|
||||
}
|
||||
}
|
22
BeefLibs/Beefy2D/src/res/SoundBank.bf
Normal file
22
BeefLibs/Beefy2D/src/res/SoundBank.bf
Normal 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);
|
||||
}
|
||||
}*/
|
||||
}
|
24
BeefLibs/Beefy2D/src/res/SoundEvent.bf
Normal file
24
BeefLibs/Beefy2D/src/res/SoundEvent.bf
Normal 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);
|
||||
}
|
||||
}*/
|
||||
}
|
11
BeefLibs/Beefy2D/src/res/SoundGameObject.bf
Normal file
11
BeefLibs/Beefy2D/src/res/SoundGameObject.bf
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Beefy.res
|
||||
{
|
||||
public class SoundGameObject
|
||||
{
|
||||
public void* mWwiseObject;
|
||||
}
|
||||
}
|
21
BeefLibs/Beefy2D/src/res/SoundParameter.bf
Normal file
21
BeefLibs/Beefy2D/src/res/SoundParameter.bf
Normal 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;
|
||||
}
|
||||
}*/
|
||||
}
|
11
BeefLibs/Beefy2D/src/sys/SysBitmap.bf
Normal file
11
BeefLibs/Beefy2D/src/sys/SysBitmap.bf
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Beefy.sys
|
||||
{
|
||||
public class SysBitmap
|
||||
{
|
||||
public void* mNativeBFBitmap;
|
||||
}
|
||||
}
|
150
BeefLibs/Beefy2D/src/sys/SysMenu.bf
Normal file
150
BeefLibs/Beefy2D/src/sys/SysMenu.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
99
BeefLibs/Beefy2D/src/theme/ThemeFactory.bf
Normal file
99
BeefLibs/Beefy2D/src/theme/ThemeFactory.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
114
BeefLibs/Beefy2D/src/theme/dark/DarkButton.bf
Normal file
114
BeefLibs/Beefy2D/src/theme/dark/DarkButton.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
176
BeefLibs/Beefy2D/src/theme/dark/DarkCheckBox.bf
Normal file
176
BeefLibs/Beefy2D/src/theme/dark/DarkCheckBox.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
375
BeefLibs/Beefy2D/src/theme/dark/DarkComboBox.bf
Normal file
375
BeefLibs/Beefy2D/src/theme/dark/DarkComboBox.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
125
BeefLibs/Beefy2D/src/theme/dark/DarkDialog.bf
Normal file
125
BeefLibs/Beefy2D/src/theme/dark/DarkDialog.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
137
BeefLibs/Beefy2D/src/theme/dark/DarkDockingFrame.bf
Normal file
137
BeefLibs/Beefy2D/src/theme/dark/DarkDockingFrame.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
922
BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf
Normal file
922
BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
21
BeefLibs/Beefy2D/src/theme/dark/DarkIconButton.bf
Normal file
21
BeefLibs/Beefy2D/src/theme/dark/DarkIconButton.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
160
BeefLibs/Beefy2D/src/theme/dark/DarkInfiniteScrollbar.bf
Normal file
160
BeefLibs/Beefy2D/src/theme/dark/DarkInfiniteScrollbar.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
1132
BeefLibs/Beefy2D/src/theme/dark/DarkListView.bf
Normal file
1132
BeefLibs/Beefy2D/src/theme/dark/DarkListView.bf
Normal file
File diff suppressed because it is too large
Load diff
408
BeefLibs/Beefy2D/src/theme/dark/DarkMenu.bf
Normal file
408
BeefLibs/Beefy2D/src/theme/dark/DarkMenu.bf
Normal 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:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
192
BeefLibs/Beefy2D/src/theme/dark/DarkScrollbar.bf
Normal file
192
BeefLibs/Beefy2D/src/theme/dark/DarkScrollbar.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
194
BeefLibs/Beefy2D/src/theme/dark/DarkSmartEdit.bf
Normal file
194
BeefLibs/Beefy2D/src/theme/dark/DarkSmartEdit.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
755
BeefLibs/Beefy2D/src/theme/dark/DarkTabbedView.bf
Normal file
755
BeefLibs/Beefy2D/src/theme/dark/DarkTabbedView.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
530
BeefLibs/Beefy2D/src/theme/dark/DarkTheme.bf
Normal file
530
BeefLibs/Beefy2D/src/theme/dark/DarkTheme.bf
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
398
BeefLibs/Beefy2D/src/theme/dark/DarkTooltip.bf
Normal file
398
BeefLibs/Beefy2D/src/theme/dark/DarkTooltip.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
161
BeefLibs/Beefy2D/src/theme/dark/DarkVirtualListViewItem.bf
Normal file
161
BeefLibs/Beefy2D/src/theme/dark/DarkVirtualListViewItem.bf
Normal 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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
105
BeefLibs/Beefy2D/src/utils/BeefPerf.bf
Normal file
105
BeefLibs/Beefy2D/src/utils/BeefPerf.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
28
BeefLibs/Beefy2D/src/utils/DisposeProxy.bf
Normal file
28
BeefLibs/Beefy2D/src/utils/DisposeProxy.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
12
BeefLibs/Beefy2D/src/utils/ISerializable.bf
Normal file
12
BeefLibs/Beefy2D/src/utils/ISerializable.bf
Normal 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);
|
||||
}
|
||||
}
|
899
BeefLibs/Beefy2D/src/utils/IdSpan.bf
Normal file
899
BeefLibs/Beefy2D/src/utils/IdSpan.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
BeefLibs/Beefy2D/src/utils/ManualBreak.bf
Normal file
17
BeefLibs/Beefy2D/src/utils/ManualBreak.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
79
BeefLibs/Beefy2D/src/utils/PerfTimer.bf
Normal file
79
BeefLibs/Beefy2D/src/utils/PerfTimer.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
74
BeefLibs/Beefy2D/src/utils/SmoothValue.bf
Normal file
74
BeefLibs/Beefy2D/src/utils/SmoothValue.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
2552
BeefLibs/Beefy2D/src/utils/StructuredData.bf
Normal file
2552
BeefLibs/Beefy2D/src/utils/StructuredData.bf
Normal file
File diff suppressed because it is too large
Load diff
161
BeefLibs/Beefy2D/src/utils/TextSearcher.bf
Normal file
161
BeefLibs/Beefy2D/src/utils/TextSearcher.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
311
BeefLibs/Beefy2D/src/utils/UndoManager.bf
Normal file
311
BeefLibs/Beefy2D/src/utils/UndoManager.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
41
BeefLibs/Beefy2D/src/widgets/ButtonWidget.bf
Normal file
41
BeefLibs/Beefy2D/src/widgets/ButtonWidget.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
49
BeefLibs/Beefy2D/src/widgets/Checkbox.bf
Normal file
49
BeefLibs/Beefy2D/src/widgets/Checkbox.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
11
BeefLibs/Beefy2D/src/widgets/ComboBox.bf
Normal file
11
BeefLibs/Beefy2D/src/widgets/ComboBox.bf
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Beefy.widgets
|
||||
{
|
||||
public class ComboBox : Widget
|
||||
{
|
||||
public bool mDisabled;
|
||||
}
|
||||
}
|
1160
BeefLibs/Beefy2D/src/widgets/Composition.bf
Normal file
1160
BeefLibs/Beefy2D/src/widgets/Composition.bf
Normal file
File diff suppressed because it is too large
Load diff
15
BeefLibs/Beefy2D/src/widgets/DesignEditableAttribute.bf
Normal file
15
BeefLibs/Beefy2D/src/widgets/DesignEditableAttribute.bf
Normal 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; }
|
||||
}
|
||||
}
|
383
BeefLibs/Beefy2D/src/widgets/Dialog.bf
Normal file
383
BeefLibs/Beefy2D/src/widgets/Dialog.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
185
BeefLibs/Beefy2D/src/widgets/DockedWidget.bf
Normal file
185
BeefLibs/Beefy2D/src/widgets/DockedWidget.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
989
BeefLibs/Beefy2D/src/widgets/DockingFrame.bf
Normal file
989
BeefLibs/Beefy2D/src/widgets/DockingFrame.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
185
BeefLibs/Beefy2D/src/widgets/DragHelper.bf
Normal file
185
BeefLibs/Beefy2D/src/widgets/DragHelper.bf
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
3425
BeefLibs/Beefy2D/src/widgets/EditWidget.bf
Normal file
3425
BeefLibs/Beefy2D/src/widgets/EditWidget.bf
Normal file
File diff suppressed because it is too large
Load diff
19
BeefLibs/Beefy2D/src/widgets/IMenu.bf
Normal file
19
BeefLibs/Beefy2D/src/widgets/IMenu.bf
Normal 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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
24
BeefLibs/Beefy2D/src/widgets/ImageWidget.bf
Normal file
24
BeefLibs/Beefy2D/src/widgets/ImageWidget.bf
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
246
BeefLibs/Beefy2D/src/widgets/InfiniteScrollbar.bf
Normal file
246
BeefLibs/Beefy2D/src/widgets/InfiniteScrollbar.bf
Normal 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
Loading…
Add table
Add a link
Reference in a new issue