From 183c7bfcea7192afde96f8c4f9f5cf548d65cf3b Mon Sep 17 00:00:00 2001 From: werelone <569629550@qq.com> Date: Sun, 10 Sep 2017 23:56:52 +0800 Subject: [PATCH] The earliest release version --- .gitignore | 3 + Easy2D.sln | 43 ++ Easy2D/Application.cpp | 368 +++++++++++ Easy2D/Easy2D.vcxproj | 374 ++++++++++++ Easy2D/Easy2D.vcxproj.filters | 126 ++++ Easy2D/Easy2D.vcxproj.user | 4 + Easy2D/EasyX/easyx.h | 321 ++++++++++ Easy2D/EasyX/x86/EasyXa.lib | Bin 0 -> 184974 bytes Easy2D/EasyX/x86/EasyXw.lib | Bin 0 -> 187270 bytes Easy2D/FreePool.cpp | 39 ++ Easy2D/Msg/KeyMsg.cpp | 172 ++++++ Easy2D/Msg/MouseMsg.cpp | 130 ++++ Easy2D/Node/BatchNode.cpp | 115 ++++ Easy2D/Node/Button/Button.cpp | 65 ++ Easy2D/Node/Button/ImageButton.cpp | 167 +++++ Easy2D/Node/Button/TextButton.cpp | 167 +++++ Easy2D/Node/Image.cpp | 181 ++++++ Easy2D/Node/MouseNode.cpp | 109 ++++ Easy2D/Node/Node.cpp | 92 +++ Easy2D/Node/Shape/Circle.cpp | 43 ++ Easy2D/Node/Shape/Rectangle.cpp | 61 ++ Easy2D/Node/Shape/Shape.cpp | 56 ++ Easy2D/Node/Sprite/Sprite.cpp | 0 Easy2D/Node/Sprite/SpriteFrame.cpp | 0 Easy2D/Node/Text.cpp | 99 +++ Easy2D/Object.cpp | 21 + Easy2D/Scene.cpp | 102 ++++ Easy2D/Style/Color.cpp | 56 ++ Easy2D/Style/FillStyle.cpp | 1 + Easy2D/Style/FontStyle.cpp | 97 +++ Easy2D/Style/LineStyle.cpp | 1 + Easy2D/Tool/FileUtils.cpp | 45 ++ Easy2D/Tool/MusicUtils.cpp | 458 ++++++++++++++ Easy2D/Tool/Timer.cpp | 183 ++++++ Easy2D/easy2d.h | 946 +++++++++++++++++++++++++++++ 35 files changed, 4645 insertions(+) create mode 100644 .gitignore create mode 100644 Easy2D.sln create mode 100644 Easy2D/Application.cpp create mode 100644 Easy2D/Easy2D.vcxproj create mode 100644 Easy2D/Easy2D.vcxproj.filters create mode 100644 Easy2D/Easy2D.vcxproj.user create mode 100644 Easy2D/EasyX/easyx.h create mode 100644 Easy2D/EasyX/x86/EasyXa.lib create mode 100644 Easy2D/EasyX/x86/EasyXw.lib create mode 100644 Easy2D/FreePool.cpp create mode 100644 Easy2D/Msg/KeyMsg.cpp create mode 100644 Easy2D/Msg/MouseMsg.cpp create mode 100644 Easy2D/Node/BatchNode.cpp create mode 100644 Easy2D/Node/Button/Button.cpp create mode 100644 Easy2D/Node/Button/ImageButton.cpp create mode 100644 Easy2D/Node/Button/TextButton.cpp create mode 100644 Easy2D/Node/Image.cpp create mode 100644 Easy2D/Node/MouseNode.cpp create mode 100644 Easy2D/Node/Node.cpp create mode 100644 Easy2D/Node/Shape/Circle.cpp create mode 100644 Easy2D/Node/Shape/Rectangle.cpp create mode 100644 Easy2D/Node/Shape/Shape.cpp create mode 100644 Easy2D/Node/Sprite/Sprite.cpp create mode 100644 Easy2D/Node/Sprite/SpriteFrame.cpp create mode 100644 Easy2D/Node/Text.cpp create mode 100644 Easy2D/Object.cpp create mode 100644 Easy2D/Scene.cpp create mode 100644 Easy2D/Style/Color.cpp create mode 100644 Easy2D/Style/FillStyle.cpp create mode 100644 Easy2D/Style/FontStyle.cpp create mode 100644 Easy2D/Style/LineStyle.cpp create mode 100644 Easy2D/Tool/FileUtils.cpp create mode 100644 Easy2D/Tool/MusicUtils.cpp create mode 100644 Easy2D/Tool/Timer.cpp create mode 100644 Easy2D/easy2d.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2e612965 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# ignore all files in the /Easy2D/** directory +Easy2D/Win32/ +Easy2D/x64/ \ No newline at end of file diff --git a/Easy2D.sln b/Easy2D.sln new file mode 100644 index 00000000..6b3b67bc --- /dev/null +++ b/Easy2D.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Easy2D", "Easy2D\Easy2D.vcxproj", "{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + DebugW|x64 = DebugW|x64 + DebugW|x86 = DebugW|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + ReleaseW|x64 = ReleaseW|x64 + ReleaseW|x86 = ReleaseW|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|x64.ActiveCfg = Debug|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|x64.Build.0 = Debug|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|x86.ActiveCfg = Debug|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|x86.Build.0 = Debug|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.DebugW|x64.ActiveCfg = DebugW|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.DebugW|x64.Build.0 = DebugW|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.DebugW|x86.ActiveCfg = DebugW|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.DebugW|x86.Build.0 = DebugW|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Release|x64.ActiveCfg = Release|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Release|x64.Build.0 = Release|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Release|x86.ActiveCfg = Release|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Release|x86.Build.0 = Release|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.ReleaseW|x64.ActiveCfg = ReleaseW|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.ReleaseW|x64.Build.0 = ReleaseW|x64 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.ReleaseW|x86.ActiveCfg = ReleaseW|Win32 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.ReleaseW|x86.Build.0 = ReleaseW|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FAC2BE2F-19AF-477A-8DC6-4645E66868A4} + EndGlobalSection +EndGlobal diff --git a/Easy2D/Application.cpp b/Easy2D/Application.cpp new file mode 100644 index 00000000..a0abbb56 --- /dev/null +++ b/Easy2D/Application.cpp @@ -0,0 +1,368 @@ +#include "easy2d.h" +#include "EasyX\easyx.h" +#include +#include +#include +#pragma comment(lib, "imm32.lib") +#include +#pragma comment(lib, "winmm.lib") + + +// Application Ψһʵ +static Application * s_pInstance = nullptr; +// ԭ +static int originX = 0; +static int originY = 0; + +Application::Application() : + m_currentScene(nullptr), + m_nextScene(nullptr), + m_bRunning(false), + m_bPause(false), + m_nWidth(0), + m_nHeight(0), + m_nWindowMode(0) +{ + assert(!s_pInstance); // ͬʱ Application ʵ + s_pInstance = this; // ʵ + setFPS(60); // Ĭ FPS Ϊ 60 +} + +Application::~Application() +{ + destory(); // Application +} + +Application * Application::get() +{ + assert(s_pInstance); // ʵ + return s_pInstance; // ȡ Application Ψһʵ +} + +void Application::setOrigin(int originX, int originY) +{ + ::originX = originX; + ::originY = originY; + setorigin(originX, originY); +} + +int Application::getOriginX() +{ + return ::originX; +} + +int Application::getOriginY() +{ + return ::originY; +} + +int Application::run() +{ + // ͼ + BeginBatchDraw(); + // ޸ʱ侫 + timeBeginPeriod(1); + // ȡ CPU ÿδ + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + // ʱ + LARGE_INTEGER nLast; + LARGE_INTEGER nNow; + // ¼ǰʱ + QueryPerformanceCounter(&nLast); + // ʱ + LONGLONG interval = 0LL; + // ʱ + LONG waitMS = 0L; + // صĴʾ + ShowWindow(GetHWnd(), SW_NORMAL); + // Ϸ + m_bRunning = true; + + // ѭ + while (m_bRunning) + { + // ȡǰʱ + QueryPerformanceCounter(&nNow); + // ʱ + interval = nNow.QuadPart - nLast.QuadPart; + // жϼʱǷ㹻 + if (interval >= m_nAnimationInterval.QuadPart) + { + // ¼ǰʱ + nLast.QuadPart = nNow.QuadPart; + // ִϷ߼ + _mainLoop(); + } + else + { + // ʱ + waitMS = LONG((m_nAnimationInterval.QuadPart - interval) * 1000LL / freq.QuadPart) - 1L; + // ̣߳ͷ CPU ռ + if (waitMS > 1L) + Sleep(waitMS); + } + } + // ֹͣͼ + EndBatchDraw(); + // رմ + close(); + // ͷڴռ + destory(); + // ʱ侫 + timeEndPeriod(1); + + return 0; +} + +void Application::_initGraph() +{ + // ͼ + initgraph(m_nWidth, m_nHeight, m_nWindowMode); + // صǰڣֹڼؽ׶ʾڴڣ + ShowWindow(GetHWnd(), SW_HIDE); + // ȡĻֱ + int screenWidth = GetSystemMetrics(SM_CXSCREEN); + int screenHeight = GetSystemMetrics(SM_CYSCREEN); + // ȡڴС + CRect rcWindow; + GetWindowRect(GetHWnd(), &rcWindow); + // ôĻ + SetWindowPos(GetHWnd(), HWND_TOP, + (screenWidth - rcWindow.Size().cx) / 2, + (screenHeight - rcWindow.Size().cy) / 2, + rcWindow.Size().cx, + rcWindow.Size().cy, + SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOSIZE); + // 뷨 + ImmAssociateContext(GetHWnd(), NULL); + // ûͼ + reset(); + // ôڱ + if (m_sTitle.empty()) + { + // 浱ǰ + TCHAR title[31]; + GetWindowText(GetHWnd(), title, 30); + m_sTitle = title; + } + else + { + setWindowText(m_sTitle); + } +} + +void Application::_mainLoop() +{ + // Ϸͣ + if (m_bPause) + { + return; + } + // һ + if (m_nextScene) + { + _enterNextScene(); + } + // Եǰǿ + assert(m_currentScene); + + cleardevice(); // ջ + m_currentScene->_onDraw(); // Ƶǰ + FlushBatchDraw(); // ˢ» + + // ִг + MouseMsg::__exec(); // + KeyMsg::__exec(); // ̰ + Timer::__exec(); // ʱִг + FreePool::__flush(); // ˢڴ +} + +void Application::createWindow(int width, int height, int mode) +{ + // 洰Ϣ + m_nWidth = width; + m_nHeight = height; + m_nWindowMode = mode; + // + _initGraph(); +} + +void Application::createWindow(tstring title, int width, int height, int mode) +{ + // 洰Ϣ + m_nWidth = width; + m_nHeight = height; + m_nWindowMode = mode; + m_sTitle = title; + // + _initGraph(); +} + +void Application::setWindowSize(int width, int height) +{ + // Ϸʱ޸ĴڴС + assert(m_bRunning); + + // + closegraph(); + /* ڻᵼڴռüӣҲ EasyX BUG yangw80 */ + initgraph(width, height, m_nWindowMode); + + /* EasyX ֧ Windows API ޸ĴڴС */ + ///////////////////////////////////////////////////////////////////////////////// + // // ȡĻֱ + // int screenWidth = GetSystemMetrics(SM_CXSCREEN); + // int screenHeight = GetSystemMetrics(SM_CYSCREEN); + // // ȡڴС˵ + // CRect rcWindow; + // GetWindowRect(GetHWnd(), &rcWindow); + // // ȡͻС + // CRect rcClient; + // GetClientRect(GetHWnd(), &rcClient); + // // ߿С + // width += (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left); + // height += (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top); + // // ޸ĴڴСôĻ + // SetWindowPos( + // GetHWnd(), + // HWND_TOP, + // (screenWidth - width) / 2, + // (screenHeight - height) / 2, + // width, + // height, + // SWP_SHOWWINDOW | SWP_NOREDRAW); + ////////////////////////////////////////////////////////////////////////////////// +} + +void Application::setWindowText(tstring title) +{ + // ôڱ + SetWindowText(GetHWnd(), title.c_str()); + // 浱ǰ⣬޸ĴڴСʱָ + m_sTitle = title; +} + +void Application::close() +{ + // رջͼ + closegraph(); +} + +void Application::enterScene(Scene * scene, bool save) +{ + // һָ + m_nextScene = scene; + // лʱǷ񱣴浱ǰ + m_bSaveScene = save; +} + +void Application::backScene() +{ + // ջȡָ룬Ϊһ + m_nextScene = m_sceneStack.top(); + // 浱ǰ + m_bSaveScene = false; +} + +void Application::_enterNextScene() +{ + // һջ˵ڷһ + if (m_sceneStack.size() && m_nextScene == m_sceneStack.top()) + { + m_sceneStack.pop(); // ɾջ + } + + if (m_bSaveScene) + { + m_sceneStack.push(m_currentScene); // Ҫ浱ǰָŵջ + } + else + { + SAFE_DELETE(m_currentScene); // ɾǰ + } + + m_currentScene = m_nextScene; // л + m_nextScene = nullptr; // һÿ +} + +void Application::quit() +{ + m_bRunning = false; +} + +void Application::end() +{ + m_bRunning = false; +} + +void Application::pause() +{ + m_bPause = true; +} + +bool Application::isRunning() +{ + return m_bRunning && !m_bPause; +} + +void Application::reset() +{ + // ûͼ + graphdefaults(); + setbkmode(TRANSPARENT); + setbkcolor(Color::black); +} + +Scene * Application::getCurrentScene() +{ + // ȡǰָ + return m_currentScene; +} + +LPCTSTR easy2d::Application::getVersion() +{ + return _T("1.0.0"); +} + +void Application::setFPS(DWORD fps) +{ + // û֡ʣԺΪλ + LARGE_INTEGER nFreq; + QueryPerformanceFrequency(&nFreq); + m_nAnimationInterval.QuadPart = (LONGLONG)(1.0 / fps * nFreq.QuadPart); +} + +int Application::getWidth() const +{ + return m_nWidth; +} + +int Application::getHeight() const +{ + return m_nHeight; +} + +void Application::free() +{ + // ͷųڴ + SAFE_DELETE(m_currentScene); + SAFE_DELETE(m_nextScene); + // ճջ + while (m_sceneStack.size()) + { + auto temp = m_sceneStack.top(); + SAFE_DELETE(temp); + m_sceneStack.pop(); + } + // ɾжʱ + Timer::clearAllTimers(); +} + +void Application::destory() +{ + // ͷڴ + free(); + // ʵָÿ + s_pInstance = nullptr; +} diff --git a/Easy2D/Easy2D.vcxproj b/Easy2D/Easy2D.vcxproj new file mode 100644 index 00000000..da303326 --- /dev/null +++ b/Easy2D/Easy2D.vcxproj @@ -0,0 +1,374 @@ + + + + + DebugW + Win32 + + + DebugW + x64 + + + Debug + Win32 + + + ReleaseW + Win32 + + + ReleaseW + x64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF} + Win32Proj + Easy2D + 10.0.15063.0 + + + + StaticLibrary + true + v141 + MultiByte + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + false + MultiByte + + + StaticLibrary + false + v141 + false + Unicode + + + StaticLibrary + true + v141 + MultiByte + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + false + MultiByte + + + StaticLibrary + false + v141 + false + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + Easy2Dd + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + true + Easy2Ddw + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + true + Easy2Dd + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + true + Easy2Ddw + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + false + Easy2D + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + false + Easy2Dw + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + false + Easy2D + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + false + Easy2Dw + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + false + + + EasyXa.lib;GdiPlus.lib + EasyX\x86 + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + EasyXw.lib;GdiPlus.lib + + + EasyX\x86 + + + false + + + + + NotUsing + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + EasyX\x64 + EasyXa.lib;GdiPlus.lib + + + + + NotUsing + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + EasyXw.lib;GdiPlus.lib + EasyX\x64 + + + + + NotUsing + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + EasyX\x86 + EasyXa.lib;GdiPlus.lib + + + + + NotUsing + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + EasyXw.lib;GdiPlus.lib + EasyX\x86 + + + + + + + NotUsing + Level3 + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + EasyX\x64 + EasyXa.lib;GdiPlus.lib + + + + + NotUsing + Level3 + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + EasyXw.lib;GdiPlus.lib + EasyX\x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Easy2D/Easy2D.vcxproj.filters b/Easy2D/Easy2D.vcxproj.filters new file mode 100644 index 00000000..e17f1845 --- /dev/null +++ b/Easy2D/Easy2D.vcxproj.filters @@ -0,0 +1,126 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {18e7fd5c-0935-47bb-9a2e-38da40377f7d} + + + {682a1a3c-39d8-4ac9-ba03-fa90c089c9ab} + + + {d6778635-8947-4f9b-9388-dd088642b5b2} + + + {e5ec6183-113b-4140-8285-18b18ea37d15} + + + {051f9343-e5a5-4491-8110-f13fc27c3827} + + + {065a3244-7169-4a45-bc9f-f2a80d8a9759} + + + {72dbabab-8278-4ee4-917f-bfffb474a51b} + + + + + + + + 源文件 + + + 源文件 + + + 源文件\Style + + + 源文件\Tool + + + 源文件\Tool + + + 源文件\Tool + + + 源文件\Style + + + 源文件\Node + + + 源文件\Node + + + 源文件\Node + + + 源文件\Node + + + 源文件\Node\Sprite + + + 源文件\Node\Sprite + + + 源文件\Node\Shape + + + 源文件\Node\Shape + + + 源文件\Node\Shape + + + 源文件\Node\Button + + + 源文件\Node + + + 源文件\Node\Button + + + 源文件\Node\Button + + + 源文件\Style + + + 源文件 + + + 源文件 + + + 源文件\Style + + + 源文件\Msg + + + 源文件\Msg + + + + + 头文件 + + + \ No newline at end of file diff --git a/Easy2D/Easy2D.vcxproj.user b/Easy2D/Easy2D.vcxproj.user new file mode 100644 index 00000000..be250787 --- /dev/null +++ b/Easy2D/Easy2D.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Easy2D/EasyX/easyx.h b/Easy2D/EasyX/easyx.h new file mode 100644 index 00000000..d5a35fac --- /dev/null +++ b/Easy2D/EasyX/easyx.h @@ -0,0 +1,321 @@ +/****************************************************** + * EasyX Library for C++ (Ver:20170827(beta)) + * http://www.easyx.cn + * + * EasyX.h + * VC ʵּ򵥵Ļͼ + ******************************************************/ + +#pragma once + +#ifndef WINVER +#define WINVER 0x0400 // Specifies that the minimum required platform is Windows 95 and Windows NT 4.0. +#endif + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 // Specifies that the minimum required platform is Windows 2000. +#endif + +#ifndef _WIN32_WINDOWS +#define _WIN32_WINDOWS 0x0410 // Specifies that the minimum required platform is Windows 98. +#endif + + +#ifndef __cplusplus +#error EasyX is only for C++ +#endif + + +#include +#include + +// ͼڳʼ +#define SHOWCONSOLE 1 // ͼδʱ̨ʾ +#define NOCLOSE 2 // ûйرչ +#define NOMINIMIZE 4 // ûС + +// ɫ +#define BLACK 0 +#define BLUE 0xAA0000 +#define GREEN 0x00AA00 +#define CYAN 0xAAAA00 +#define RED 0x0000AA +#define MAGENTA 0xAA00AA +#define BROWN 0x0055AA +#define LIGHTGRAY 0xAAAAAA +#define DARKGRAY 0x555555 +#define LIGHTBLUE 0xFF5555 +#define LIGHTGREEN 0x55FF55 +#define LIGHTCYAN 0xFFFF55 +#define LIGHTRED 0x5555FF +#define LIGHTMAGENTA 0xFF55FF +#define YELLOW 0x55FFFF +#define WHITE 0xFFFFFF + +// ɫת +#define BGR(color) ( (((color) & 0xFF) << 16) | ((color) & 0xFF00FF00) | (((color) & 0xFF0000) >> 16) ) + + +class IMAGE; + +// ߵʽ +class LINESTYLE +{ +public: + LINESTYLE(); + LINESTYLE(const LINESTYLE &style); + LINESTYLE& operator = (const LINESTYLE &style); // ֵغ + virtual ~LINESTYLE(); + + DWORD style; + DWORD thickness; + DWORD *puserstyle; + DWORD userstylecount; +}; + +class FILLSTYLE +{ +public: + FILLSTYLE(); + FILLSTYLE(const FILLSTYLE &style); + FILLSTYLE& operator = (const FILLSTYLE &style); // ֵغ + virtual ~FILLSTYLE(); + + int style; // ʽ + long hatch; // ͼʽ + IMAGE* ppattern; // ͼ +}; + +// ͼ +class IMAGE +{ +public: + int getwidth() const; // ȡĿ + int getheight() const; // ȡĸ߶ + +private: + int width, height; // Ŀ + HBITMAP m_hBmp; + HDC m_hMemDC; + int m_MemCurX; // ǰX + int m_MemCurY; // ǰY + float m_data[6]; + COLORREF m_LineColor; // ǰɫ + COLORREF m_FillColor; // ǰɫ + COLORREF m_TextColor; // ǰɫ + COLORREF m_BkColor; // ǰɫ + DWORD* m_pBuffer; // ͼڴ + + LINESTYLE m_LineStyle; // ʽ + FILLSTYLE m_FillStyle; // ʽ + + virtual void SetDefault(); // ΪĬ״̬ + +public: + IMAGE(int _width = 0, int _height = 0); // ͼ + IMAGE(const IMAGE &img); // 캯 + IMAGE& operator = (const IMAGE &img); // ֵغ + virtual ~IMAGE(); + virtual void Resize(int _width, int _height); // ߴ +}; + + + +// ͼģʽغ + +HWND initgraph(int width, int height, int flag = NULL); // ʼͼλ +void closegraph(); // رͼλ + +// ͼ + +void cleardevice(); // +void setcliprgn(HRGN hrgn); // õǰͼ豸IJü +void clearcliprgn(); // üĻ + +void getlinestyle(LINESTYLE* pstyle); // ȡǰʽ +void setlinestyle(const LINESTYLE* pstyle); // õǰʽ +void setlinestyle(int style, int thickness = 1, const DWORD *puserstyle = NULL, DWORD userstylecount = 0); // õǰʽ +void getfillstyle(FILLSTYLE* pstyle); // ȡǰʽ +void setfillstyle(const FILLSTYLE* pstyle); // õǰʽ +void setfillstyle(int style, long hatch = NULL, IMAGE* ppattern = NULL); // õǰʽ +void setfillstyle(BYTE* ppattern8x8); // õǰʽ + +void setorigin(int x, int y); // ԭ +void getaspectratio(float *pxasp, float *pyasp); // ȡǰ +void setaspectratio(float xasp, float yasp); // õǰ + +int getrop2(); // ȡǰĶԪդģʽ +void setrop2(int mode); // ǰĶԪդģʽ +int getpolyfillmode(); // ȡģʽ +void setpolyfillmode(int mode); // öģʽ + +void graphdefaults(); // лͼΪĬֵ + +COLORREF getlinecolor(); // ȡǰɫ +void setlinecolor(COLORREF color); // õǰɫ +COLORREF gettextcolor(); // ȡǰɫ +void settextcolor(COLORREF color); // õǰɫ +COLORREF getfillcolor(); // ȡǰɫ +void setfillcolor(COLORREF color); // õǰɫ +COLORREF getbkcolor(); // ȡǰͼɫ +void setbkcolor(COLORREF color); // õǰͼɫ +int getbkmode(); // ȡģʽ +void setbkmode(int mode); // ñģʽ + +// ɫģת +COLORREF RGBtoGRAY(COLORREF rgb); +void RGBtoHSL(COLORREF rgb, float *H, float *S, float *L); +void RGBtoHSV(COLORREF rgb, float *H, float *S, float *V); +COLORREF HSLtoRGB(float H, float S, float L); +COLORREF HSVtoRGB(float H, float S, float V); + + +// ͼ + +COLORREF getpixel(int x, int y); // ȡɫ +void putpixel(int x, int y, COLORREF color); // + +void moveto(int x, int y); // ƶǰ() +void moverel(int dx, int dy); // ƶǰ() + +void line(int x1, int y1, int x2, int y2); // +void linerel(int dx, int dy); // () +void lineto(int x, int y); // () + +void rectangle (int left, int top, int right, int bottom); // +void fillrectangle (int left, int top, int right, int bottom); // (б߿) +void solidrectangle(int left, int top, int right, int bottom); // (ޱ߿) +void clearrectangle(int left, int top, int right, int bottom); // վ + +void circle (int x, int y, int radius); // Բ +void fillcircle (int x, int y, int radius); // Բ(б߿) +void solidcircle(int x, int y, int radius); // Բ(ޱ߿) +void clearcircle(int x, int y, int radius); // Բ + +void ellipse (int left, int top, int right, int bottom); // Բ +void fillellipse (int left, int top, int right, int bottom); // Բ(б߿) +void solidellipse(int left, int top, int right, int bottom); // Բ(ޱ߿) +void clearellipse(int left, int top, int right, int bottom); // Բ + +void roundrect (int left, int top, int right, int bottom, int ellipsewidth, int ellipseheight); // ԲǾ +void fillroundrect (int left, int top, int right, int bottom, int ellipsewidth, int ellipseheight); // ԲǾ(б߿) +void solidroundrect(int left, int top, int right, int bottom, int ellipsewidth, int ellipseheight); // ԲǾ(ޱ߿) +void clearroundrect(int left, int top, int right, int bottom, int ellipsewidth, int ellipseheight); // ԲǾ + +void arc (int left, int top, int right, int bottom, double stangle, double endangle); // Բ(ʼǶȺֹǶΪ) +void pie (int left, int top, int right, int bottom, double stangle, double endangle); // Բ(ʼǶȺֹǶΪ) +void fillpie (int left, int top, int right, int bottom, double stangle, double endangle); // Բ(б߿) +void solidpie(int left, int top, int right, int bottom, double stangle, double endangle); // Բ(ޱ߿) +void clearpie(int left, int top, int right, int bottom, double stangle, double endangle); // Բ + +void polyline (const POINT *points, int num); // +void polygon (const POINT *points, int num); // +void fillpolygon (const POINT *points, int num); // Ķ(б߿) +void solidpolygon(const POINT *points, int num); // Ķ(ޱ߿) +void clearpolygon(const POINT *points, int num); // ն + +void floodfill(int x, int y, int border); // + + + +// غ + +void outtext(LPCTSTR str); // ڵǰλַ +void outtext(TCHAR c); // ڵǰλַ +void outtextxy(int x, int y, LPCTSTR str); // ָλַ +void outtextxy(int x, int y, TCHAR c); // ָλַ +int textwidth(LPCTSTR str); // ȡַռõؿ +int textwidth(TCHAR c); // ȡַռõؿ +int textheight(LPCTSTR str); // ȡַռõظ +int textheight(TCHAR c); // ȡַռõظ +int drawtext(LPCTSTR str, RECT* pRect, UINT uFormat); // ָָʽַ +int drawtext(TCHAR c, RECT* pRect, UINT uFormat); // ָָʽַ + +// õǰʽ() +// nHeight: ַƽ߶ȣ +// nWidth: ַƽ(0 ʾӦ) +// lpszFace: ƣ +// nEscapement: ַдǶ(λ 0.1 ) +// nOrientation: ÿַдǶ(λ 0.1 ) +// nWeight: ַıʻϸ(0 ʾĬϴϸ) +// bItalic: Ƿб壻 +// bUnderline: Ƿ»ߣ +// bStrikeOut: Ƿɾߣ +// fbCharSet: ַָ +// fbOutPrecision: ֵָȣ +// fbClipPrecision: ֵָļȣ +// fbQuality: ֵָ +// fbPitchAndFamily: ָԳ淽ʽϵС +void settextstyle(int nHeight, int nWidth, LPCTSTR lpszFace); +void settextstyle(int nHeight, int nWidth, LPCTSTR lpszFace, int nEscapement, int nOrientation, int nWeight, bool bItalic, bool bUnderline, bool bStrikeOut); +void settextstyle(int nHeight, int nWidth, LPCTSTR lpszFace, int nEscapement, int nOrientation, int nWeight, bool bItalic, bool bUnderline, bool bStrikeOut, BYTE fbCharSet, BYTE fbOutPrecision, BYTE fbClipPrecision, BYTE fbQuality, BYTE fbPitchAndFamily); +void settextstyle(const LOGFONT *font); // õǰʽ +void gettextstyle(LOGFONT *font); // ȡǰʽ + + + +// ͼ +void loadimage(IMAGE *pDstImg, LPCTSTR pImgFile, int nWidth = 0, int nHeight = 0, bool bResize = false); // ͼƬļȡͼ(bmp/jpg/gif/emf/wmf) +void loadimage(IMAGE *pDstImg, LPCTSTR pResType, LPCTSTR pResName, int nWidth = 0, int nHeight = 0, bool bResize = false); // Դļȡͼ(bmp/jpg/gif/emf/wmf) +void saveimage(LPCTSTR pImgFile, IMAGE* pImg = NULL); // ͼ +void getimage(IMAGE *pDstImg, int srcX, int srcY, int srcWidth, int srcHeight); // ӵǰͼ豸ȡͼ +void putimage(int dstX, int dstY, const IMAGE *pSrcImg, DWORD dwRop = SRCCOPY); // ͼĻ +void putimage(int dstX, int dstY, int dstWidth, int dstHeight, const IMAGE *pSrcImg, int srcX, int srcY, DWORD dwRop = SRCCOPY); // ͼĻ(ָ) +void rotateimage(IMAGE *dstimg, IMAGE *srcimg, double radian, COLORREF bkcolor = BLACK, bool autosize = false, bool highquality = true);// תͼ +void Resize(IMAGE* pImg, int width, int height); // ͼ豸ĴС +DWORD* GetImageBuffer(IMAGE* pImg = NULL); // ȡͼ豸Դָ +IMAGE* GetWorkingImage(); // ȡǰͼ豸 +void SetWorkingImage(IMAGE* pImg = NULL); // õǰͼ豸 +HDC GetImageHDC(IMAGE* pImg = NULL); // ȡͼ豸(HDC) + + +// + +int getwidth(); // ȡͼ +int getheight(); // ȡͼ߶ +int getx(); // ȡǰ x +int gety(); // ȡǰ y + +void BeginBatchDraw(); // ʼ +void FlushBatchDraw(); // ִδɵĻ +void FlushBatchDraw(int left, int top, int right, int bottom); // ִָδɵĻ +void EndBatchDraw(); // ƣִδɵĻ +void EndBatchDraw(int left, int top, int right, int bottom); // ƣִָδɵĻ + +HWND GetHWnd(); // ȡͼھ(HWND) +TCHAR* GetEasyXVer(); // ȡ EasyX ǰ汾 + +// ȡû +bool InputBox(LPTSTR pString, int nMaxCount, LPCTSTR pPrompt = NULL, LPCTSTR pTitle = NULL, LPCTSTR pDefault = NULL, int width = 0, int height = 0, bool bOnlyOK = true); + + + +// Ϣ +// ֧Ϣ +// WM_MOUSEMOVE ƶ +// WM_MOUSEWHEEL ֲ +// WM_LBUTTONDOWN +// WM_LBUTTONUP +// WM_LBUTTONDBLCLK ˫ +// WM_MBUTTONDOWN м +// WM_MBUTTONUP м +// WM_MBUTTONDBLCLK м˫ +// WM_RBUTTONDOWN Ҽ +// WM_RBUTTONUP Ҽ +// WM_RBUTTONDBLCLK Ҽ˫ +struct MOUSEMSG +{ + UINT uMsg; // ǰϢ + bool mkCtrl; // Ctrl Ƿ + bool mkShift; // Shift Ƿ + bool mkLButton; // Ƿ + bool mkMButton; // мǷ + bool mkRButton; // ҼǷ + short x; // ǰ x + short y; // ǰ y + short wheel; // ֵֹ (120 ı) +}; + +bool MouseHit(); // ǷϢ +MOUSEMSG GetMouseMsg(); // ȡһϢûУ͵ȴ +void FlushMouseMsgBuffer(); // Ϣ diff --git a/Easy2D/EasyX/x86/EasyXa.lib b/Easy2D/EasyX/x86/EasyXa.lib new file mode 100644 index 0000000000000000000000000000000000000000..db14e5bf1bffcd96f82dced386dea49c6646b92b GIT binary patch literal 184974 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 literal 0 HcmV?d00001 diff --git a/Easy2D/FreePool.cpp b/Easy2D/FreePool.cpp new file mode 100644 index 00000000..f177c2d5 --- /dev/null +++ b/Easy2D/FreePool.cpp @@ -0,0 +1,39 @@ +#include "easy2d.h" + +// FreePool ͷųصʵֻƣ +/// Object еüm_nRefüָ֤ʹðȫ +/// ¼˶ʹõĴΪ 0 ʱFreePool Զͷ +/// е Object Ӧڱʹʱ Text ӵ˳У +/// retain ֤ö󲻱ɾڲʹʱ release +/// Զͷ + +// ͷų +static std::vector pool; + +void FreePool::__flush() +{ + // + std::vector::iterator iter; + // ѭеж + for (iter = pool.begin(); iter != pool.end();) + { + // õļΪ 0 + if ((*iter)->m_nRef == 0) + { + // ͷŸö + delete (*iter); + // ͷųɾö + iter = pool.erase(iter); + } + else + { + iter++; // ƶ + } + } +} + +void FreePool::add(Object * nptr) +{ + // һͷų + pool.push_back(nptr); +} diff --git a/Easy2D/Msg/KeyMsg.cpp b/Easy2D/Msg/KeyMsg.cpp new file mode 100644 index 00000000..6ed05471 --- /dev/null +++ b/Easy2D/Msg/KeyMsg.cpp @@ -0,0 +1,172 @@ +#include "..\easy2d.h" +#include "..\EasyX\easyx.h" +#include + +// ص +static std::vector s_vKeyMsg; + +// ֵ +static std::vector s_vKeys = { + KeyMsg::A, KeyMsg::B, KeyMsg::C, KeyMsg::D, KeyMsg::E, KeyMsg::F, KeyMsg::G, KeyMsg::H, KeyMsg::I, KeyMsg::J, + KeyMsg::K, KeyMsg::L, KeyMsg::M, KeyMsg::N, KeyMsg::O, KeyMsg::P, KeyMsg::Q, KeyMsg::R, KeyMsg::S, KeyMsg::T, + KeyMsg::U, KeyMsg::V, KeyMsg::W, KeyMsg::X, KeyMsg::Y, KeyMsg::Z, + KeyMsg::NUM_1, KeyMsg::NUM_2, KeyMsg::NUM_3, KeyMsg::NUM_4, KeyMsg::NUM_5, + KeyMsg::NUM_6, KeyMsg::NUM_7, KeyMsg::NUM_8, KeyMsg::NUM_9, KeyMsg::NUM_0, + KeyMsg::NUMPAD_1, KeyMsg::NUMPAD_2, KeyMsg::NUMPAD_3, KeyMsg::NUMPAD_4, KeyMsg::NUMPAD_5, + KeyMsg::NUMPAD_6, KeyMsg::NUMPAD_7, KeyMsg::NUMPAD_8, KeyMsg::NUMPAD_9, KeyMsg::NUMPAD_0, + KeyMsg::Enter, KeyMsg::Space, KeyMsg::Up, KeyMsg::Down, KeyMsg::Left, KeyMsg::Right, KeyMsg::Esc, + KeyMsg::Decimal, KeyMsg::Shift, KeyMsg::LShift, KeyMsg::RShift, KeyMsg::Ctrl, KeyMsg::LCtrl, KeyMsg::RCtrl, + KeyMsg::F1, KeyMsg::F2, KeyMsg::F3, KeyMsg::F4, KeyMsg::F5, KeyMsg::F6, + KeyMsg::F7, KeyMsg::F8, KeyMsg::F9, KeyMsg::F10, KeyMsg::F11, KeyMsg::F12 +}; + +// ֵĶ +const VK_KEY KeyMsg::A = 'A'; +const VK_KEY KeyMsg::B = 'B'; +const VK_KEY KeyMsg::C = 'C'; +const VK_KEY KeyMsg::D = 'D'; +const VK_KEY KeyMsg::E = 'E'; +const VK_KEY KeyMsg::F = 'F'; +const VK_KEY KeyMsg::G = 'G'; +const VK_KEY KeyMsg::H = 'H'; +const VK_KEY KeyMsg::I = 'I'; +const VK_KEY KeyMsg::J = 'J'; +const VK_KEY KeyMsg::K = 'K'; +const VK_KEY KeyMsg::L = 'L'; +const VK_KEY KeyMsg::M = 'M'; +const VK_KEY KeyMsg::N = 'N'; +const VK_KEY KeyMsg::O = 'O'; +const VK_KEY KeyMsg::P = 'P'; +const VK_KEY KeyMsg::Q = 'Q'; +const VK_KEY KeyMsg::R = 'R'; +const VK_KEY KeyMsg::S = 'S'; +const VK_KEY KeyMsg::T = 'T'; +const VK_KEY KeyMsg::U = 'U'; +const VK_KEY KeyMsg::V = 'V'; +const VK_KEY KeyMsg::W = 'W'; +const VK_KEY KeyMsg::X = 'X'; +const VK_KEY KeyMsg::Y = 'Y'; +const VK_KEY KeyMsg::Z = 'Z'; +const VK_KEY KeyMsg::NUM_0 = '0'; +const VK_KEY KeyMsg::NUM_1 = '1'; +const VK_KEY KeyMsg::NUM_2 = '2'; +const VK_KEY KeyMsg::NUM_3 = '3'; +const VK_KEY KeyMsg::NUM_4 = '4'; +const VK_KEY KeyMsg::NUM_5 = '5'; +const VK_KEY KeyMsg::NUM_6 = '6'; +const VK_KEY KeyMsg::NUM_7 = '7'; +const VK_KEY KeyMsg::NUM_8 = '8'; +const VK_KEY KeyMsg::NUM_9 = '9'; +const VK_KEY KeyMsg::NUMPAD_0 = VK_NUMPAD0; +const VK_KEY KeyMsg::NUMPAD_1 = VK_NUMPAD1; +const VK_KEY KeyMsg::NUMPAD_2 = VK_NUMPAD2; +const VK_KEY KeyMsg::NUMPAD_3 = VK_NUMPAD3; +const VK_KEY KeyMsg::NUMPAD_4 = VK_NUMPAD4; +const VK_KEY KeyMsg::NUMPAD_5 = VK_NUMPAD5; +const VK_KEY KeyMsg::NUMPAD_6 = VK_NUMPAD6; +const VK_KEY KeyMsg::NUMPAD_7 = VK_NUMPAD7; +const VK_KEY KeyMsg::NUMPAD_8 = VK_NUMPAD8; +const VK_KEY KeyMsg::NUMPAD_9 = VK_NUMPAD9; +const VK_KEY KeyMsg::Enter = VK_RETURN; +const VK_KEY KeyMsg::Space = VK_SPACE; +const VK_KEY KeyMsg::Decimal = VK_DECIMAL; +const VK_KEY KeyMsg::Ctrl = VK_CONTROL; +const VK_KEY KeyMsg::LCtrl = VK_LCONTROL; +const VK_KEY KeyMsg::RCtrl = VK_RCONTROL; +const VK_KEY KeyMsg::Shift = VK_SHIFT; +const VK_KEY KeyMsg::LShift = VK_LSHIFT; +const VK_KEY KeyMsg::RShift = VK_RSHIFT; +const VK_KEY KeyMsg::Up = VK_UP; +const VK_KEY KeyMsg::Down = VK_DOWN; +const VK_KEY KeyMsg::Left = VK_LEFT; +const VK_KEY KeyMsg::Right = VK_RIGHT; +const VK_KEY KeyMsg::Esc = VK_ESCAPE; +const VK_KEY KeyMsg::F1 = VK_F1; +const VK_KEY KeyMsg::F2 = VK_F2; +const VK_KEY KeyMsg::F3 = VK_F3; +const VK_KEY KeyMsg::F4 = VK_F4; +const VK_KEY KeyMsg::F5 = VK_F5; +const VK_KEY KeyMsg::F6 = VK_F6; +const VK_KEY KeyMsg::F7 = VK_F7; +const VK_KEY KeyMsg::F8 = VK_F8; +const VK_KEY KeyMsg::F9 = VK_F9; +const VK_KEY KeyMsg::F10 = VK_F10; +const VK_KEY KeyMsg::F11 = VK_F11; +const VK_KEY KeyMsg::F12 = VK_F12; + +KeyMsg::KeyMsg(tstring name, const KEY_CALLBACK & callback) +{ + m_sName = name; + m_callback = callback; +} + +KeyMsg::~KeyMsg() +{ +} + +void KeyMsg::onKbHit(VK_KEY key) +{ + m_callback(key); +} + +void KeyMsg::__exec() +{ + if (_kbhit()) // ȡϢ + { + for (VK_KEY key : s_vKeys) // ѭеֵ + { + if (GetAsyncKeyState(key) & 0x8000) // жϸüǷ + { + for (auto k : s_vKeyMsg) // ַðϢ + { + k->onKbHit(key); // ִаص + } + } + } + } +} + +void KeyMsg::addListener(tstring name, const KEY_CALLBACK & callback) +{ + // µļ + auto key = new KeyMsg(name, callback); + // µİص + s_vKeyMsg.push_back(key); +} + +bool easy2d::KeyMsg::delListener(tstring name) +{ + // + std::vector::iterator iter; + // ѭм + for (iter = s_vKeyMsg.begin(); iter != s_vKeyMsg.end(); iter++) + { + // ͬƵļ + if ((*iter)->m_sName == name) + { + // ɾöʱ + delete (*iter); + s_vKeyMsg.erase(iter); + return true; + } + } + // δҵͬƵļ false + return false; +} + +void easy2d::KeyMsg::clearAllListener() +{ + // ɾм + for (auto t : s_vKeyMsg) + { + delete t; + } + // + s_vKeyMsg.clear(); +} + +bool KeyMsg::isKeyDown(VK_KEY key) +{ + // ȡ key İ + return (GetAsyncKeyState(key) & 0x8000); +} \ No newline at end of file diff --git a/Easy2D/Msg/MouseMsg.cpp b/Easy2D/Msg/MouseMsg.cpp new file mode 100644 index 00000000..8b725f25 --- /dev/null +++ b/Easy2D/Msg/MouseMsg.cpp @@ -0,0 +1,130 @@ +#include "..\easy2d.h" +#include "..\EasyX\easyx.h" + +// Ϣ +static MouseMsg s_mouseMsg = MouseMsg(); + +// EasyX MOUSEMSG תΪ MouseMsg +static void ConvertMsg(MOUSEMSG msg); + +void easy2d::MouseMsg::__exec() +{ + // ȡϢ + while (MouseHit()) + { + // תϢ + ConvertMsg(GetMouseMsg()); + // ִг + Application::get()->getCurrentScene()->_exec(); + } +} + +MouseMsg MouseMsg::getMsg() +{ + return s_mouseMsg; // ȡǰϢ +} + +bool MouseMsg::getLButtonDown() +{ + return s_mouseMsg.mkLButton; +} + +bool MouseMsg::getRButtonDown() +{ + return s_mouseMsg.mkRButton; +} + +bool MouseMsg::getMButtonDown() +{ + return s_mouseMsg.mkMButton; +} + +int MouseMsg::getMouseX() +{ + return s_mouseMsg.x; +} + +int MouseMsg::getMouseY() +{ + return s_mouseMsg.y; +} + +int MouseMsg::getMouseWheel() +{ + return s_mouseMsg.wheel; +} + +bool MouseMsg::getMouseMovedMsg() +{ + return s_mouseMsg.uMsg == WM_MOUSEMOVE; +} + +bool MouseMsg::getLButtonDBClickedMsg() +{ + return s_mouseMsg.uMsg == WM_LBUTTONDBLCLK; +} + +bool MouseMsg::getLButtonDownMsg() +{ + return s_mouseMsg.uMsg == WM_LBUTTONDOWN; +} + +bool MouseMsg::getLButtonUpMsg() +{ + return s_mouseMsg.uMsg == WM_LBUTTONUP; +} + +bool MouseMsg::getRButtonDBClicked() +{ + return s_mouseMsg.uMsg == WM_RBUTTONDBLCLK; +} + +bool MouseMsg::getRButtonDownMsg() +{ + return s_mouseMsg.uMsg == WM_RBUTTONDOWN; +} + +bool MouseMsg::getRButtonUpMsg() +{ + return s_mouseMsg.uMsg == WM_LBUTTONUP; +} + +bool MouseMsg::getMButtonDBClicked() +{ + return s_mouseMsg.uMsg == WM_MBUTTONDBLCLK; +} + +bool MouseMsg::getMButtonDownMsg() +{ + return s_mouseMsg.uMsg == WM_MBUTTONDOWN; +} + +bool MouseMsg::getMButtonUpMsg() +{ + return s_mouseMsg.uMsg == WM_MBUTTONUP; +} + +bool MouseMsg::getWheelMsg() +{ + return s_mouseMsg.uMsg == WM_MOUSEWHEEL; +} + +void MouseMsg::resetMouseMsg() +{ + s_mouseMsg.uMsg = 0; +} + +void ConvertMsg(MOUSEMSG msg) +{ + // MOUSEMSG תΪ MouseMsg + /// Ȼ MOUSEMSG MouseMsg һ + /// Ϊʵ Easy2D EasyX Ը룬Զµ MouseMsg + /// Msg ϢĴͳһ WinAPIʵ֣ EasyX ĺ + s_mouseMsg.uMsg = msg.uMsg; + s_mouseMsg.mkLButton = msg.mkLButton; + s_mouseMsg.mkMButton = msg.mkMButton; + s_mouseMsg.mkRButton = msg.mkRButton; + s_mouseMsg.wheel = msg.wheel; + s_mouseMsg.x = msg.x; + s_mouseMsg.y = msg.y; +} diff --git a/Easy2D/Node/BatchNode.cpp b/Easy2D/Node/BatchNode.cpp new file mode 100644 index 00000000..57f507e0 --- /dev/null +++ b/Easy2D/Node/BatchNode.cpp @@ -0,0 +1,115 @@ +#include "..\easy2d.h" +#include "..\EasyX\easyx.h" +#include + +BatchNode::BatchNode() +{ +} + + +BatchNode::~BatchNode() +{ + clearAllChildren(); +} + +bool BatchNode::_exec(bool active) +{ + // ڵǷʾ + if (!m_bDisplay) + { + return false; + } + // ӽڵ + for (int i = int(m_vChildren.size() - 1); i >= 0; i--) + { + assert(m_vChildren[i]); + if (m_vChildren[i]->_exec(active)) + { + active = false; + } + } + // ӽڵȡ˻潹㣬ýڵҲȡ˽ + return !active; +} + +void BatchNode::_onDraw() +{ + // ڵǷʾ + if (!m_bDisplay) + { + return; + } + + // λûӽڵ + Application::setOrigin(Application::getOriginX() + m_nX, Application::getOriginY() + m_nY); + for (auto child : m_vChildren) + { + assert(child); + child->_onDraw(); + } + Application::setOrigin(Application::getOriginX() - m_nX, Application::getOriginY() - m_nY); +} + +void BatchNode::add(Node * child, int z_Order) +{ + // ӵĽڵǿ + assert(child); + // ýڵĸ + child->setParentScene(this->getParentScene()); + // ýڵڵе z ˳ + child->setZOrder(z_Order); + // üһ + child->retain(); + + // z ˳ڵ + size_t size = m_vChildren.size(); + for (unsigned i = 0; i <= size; i++) + { + if (i != size) + { + if (z_Order < m_vChildren.at(i)->getZOrder()) + { + m_vChildren.insert(m_vChildren.begin() + i, child); + break; + } + } + else + { + m_vChildren.push_back(child); + break; + } + } +} + +bool BatchNode::del(Node * child) +{ + // Խڵǿ + assert(child); + + // ѰǷͬڵ + std::vector::iterator iter; + for (iter = m_vChildren.begin(); iter != m_vChildren.end(); iter++) + { + // ҵͬڵ + if ((*iter) == child) + { + // üһ + (*iter)->release(); + // ȥýڵ + m_vChildren.erase(iter); + return true; + } + } + return false; +} + +void BatchNode::clearAllChildren() +{ + // нڵüһ + for (auto child : m_vChildren) + { + child->release(); + } + // մڵ + m_vChildren.clear(); +} diff --git a/Easy2D/Node/Button/Button.cpp b/Easy2D/Node/Button/Button.cpp new file mode 100644 index 00000000..256166a6 --- /dev/null +++ b/Easy2D/Node/Button/Button.cpp @@ -0,0 +1,65 @@ +#include "..\..\Easy2d.h" +#include "..\..\EasyX\easyx.h" + + +Button::Button() : + m_bEnable(true) +{ +} + +Button::~Button() +{ +} + +bool Button::_exec(bool active) +{ + // ťǷ + if (!m_bEnable || !m_bDisplay) + { + return false; + } + return MouseNode::_exec(active); +} + +void Button::_onDraw() +{ + // ťǷ + if (!m_bEnable) + { + // δʱ Disable ״̬ + _onDisable(); + return; + } + MouseNode::_onDraw(); +} + +void Button::_judge() +{ + // жϰťǰ״̬ + // λڰťڵľ + if (MouseMsg::getMsg().x >= m_nX && MouseMsg::getMsg().x <= m_nX + m_nWidth && + MouseMsg::getMsg().y >= m_nY && MouseMsg::getMsg().y <= m_nY + m_nHeight) + { + _setMouseIn(); + + // ڰťϣ + if (MouseMsg::getLButtonDownMsg()) + { + _setSelected(); + } + } + else + { + _setNormal(); + } +} + +bool Button::isEnable() +{ + return m_bEnable; +} + +void Button::setEnable(bool enable) +{ + m_bEnable = enable; +} diff --git a/Easy2D/Node/Button/ImageButton.cpp b/Easy2D/Node/Button/ImageButton.cpp new file mode 100644 index 00000000..79733a98 --- /dev/null +++ b/Easy2D/Node/Button/ImageButton.cpp @@ -0,0 +1,167 @@ +#include "..\..\Easy2d.h" + + +ImageButton::ImageButton() : + m_pNormalImage(nullptr), + m_pMouseInImage(nullptr), + m_pSelectedImage(nullptr), + m_pUnableImage(nullptr) +{ + m_nWidth = 0; + m_nHeight = 0; +} + +ImageButton::ImageButton(Image * image) : + ImageButton() +{ + setNormalImage(image); // ðť״̬ʱͼƬ +} + +ImageButton::~ImageButton() +{ + // ͼƬüһ + SAFE_RELEASE(m_pNormalImage); + SAFE_RELEASE(m_pMouseInImage); + SAFE_RELEASE(m_pSelectedImage); + SAFE_RELEASE(m_pUnableImage); +} + +void ImageButton::_onNormal() +{ + if (m_pNormalImage) + { + m_pNormalImage->_onDraw(); + } +} + +void ImageButton::_onMouseIn() +{ + if (m_pMouseInImage) + { + m_pMouseInImage->_onDraw(); + } + else + { + _onNormal(); + } +} + +void ImageButton::_onSelected() +{ + if (m_pSelectedImage) + { + m_pSelectedImage->_onDraw(); + } + else + { + _onNormal(); + } +} + +void ImageButton::_onDisable() +{ + if (m_pUnableImage) + { + m_pUnableImage->_onDraw(); + } + else + { + _onNormal(); + } +} + +void ImageButton::setNormalImage(Image * image) +{ + if (image) + { + // ԭͼƬüһ + SAFE_RELEASE(m_pNormalImage); + // ޸ͼƬ + m_pNormalImage = image; + // ͼƬüһ + m_pNormalImage->retain(); + // ¼ͼƬλ + resetImagePosition(); + } +} + +void ImageButton::setMouseInImage(Image * image) +{ + if (image) + { + SAFE_RELEASE(m_pMouseInImage); + m_pMouseInImage = image; + m_pMouseInImage->retain(); + resetImagePosition(); + } +} + +void ImageButton::setSelectedImage(Image * image) +{ + if (image) + { + SAFE_RELEASE(m_pSelectedImage); + m_pSelectedImage = image; + m_pSelectedImage->retain(); + resetImagePosition(); + } +} + +void ImageButton::setUnableImage(Image * image) +{ + if (image) + { + SAFE_RELEASE(m_pUnableImage); + m_pUnableImage = image; + m_pUnableImage->retain(); + resetImagePosition(); + } +} + +void ImageButton::setX(int x) +{ + Node::setX(x); + resetImagePosition(); +} + +void ImageButton::setY(int y) +{ + Node::setY(y); + resetImagePosition(); +} + +void ImageButton::setPos(int x, int y) +{ + Node::setPos(x, y); + resetImagePosition(); +} + +void ImageButton::resetImagePosition() +{ + if (m_pNormalImage) + { + // ͼƬ趨ťС + m_nWidth = m_pNormalImage->getWidth(); + m_nHeight = m_pNormalImage->getHeight(); + // ݰťλúͼƬͼƬλþʾ + m_pNormalImage->setPos(m_nX, m_nY); + } + if (m_pMouseInImage) + { + m_pMouseInImage->setPos( + m_nX + (m_nWidth - m_pMouseInImage->getWidth()) / 2, + m_nY + (m_nHeight - m_pMouseInImage->getHeight()) / 2); + } + if (m_pSelectedImage) + { + m_pSelectedImage->setPos( + m_nX + (m_nWidth - m_pSelectedImage->getWidth()) / 2, + m_nY + (m_nHeight - m_pSelectedImage->getHeight()) / 2); + } + if (m_pUnableImage) + { + m_pUnableImage->setPos( + m_nX + (m_nWidth - m_pUnableImage->getWidth()) / 2, + m_nY + (m_nHeight - m_pUnableImage->getHeight()) / 2); + } +} diff --git a/Easy2D/Node/Button/TextButton.cpp b/Easy2D/Node/Button/TextButton.cpp new file mode 100644 index 00000000..fb6ce9d9 --- /dev/null +++ b/Easy2D/Node/Button/TextButton.cpp @@ -0,0 +1,167 @@ +#include "..\..\Easy2d.h" + + +TextButton::TextButton() : + m_pNormalText(nullptr), + m_pMouseInText(nullptr), + m_pSelectedText(nullptr), + m_pUnableText(nullptr) +{ + m_nWidth = 0; + m_nHeight = 0; +} + +TextButton::TextButton(Text * text) : + TextButton() +{ + setNormalText(text); // ðť״̬ʱ +} + +TextButton::~TextButton() +{ + // ıüһ + SAFE_RELEASE(m_pNormalText); + SAFE_RELEASE(m_pMouseInText); + SAFE_RELEASE(m_pSelectedText); + SAFE_RELEASE(m_pUnableText); +} + +void TextButton::_onNormal() +{ + if (m_pNormalText) + { + m_pNormalText->_onDraw(); + } +} + +void TextButton::_onMouseIn() +{ + if (m_pMouseInText) + { + m_pMouseInText->_onDraw(); + } + else + { + _onNormal(); + } +} + +void TextButton::_onSelected() +{ + if (m_pSelectedText) + { + m_pSelectedText->_onDraw(); + } + else + { + _onNormal(); + } +} + +void TextButton::_onDisable() +{ + if (m_pUnableText) + { + m_pUnableText->_onDraw(); + } + else + { + _onNormal(); + } +} + +void TextButton::setNormalText(Text * text) +{ + if (text) + { + // ԭıüһ + SAFE_RELEASE(m_pNormalText); + // ޸ı + m_pNormalText = text; + // ıüһ + m_pNormalText->retain(); + // ¼ıλ + resetTextPosition(); + } +} + +void TextButton::setMouseInText(Text * text) +{ + if (text) + { + SAFE_RELEASE(m_pMouseInText); + m_pMouseInText = text; + m_pMouseInText->retain(); + resetTextPosition(); + } +} + +void TextButton::setSelectedText(Text * text) +{ + if (text) + { + SAFE_RELEASE(m_pSelectedText); + m_pSelectedText = text; + m_pSelectedText->retain(); + resetTextPosition(); + } +} + +void TextButton::setUnableText(Text * text) +{ + if (text) + { + SAFE_RELEASE(m_pUnableText); + m_pUnableText = text; + m_pUnableText->retain(); + resetTextPosition(); + } +} + +void TextButton::setX(int x) +{ + Node::setX(x); + resetTextPosition(); +} + +void TextButton::setY(int y) +{ + Node::setY(y); + resetTextPosition(); +} + +void TextButton::setPos(int x, int y) +{ + Node::setPos(x, y); + resetTextPosition(); +} + +void TextButton::resetTextPosition() +{ + if (m_pNormalText) + { + // ֿ趨ťС + m_nWidth = m_pNormalText->getWidth(); + m_nHeight = m_pNormalText->getHeight(); + // ݰťλúֿλþʾ + m_pNormalText->setPos(m_nX , m_nY); + } + if (m_pMouseInText) + { + m_pMouseInText->setPos( + m_nX + (m_nWidth - m_pMouseInText->getWidth()) / 2, + m_nY + (m_nHeight - m_pMouseInText->getHeight()) / 2); + } + if (m_pSelectedText) + { + m_pSelectedText->setPos( + m_nX + (m_nWidth - m_pSelectedText->getWidth()) / 2, + m_nY + (m_nHeight - m_pSelectedText->getHeight()) / 2); + } + if (m_pUnableText) + { + m_pUnableText->setPos( + m_nX + (m_nWidth - m_pUnableText->getWidth()) / 2, + m_nY + (m_nHeight - m_pUnableText->getHeight()) / 2); + } +} diff --git a/Easy2D/Node/Image.cpp b/Easy2D/Node/Image.cpp new file mode 100644 index 00000000..bc9f84db --- /dev/null +++ b/Easy2D/Node/Image.cpp @@ -0,0 +1,181 @@ +#include "..\Easy2d.h" +#include "..\EasyX\easyx.h" + +// PNG ͼת +static void CrossImage(CImage &img); + +Image::Image() : + m_fScaleX(1), + m_fScaleY(1) +{ +} + +Image::Image(LPCTSTR ImageFile, int x, int y, int width, int height) : + m_fScaleX(1), + m_fScaleY(1) +{ + setImageFile(ImageFile, x, y, width, height); // ͼƬԴͲüС +} + +Image::~Image() +{ +} + +void Image::_onDraw() +{ + // display Ϊ falseδͼƬԴʱƸͼƬ + if (!m_bDisplay || m_Image.IsNull()) + { + return; + } + // ͼƬ + m_Image.Draw(GetImageHDC(), m_rDest, m_rSrc); +} + +int Image::getWidth() const +{ + return m_rDest.Width(); // ĿεĿ +} + +int Image::getHeight() const +{ + return m_rDest.Height(); // Ŀεĸ߶ +} + +float Image::getScaleX() const +{ + return m_fScaleX; +} + +float Image::getScaleY() const +{ + return m_fScaleY; +} + +void Image::setImageFile(LPCTSTR ImageFile, int x, int y, int width, int height) +{ + // ͼƬ + m_Image.Load(ImageFile); + // ȡչ PNG ͼƬ⴦ + if (_T(".png") == FileUtils::getFileExtension(ImageFile)) + { + // ת + CrossImage(m_Image); + // Alpha ͨ + m_Image.AlphaBlend(GetImageHDC(), 15, 30); + } + // ĿΣƵڵλúʹС + m_rDest.SetRect(0, 0, m_Image.GetWidth(), m_Image.GetHeight()); + // üͼƬС + crop(x, y, width, height); +} + +void Image::setImageRes(LPCTSTR pResName, int x, int y, int width, int height) +{ + // ԴͼƬ֧ PNG + m_Image.LoadFromResource(GetModuleHandle(NULL), pResName); + // + m_fScaleX = 0, m_fScaleY = 0; + // ĿΣƵڵλúʹС + m_rDest.SetRect(0, 0, m_Image.GetWidth(), m_Image.GetHeight()); + // üͼƬС + crop(x, y, width, height); +} + +void Image::crop(int x, int y, int width, int height) +{ + // ԴελúʹСڲü + m_rSrc.SetRect( + x, y, + x + (width ? width : m_Image.GetWidth() - x), + y + (height ? height : m_Image.GetHeight() - y)); + // ĿΣƵڵλúʹС + m_rDest.SetRect( + m_nX, m_nY, + m_nX + (width ? width : int(m_rSrc.Width() * m_fScaleX)), + m_nY + (height ? height : int(m_rSrc.Height() * m_fScaleY))); +} + +void Image::stretch(int width, int height) +{ + // ĿελúʹСƵڵλúʹСͼƬ + m_rDest.SetRect( + m_nX, m_nY, + m_nX + (width ? width : m_Image.GetWidth()), + m_nY + (height ? height : m_Image.GetHeight())); +} + +void Image::scale(float scaleX, float scaleY) +{ + m_fScaleX = min(max(scaleX, 0), 1.0f); + m_fScaleY = min(max(scaleY, 0), 1.0f); + m_rDest.SetRect( + m_nX, m_nY, + m_nX + int(m_Image.GetWidth() * scaleX), + m_nY + int(m_Image.GetHeight() * scaleY)); +} + +void Image::setPos(int x, int y) +{ + // ƶĿ + m_rDest.MoveToXY(x, y); + m_nX = x; + m_nY = y; +} + +void Image::move(int x, int y) +{ + // ƶĿ + m_rDest.OffsetRect(x, y); + m_nX += x; + m_nY += y; +} + +void Image::setX(int x) +{ + // ƶĿ + m_rDest.MoveToX(x); + m_nX = x; +} + +void Image::setY(int y) +{ + // ƶĿ + m_rDest.MoveToY(y); + m_nY = y; +} + +void Image::setTransparentColor(COLORREF value) +{ + // ͸ɫ + m_Image.SetTransparentColor(value); +} + +void Image::screenshot() +{ + tstring savePath; + // ȡλ + if (FileUtils::getSaveFilePath(savePath, _T("ͼ浽"), _T("jpg"))) + { + // 洰ڽͼ + IMAGE image; + getimage(&image, 0, 0, Application::get()->getWidth(), Application::get()->getHeight()); + saveimage(savePath.c_str(), &image); + } +} + + +// PNG ͼת +void CrossImage(CImage &img) +{ + for (int i = 0; i < img.GetWidth(); i++) + { + for (int j = 0; j < img.GetHeight(); j++) + { + UCHAR *cr = (UCHAR*)img.GetPixelAddress(i, j); + cr[0] = cr[0] * cr[3] / 255; + cr[1] = cr[1] * cr[3] / 255; + cr[2] = cr[2] * cr[3] / 255; + } + } +} \ No newline at end of file diff --git a/Easy2D/Node/MouseNode.cpp b/Easy2D/Node/MouseNode.cpp new file mode 100644 index 00000000..089b7ec6 --- /dev/null +++ b/Easy2D/Node/MouseNode.cpp @@ -0,0 +1,109 @@ +#include "..\easy2d.h" + + +MouseNode::MouseNode() : + m_bBlock(true), + m_bTarget(false), + m_callback([]() {}) +{ +} + +MouseNode::~MouseNode() +{ +} + +bool MouseNode::_exec(bool active) +{ + // ȡý㣬 display Ϊ false˳ + if (!active || !m_bDisplay) + { + return false; + } + // жϽڵ״̬ + _judge(); + // ڽڵϣѡʱҲڽڵϣ + if (m_eStatus == MOUSEIN || m_eStatus == SELECTED) + { + // ڵ㱻ѡУ̧ + if (m_bTarget && MouseMsg::getLButtonUpMsg()) + { + onClicked(); // ִлص + } + // ڵ㲻Ϣȡû潹 + if (!m_bBlock) return true; + } + return false; +} + +void MouseNode::_onDraw() +{ + // ڵǷʾ + if (!m_bDisplay) + { + return; + } + // ڵǷѡ + if (m_eStatus == SELECTED) + { + _onSelected(); + } + else + { + // Ƿڽڵ + if (m_eStatus == MOUSEIN) + { + _onMouseIn(); + } + else + { + _onNormal(); + } + } +} + +void MouseNode::_setNormal() +{ + m_bTarget = false; // ʧȥ + m_eStatus = NORMAL; +} + +void MouseNode::_setMouseIn() +{ + m_eStatus = MOUSEIN; +} + +void MouseNode::_setSelected() +{ + m_bTarget = true; // ȡý + m_eStatus = SELECTED; +} + +void MouseNode::onClicked() +{ + m_callback(); +} + +bool MouseNode::isMouseIn() +{ + return m_eStatus == MOUSEIN || m_eStatus == SELECTED; +} + +bool MouseNode::isSelected() +{ + return m_eStatus == SELECTED; +} + +void MouseNode::setOnMouseClicked(const CLICK_CALLBACK & callback) +{ + m_callback = callback; +} + +void MouseNode::reset() +{ + m_eStatus = NORMAL; +} + +void MouseNode::setBlock(bool block) +{ + m_bBlock = block; +} diff --git a/Easy2D/Node/Node.cpp b/Easy2D/Node/Node.cpp new file mode 100644 index 00000000..3f8ea475 --- /dev/null +++ b/Easy2D/Node/Node.cpp @@ -0,0 +1,92 @@ +#include "..\Easy2d.h" + +Node::Node() : + m_nZOrder(0), + m_bDisplay(true), + m_nX(0), + m_nY(0) +{ +} + +Node::Node(int x, int y) : + m_nZOrder(0), + m_bDisplay(true), + m_nX(x), + m_nY(y) +{ +} + +Node::~Node() +{ +} + +bool Node::_exec(bool active) +{ + return false; +} + +void Node::_onDraw() +{ +} + +const int Node::getX() const +{ + return m_nX; +} + +const int Node::getY() const +{ + return m_nY; +} + +void Node::setX(int x) +{ + m_nX = x; +} + +void Node::setY(int y) +{ + m_nY = y; +} + +void Node::setPos(int x, int y) +{ + m_nX = x; + m_nY = y; +} + +void Node::move(int x, int y) +{ + m_nX += x; + m_nY += y; +} + +int Node::getZOrder() const +{ + return m_nZOrder; +} + +void Node::setZOrder(int z) +{ + m_nZOrder = z; +} + +Scene * Node::getParentScene() +{ + return m_pScene; +} + +void Node::setParentScene(Scene * scene) +{ + m_pScene = scene; +} + +void Node::setDisplay(bool value) +{ + m_bDisplay = value; +} + +bool Node::display() const +{ + return m_bDisplay; +} \ No newline at end of file diff --git a/Easy2D/Node/Shape/Circle.cpp b/Easy2D/Node/Shape/Circle.cpp new file mode 100644 index 00000000..0e5af186 --- /dev/null +++ b/Easy2D/Node/Shape/Circle.cpp @@ -0,0 +1,43 @@ +#include "..\..\easy2d.h" +#include "..\..\EasyX\easyx.h" + + +Circle::Circle() : + m_nRadius(0) +{ +} + +Circle::Circle(int x, int y, int radius) : + Node(x, y), + m_nRadius(radius) +{ +} + +Circle::~Circle() +{ +} + +void Circle::solidShape() +{ + solidcircle(m_nX, m_nY, m_nRadius); +} + +void Circle::fillShape() +{ + fillcircle(m_nX, m_nY, m_nRadius); +} + +void Circle::roundShape() +{ + circle(m_nX, m_nY, m_nRadius); +} + +int Circle::getRadius() const +{ + return m_nRadius; +} + +void Circle::setRadius(int r) +{ + m_nRadius = r; +} \ No newline at end of file diff --git a/Easy2D/Node/Shape/Rectangle.cpp b/Easy2D/Node/Shape/Rectangle.cpp new file mode 100644 index 00000000..4c7517a4 --- /dev/null +++ b/Easy2D/Node/Shape/Rectangle.cpp @@ -0,0 +1,61 @@ +#include "..\..\easy2d.h" +#include "..\..\EasyX\easyx.h" + + +Rect::Rect() : + m_nWidth(0), + m_nHeight(0) +{ +} + +Rect::Rect(int x, int y, int width, int height) : + Node(x, y), + m_nWidth(width), + m_nHeight(height) +{ +} + +Rect::~Rect() +{ +} + +void Rect::solidShape() +{ + solidrectangle(m_nX, m_nY, m_nX + m_nWidth, m_nY + m_nHeight); +} + +void Rect::fillShape() +{ + fillrectangle(m_nX, m_nY, m_nX + m_nWidth, m_nY + m_nHeight); +} + +void Rect::roundShape() +{ + rectangle(m_nX, m_nY, m_nX + m_nWidth, m_nY + m_nHeight); +} + +int Rect::getWidth() const +{ + return m_nWidth; +} + +int Rect::getHeight() const +{ + return m_nHeight; +} + +void Rect::setWidth(int width) +{ + m_nWidth = width; +} + +void Rect::setHeight(int height) +{ + m_nHeight = height; +} + +void Rect::setSize(int width, int height) +{ + m_nWidth = width; + m_nHeight = height; +} \ No newline at end of file diff --git a/Easy2D/Node/Shape/Shape.cpp b/Easy2D/Node/Shape/Shape.cpp new file mode 100644 index 00000000..7258439d --- /dev/null +++ b/Easy2D/Node/Shape/Shape.cpp @@ -0,0 +1,56 @@ +#include "..\..\Easy2d.h" +#include "..\..\EasyX\easyx.h" + +Shape::Shape() +{ +} + +Shape::~Shape() +{ +} + +void Shape::_onDraw() +{ + // ״Ƿʾ + if (!m_bDisplay) + { + return; + } + // ɫ + setlinecolor(lineColor); + setfillcolor(fillColor); + + // ״ʽвͬĻ + if (_style == Shape::STYLE::round) + { + roundShape(); + } + else if (_style == Shape::STYLE::solid) + { + solidShape(); + } + else if (_style == Shape::STYLE::fill) + { + fillShape(); + } +} + +inline COLORREF Shape::getFillColor() const +{ + return fillColor; +} + +inline COLORREF Shape::getLineColor() const +{ + return lineColor; +} + +void Shape::setFillColor(COLORREF color) +{ + fillColor = color; +} + +void Shape::setLineColor(COLORREF color) +{ + lineColor = color; +} diff --git a/Easy2D/Node/Sprite/Sprite.cpp b/Easy2D/Node/Sprite/Sprite.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Easy2D/Node/Sprite/SpriteFrame.cpp b/Easy2D/Node/Sprite/SpriteFrame.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Easy2D/Node/Text.cpp b/Easy2D/Node/Text.cpp new file mode 100644 index 00000000..cbef6dbd --- /dev/null +++ b/Easy2D/Node/Text.cpp @@ -0,0 +1,99 @@ +#include "..\Easy2d.h" +#include "..\EasyX\easyx.h" + + +Text::Text() : + m_sText(_T("")), + m_color(Color::white), + m_pFontStyle(FontStyle::getDefault()) +{ + m_pFontStyle->retain(); // üһ +} + +Text::Text(tstring text, COLORREF color, FontStyle * font) : + m_sText(text), + m_color(color), + m_pFontStyle(font) +{ + m_pFontStyle->retain(); // üһ +} + +Text::Text(int x, int y, tstring text, COLORREF color, FontStyle * font) : + Node(x, y), + m_sText(text), + m_color(color), + m_pFontStyle(font) +{ + m_pFontStyle->retain(); // üһ +} + +Text::~Text() +{ + SAFE_RELEASE(m_pFontStyle); // üһ +} + +void Text::_onDraw() +{ + // display Ϊ falseı + if (!m_bDisplay) + { + return; + } + // + settextstyle(&m_pFontStyle->m_font); + // ıɫ + settextcolor(m_color); + // + outtextxy(m_nX, m_nY, m_sText.c_str()); +} + +COLORREF Text::getColor() const +{ + return m_color; +} + +tstring Text::getText() const +{ + return m_sText; +} + +FontStyle * Text::getFontStyle() +{ + return m_pFontStyle; +} + +int Text::getWidth() +{ + // 壬ȻȡıڸµĿ + settextstyle(&m_pFontStyle->m_font); + return textwidth(getText().c_str()); +} + +int Text::getHeight() +{ + // 壬Ȼȡıڸµĸ߶ + settextstyle(&m_pFontStyle->m_font); + return textheight(getText().c_str()); +} + +bool Text::isEmpty() const +{ + return m_sText.empty(); // ıǷΪ +} + +void Text::setText(tstring text) +{ + m_sText = text; +} + +void Text::setColor(COLORREF color) +{ + m_color = color; +} + +void Text::setFontStyle(FontStyle * style) +{ + SAFE_RELEASE(m_pFontStyle); // ԭüһ + m_pFontStyle = style; // ޸ + m_pFontStyle->retain(); // üһ +} diff --git a/Easy2D/Object.cpp b/Easy2D/Object.cpp new file mode 100644 index 00000000..08ca53aa --- /dev/null +++ b/Easy2D/Object.cpp @@ -0,0 +1,21 @@ +#include "easy2d.h" + +Object::Object() : + m_nRef(0) +{ + FreePool::add(this); // öͷų +} + +Object::~Object() +{ +} + +void Object::retain() +{ + m_nRef++; // üһ +} + +void Object::release() +{ + m_nRef--; // üһ +} diff --git a/Easy2D/Scene.cpp b/Easy2D/Scene.cpp new file mode 100644 index 00000000..93099331 --- /dev/null +++ b/Easy2D/Scene.cpp @@ -0,0 +1,102 @@ +#include "easy2d.h" +#include + +Scene::Scene() +{ +} + +Scene::~Scene() +{ + clearAllChildren(); +} + +void Scene::_exec() +{ + // active ־Ƿȡý + bool active = true; + // ִУƵĽڵ㣨λڻϷȱ + for (int i = int(m_vChildren.size()) - 1; i >= 0; i--) + { + assert(m_vChildren[i]); + if (m_vChildren[i]->_exec(active)) // ִнڵ + { + active = false; // ӽڵȡý㣬־ false + } + } +} + +void Scene::_onDraw() +{ + // нڵ + for (auto child : m_vChildren) + { + assert(child); + child->_onDraw(); + } +} + +void Scene::add(Node * child, int zOrder) +{ + // ӵĽڵǿ + assert(child); + // ýڵĸ + child->setParentScene(this); + // z ˳ + child->setZOrder(zOrder); + // üһ + child->retain(); + + // z ˳ڵ + size_t size = m_vChildren.size(); + for (unsigned i = 0; i <= size; i++) + { + if (i == size) + { + m_vChildren.push_back(child); + break; + } + else + { + auto temp = m_vChildren.at(i); + if (temp->getZOrder() > zOrder) + { + m_vChildren.insert(m_vChildren.begin() + i, child); + break; + } + } + } +} + +bool Scene::del(Node * child) +{ + // Խڵǿ + assert(child); + + // ѰǷͬڵ + std::vector::iterator iter; + for (iter = m_vChildren.begin(); iter != m_vChildren.end(); iter++) + { + // ҵͬڵ + if (*iter == child) + { + // üһ + (*iter)->release(); + // ȥýڵ + m_vChildren.erase(iter); + return true; + } + } + // δҵýڵ㷵 false + return false; +} + +void Scene::clearAllChildren() +{ + // нڵüһ + for (auto child : m_vChildren) + { + child->release(); + } + // մڵ + m_vChildren.clear(); +} \ No newline at end of file diff --git a/Easy2D/Style/Color.cpp b/Easy2D/Style/Color.cpp new file mode 100644 index 00000000..5daa3584 --- /dev/null +++ b/Easy2D/Style/Color.cpp @@ -0,0 +1,56 @@ +#include "..\Easy2d.h" +#include "..\EasyX\easyx.h" + +// ɫֵĶ +const COLORREF Color::black = BLACK; +const COLORREF Color::blue = BLUE; +const COLORREF Color::green = GREEN; +const COLORREF Color::cyan = CYAN; +const COLORREF Color::red = RED; +const COLORREF Color::magenta = MAGENTA; +const COLORREF Color::brown = BROWN; +const COLORREF Color::lightgray = LIGHTGRAY; +const COLORREF Color::darkgray = DARKGRAY; +const COLORREF Color::lightblue = LIGHTBLUE; +const COLORREF Color::lightgreen = LIGHTGREEN; +const COLORREF Color::lightcyan = LIGHTCYAN; +const COLORREF Color::lightred = LIGHTRED; +const COLORREF Color::lightmagenta = LIGHTMAGENTA; +const COLORREF Color::yellow = YELLOW; +const COLORREF Color::white = WHITE; + + +COLORREF Color::getFromRGB(BYTE r, BYTE g, BYTE b) +{ + return RGB(r, g, b); // (r, g, b) ɫֵתΪɫ +} + +COLORREF Color::getFromHSL(float H, float S, float L) +{ + return HSLtoRGB(H, S, L); +} + +COLORREF Color::getFromHSV(float H, float S, float V) +{ + return HSVtoRGB(H, S, V); +} + +BYTE Color::getRValue(COLORREF color) +{ + return GetRValue(color); // ɫеĺɫֵ +} + +BYTE Color::getGValue(COLORREF color) +{ + return GetGValue(color); // ɫеɫֵ +} + +BYTE Color::getBValue(COLORREF color) +{ + return GetBValue(color); // ɫеɫֵ +} + +COLORREF Color::getGray(COLORREF color) +{ + return RGBtoGRAY(color); // ȡɫеĻҶֵ +} diff --git a/Easy2D/Style/FillStyle.cpp b/Easy2D/Style/FillStyle.cpp new file mode 100644 index 00000000..498580d5 --- /dev/null +++ b/Easy2D/Style/FillStyle.cpp @@ -0,0 +1 @@ +/* FillStyle EasyX е࣬Ŀǰδʵ */ \ No newline at end of file diff --git a/Easy2D/Style/FontStyle.cpp b/Easy2D/Style/FontStyle.cpp new file mode 100644 index 00000000..6d9b6921 --- /dev/null +++ b/Easy2D/Style/FontStyle.cpp @@ -0,0 +1,97 @@ +#include "..\Easy2d.h" + +// ϸֵĶ +const LONG FontWeight::dontcare = 0; +const LONG FontWeight::thin = 100; +const LONG FontWeight::extraLight = 200; +const LONG FontWeight::light = 300; +const LONG FontWeight::normal = 400; +const LONG FontWeight::regular = 400; +const LONG FontWeight::medium = 500; +const LONG FontWeight::demiBlod = 600; +const LONG FontWeight::blod = 700; +const LONG FontWeight::extraBold = 800; +const LONG FontWeight::black = 900; +const LONG FontWeight::heavy = 900; + +// Ĭ +static const FontStyle s_defaultFont(_T(""), 18, FontWeight::normal); + + +FontStyle::FontStyle() +{ + m_font = s_defaultFont.m_font; +} + +FontStyle::FontStyle(LPCTSTR fontfamily, LONG height, LONG weight, LONG width, bool italic, bool underline, bool strikeout, LONG escapement, LONG orientation, bool quality) +{ + setFontFamily(fontfamily); + m_font.lfWeight = weight; + m_font.lfHeight = height; + m_font.lfWidth = width; + m_font.lfItalic = italic; + m_font.lfUnderline = underline; + m_font.lfStrikeOut = strikeout; + m_font.lfEscapement = escapement; + m_font.lfOrientation = orientation; + setQuality(quality); +} + +FontStyle::~FontStyle() +{ +} + +FontStyle * FontStyle::getDefault() +{ + return new FontStyle(s_defaultFont); +} + +void FontStyle::setHeight(LONG value) +{ + m_font.lfHeight = value; +} + +void FontStyle::setWidth(LONG value) +{ + m_font.lfWidth = value; +} + +void FontStyle::setFontFamily(LPCTSTR value) +{ + _tcscpy_s(m_font.lfFaceName, 32, value); +} + +void FontStyle::setEscapement(LONG value) +{ + m_font.lfEscapement = value; +} + +void FontStyle::setOrientation(LONG value) +{ + m_font.lfOrientation = value; +} + +void FontStyle::setQuality(bool value) +{ + m_font.lfQuality = value ? ANTIALIASED_QUALITY : DEFAULT_QUALITY; +} + +void FontStyle::setWeight(LONG value) +{ + m_font.lfWeight = value; +} + +void FontStyle::setItalic(bool value) +{ + m_font.lfItalic = value; +} + +void FontStyle::setUnderline(bool value) +{ + m_font.lfUnderline = value; +} + +void FontStyle::setStrikeOut(bool value) +{ + m_font.lfStrikeOut = value; +} \ No newline at end of file diff --git a/Easy2D/Style/LineStyle.cpp b/Easy2D/Style/LineStyle.cpp new file mode 100644 index 00000000..1b613360 --- /dev/null +++ b/Easy2D/Style/LineStyle.cpp @@ -0,0 +1 @@ +/* LineStyle EasyX е࣬Ŀǰδʵ */ \ No newline at end of file diff --git a/Easy2D/Tool/FileUtils.cpp b/Easy2D/Tool/FileUtils.cpp new file mode 100644 index 00000000..067cca17 --- /dev/null +++ b/Easy2D/Tool/FileUtils.cpp @@ -0,0 +1,45 @@ +#include "..\Easy2d.h" +#include "..\EasyX\easyx.h" +#include + + +tstring FileUtils::getFileExtension(const tstring & filePath) +{ + tstring fileExtension; + // ҵļеһ '.' λ + size_t pos = filePath.find_last_of('.'); + // ж pos ǷǸЧλ + if (pos != tstring::npos) + { + // ȡչ + fileExtension = filePath.substr(pos, filePath.length()); + // תΪСдĸ + std::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), ::tolower); + } + + return fileExtension; +} + +bool FileUtils::getSaveFilePath(tstring& path, LPCTSTR title, LPCTSTR defExt) +{ + // Ի + OPENFILENAME ofn = { 0 }; + TCHAR strFilename[MAX_PATH] = { 0 }; // ڽļ + ofn.lStructSize = sizeof(OPENFILENAME); // ṹС + ofn.hwndOwner = GetHWnd(); // ӵŴھNULL ʾԻǷģ̬ + ofn.lpstrFilter = _T("ļ\0*.*\0\0"); // ù + ofn.nFilterIndex = 1; // + ofn.lpstrFile = strFilename; // շصļ·ļ + ofn.nMaxFile = sizeof(strFilename); // + ofn.lpstrInitialDir = NULL; // ʼĿ¼ΪĬ + ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;// Ŀ¼ڣļǰ + ofn.lpstrTitle = title; // ʹϵͳĬϱռ + ofn.lpstrDefExt = defExt; // Ĭ׷ӵչ + + if (GetSaveFileName(&ofn)) + { + path = strFilename; + return true; + } + return false; +} diff --git a/Easy2D/Tool/MusicUtils.cpp b/Easy2D/Tool/MusicUtils.cpp new file mode 100644 index 00000000..e5575f35 --- /dev/null +++ b/Easy2D/Tool/MusicUtils.cpp @@ -0,0 +1,458 @@ +#include "..\Easy2d.h" + + +/* עMusicUtils ȫ Cocos2dx е SimpleAudioEngine ʵ */ + +#include +#pragma comment(lib , "winmm.lib") +#include + +//////////////////////////////////////////////////////////////////// +// MciPlayer +//////////////////////////////////////////////////////////////////// + +class MciPlayer +{ +public: + MciPlayer(); + ~MciPlayer(); + + void Close(); + void Open(tstring pFileName, UINT uId); + void Play(UINT uTimes = 1); + void Pause(); + void Resume(); + void Stop(); + void Rewind(); + bool IsPlaying(); + UINT GetSoundID(); + +private: + friend LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); + + void _SendGenericCommand(int nCommand, DWORD_PTR param1 = 0, DWORD_PTR parma2 = 0); + + HWND _wnd; + MCIDEVICEID _dev; + UINT _soundID; + UINT _times; + bool _playing; + tstring strExt; +}; + + + +#define WIN_CLASS_NAME "Easy2dCallbackWnd" + +static HINSTANCE s_hInstance; +static MCIERROR s_mciError; + +LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); + +MciPlayer::MciPlayer() + : _wnd(NULL) + , _dev(0L) + , _soundID(0) + , _times(0) + , _playing(false) + , strExt(_T("")) +{ + if (!s_hInstance) + { + s_hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window + + WNDCLASS wc; // Windows Class Structure + + // Redraw On Size, And Own DC For Window. + wc.style = 0; + wc.lpfnWndProc = _SoundPlayProc; // WndProc Handles Messages + wc.cbClsExtra = 0; // No Extra Window Data + wc.cbWndExtra = 0; // No Extra Window Data + wc.hInstance = s_hInstance; // Set The Instance + wc.hIcon = 0; // Load The Default Icon + wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer + wc.hbrBackground = NULL; // No Background Required For GL + wc.lpszMenuName = NULL; // We Don't Want A Menu + wc.lpszClassName = _T(WIN_CLASS_NAME); // Set The Class Name + + if (!RegisterClass(&wc) // Register Our Class + && GetLastError() != 1410) // Class is Already Existent + { + return; + } + } + + _wnd = CreateWindowEx( + WS_EX_APPWINDOW, // Extended Style For The Window + _T(WIN_CLASS_NAME), // Class Name + NULL, // Window Title + WS_POPUPWINDOW, // Defined Window Style + 0, 0, // Window Position + 0, 0, // Window Width And Height + NULL, // No Parent Window + NULL, // No Menu + s_hInstance, // Instance + NULL); // No Param + + if (_wnd) + { + SetWindowLongPtr(_wnd, GWLP_USERDATA, (LONG_PTR)this); + } +} + +MciPlayer::~MciPlayer() +{ + Close(); + DestroyWindow(_wnd); +} + +void MciPlayer::Open(tstring pFileName, UINT uId) +{ + if (pFileName.empty() || !_wnd) return; + int nLen = (int)pFileName.size(); + if (!nLen) return; + + strExt = FileUtils::getFileExtension(pFileName); + + Close(); + + MCI_OPEN_PARMS mciOpen = { 0 }; + MCIERROR mciError; + mciOpen.lpstrDeviceType = (LPCTSTR)MCI_ALL_DEVICE_ID; + mciOpen.lpstrElementName = pFileName.c_str(); + + mciError = mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast(&mciOpen)); + if (mciError) return; + + _dev = mciOpen.wDeviceID; + _soundID = uId; + _playing = false; +} + +void MciPlayer::Play(UINT uTimes /* = 1 */) +{ + if (!_dev) + { + return; + } + MCI_PLAY_PARMS mciPlay = { 0 }; + mciPlay.dwCallback = reinterpret_cast(_wnd); + s_mciError = mciSendCommand(_dev, MCI_PLAY, MCI_FROM | MCI_NOTIFY, reinterpret_cast(&mciPlay)); + if (!s_mciError) + { + _playing = true; + _times = uTimes; + } +} + +void MciPlayer::Close() +{ + if (_playing) + { + Stop(); + } + if (_dev) + { + _SendGenericCommand(MCI_CLOSE); + } + _dev = 0; + _playing = false; +} + +void MciPlayer::Pause() +{ + _SendGenericCommand(MCI_PAUSE); + _playing = false; +} + +void MciPlayer::Resume() +{ + if (strExt == _T(".mid")) + { + // midi not support MCI_RESUME, should get the position and use MCI_FROM + MCI_STATUS_PARMS mciStatusParms; + MCI_PLAY_PARMS mciPlayParms; + mciStatusParms.dwItem = MCI_STATUS_POSITION; + _SendGenericCommand(MCI_STATUS, MCI_STATUS_ITEM, reinterpret_cast(&mciStatusParms)); // MCI_STATUS + mciPlayParms.dwFrom = mciStatusParms.dwReturn; // get position + _SendGenericCommand(MCI_PLAY, MCI_FROM, reinterpret_cast(&mciPlayParms)); // MCI_FROM + } + else + { + _SendGenericCommand(MCI_RESUME); + _playing = true; + } +} + +void MciPlayer::Stop() +{ + _SendGenericCommand(MCI_STOP); + _playing = false; + _times = 0; +} + +void MciPlayer::Rewind() +{ + if (!_dev) + { + return; + } + mciSendCommand(_dev, MCI_SEEK, MCI_SEEK_TO_START, 0); + + MCI_PLAY_PARMS mciPlay = { 0 }; + mciPlay.dwCallback = reinterpret_cast(_wnd); + _playing = mciSendCommand(_dev, MCI_PLAY, MCI_NOTIFY, reinterpret_cast(&mciPlay)) ? false : true; +} + +bool MciPlayer::IsPlaying() +{ + return _playing; +} + +UINT MciPlayer::GetSoundID() +{ + return _soundID; +} + +void MciPlayer::_SendGenericCommand(int nCommand, DWORD_PTR param1 /*= 0*/, DWORD_PTR parma2 /*= 0*/) +{ + if (!_dev) + { + return; + } + mciSendCommand(_dev, nCommand, param1, parma2); +} + + + + +//////////////////////////////////////////////////////////////////// +// MusicUtils +//////////////////////////////////////////////////////////////////// + + +typedef std::map MusicList; +typedef std::pair Music; + + +static unsigned int _Hash(tstring key); + + +static MusicList& sharedList() +{ + static MusicList s_List; + return s_List; +} + +static MciPlayer& sharedMusic() +{ + static MciPlayer s_Music; + return s_Music; +} + +void MusicUtils::end() +{ + sharedMusic().Close(); + + for (auto& iter : sharedList()) + { + SAFE_DELETE(iter.second); + } + sharedList().clear(); + return; +} + +////////////////////////////////////////////////////////////////////////// +// BackgroundMusic +////////////////////////////////////////////////////////////////////////// + +void MusicUtils::playBackgroundMusic(tstring pszFilePath, bool bLoop) +{ + if (pszFilePath.empty()) + { + return; + } + + sharedMusic().Open(pszFilePath, ::_Hash(pszFilePath)); + sharedMusic().Play((bLoop) ? -1 : 1); +} + +void MusicUtils::stopBackgroundMusic(bool bReleaseData) +{ + if (bReleaseData) + { + sharedMusic().Close(); + } + else + { + sharedMusic().Stop(); + } +} + +void MusicUtils::pauseBackgroundMusic() +{ + sharedMusic().Pause(); +} + +void MusicUtils::resumeBackgroundMusic() +{ + sharedMusic().Resume(); +} + +void MusicUtils::rewindBackgroundMusic() +{ + sharedMusic().Rewind(); +} + +bool MusicUtils::isBackgroundMusicPlaying() +{ + return sharedMusic().IsPlaying(); +} + +////////////////////////////////////////////////////////////////////////// +// effect function +////////////////////////////////////////////////////////////////////////// + +unsigned int MusicUtils::playMusic(tstring pszFilePath, bool bLoop) +{ + unsigned int nRet = ::_Hash(pszFilePath); + + preloadMusic(pszFilePath); + + MusicList::iterator p = sharedList().find(nRet); + if (p != sharedList().end()) + { + p->second->Play((bLoop) ? -1 : 1); + } + return nRet; +} + +void MusicUtils::stopMusic(unsigned int nSoundId) +{ + MusicList::iterator p = sharedList().find(nSoundId); + if (p != sharedList().end()) + { + p->second->Stop(); + } +} + +void MusicUtils::preloadMusic(tstring pszFilePath) +{ + if (pszFilePath.empty()) return; + + int nRet = ::_Hash(pszFilePath); + + if (sharedList().end() != sharedList().find(nRet)) return; + + sharedList().insert(Music(nRet, new MciPlayer())); + MciPlayer * pPlayer = sharedList()[nRet]; + pPlayer->Open(pszFilePath, nRet); + + if (nRet == pPlayer->GetSoundID()) return; + + delete pPlayer; + sharedList().erase(nRet); + nRet = 0; +} + +void MusicUtils::pauseMusic(unsigned int nSoundId) +{ + MusicList::iterator p = sharedList().find(nSoundId); + if (p != sharedList().end()) + { + p->second->Pause(); + } +} + +void MusicUtils::pauseAllMusics() +{ + for (auto& iter : sharedList()) + { + iter.second->Pause(); + } +} + +void MusicUtils::resumeMusic(unsigned int nSoundId) +{ + MusicList::iterator p = sharedList().find(nSoundId); + if (p != sharedList().end()) + { + p->second->Resume(); + } +} + +void MusicUtils::resumeAllMusics() +{ + for (auto& iter : sharedList()) + { + iter.second->Resume(); + } +} + +void MusicUtils::stopAllMusics() +{ + for (auto& iter : sharedList()) + { + iter.second->Stop(); + } +} + +void MusicUtils::unloadMusic(LPCTSTR pszFilePath) +{ + unsigned int nID = ::_Hash(pszFilePath); + + MusicList::iterator p = sharedList().find(nID); + if (p != sharedList().end()) + { + SAFE_DELETE(p->second); + sharedList().erase(nID); + } +} + + + +////////////////////////////////////////////////////////////////////////// +// static function +////////////////////////////////////////////////////////////////////////// + +LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + MciPlayer * pPlayer = NULL; + if (MM_MCINOTIFY == Msg + && MCI_NOTIFY_SUCCESSFUL == wParam + && (pPlayer = (MciPlayer *)GetWindowLongPtr(hWnd, GWLP_USERDATA))) + { + if (pPlayer->_times) + { + --pPlayer->_times; + } + + if (pPlayer->_times) + { + mciSendCommand(lParam, MCI_SEEK, MCI_SEEK_TO_START, 0); + + MCI_PLAY_PARMS mciPlay = { 0 }; + mciPlay.dwCallback = reinterpret_cast(hWnd); + mciSendCommand(lParam, MCI_PLAY, MCI_NOTIFY, reinterpret_cast(&mciPlay)); + } + else + { + pPlayer->_playing = false; + } + return 0; + } + return DefWindowProc(hWnd, Msg, wParam, lParam); +} + +unsigned int _Hash(tstring key) +{ + unsigned int len = unsigned(key.size()); + unsigned int hash = 0; + + for (unsigned i = 0; i < len; i++) + { + hash *= 16777619; + hash ^= (unsigned int)(unsigned char)toupper(key[i]); + } + return (hash); +} \ No newline at end of file diff --git a/Easy2D/Tool/Timer.cpp b/Easy2D/Tool/Timer.cpp new file mode 100644 index 00000000..aa62ff90 --- /dev/null +++ b/Easy2D/Tool/Timer.cpp @@ -0,0 +1,183 @@ +#include "..\Easy2d.h" + +// жʱ +static std::vector s_nTimers; + +Timer::Timer(tstring name, UINT ms, const TIMER_CALLBACK & callback) : + m_sName(name), + m_bRunning(false), + m_callback(callback) +{ + setInterval(ms); // öʱʱ +} + +Timer::~Timer() +{ +} + +void Timer::start() +{ + // ־öʱ + this->m_bRunning = true; + // ¼ǰʱ + QueryPerformanceCounter(&m_nLast); +} + +void Timer::stop() +{ + this->m_bRunning = false; // ־öʱֹͣ +} + +bool Timer::isRunning() +{ + return m_bRunning; // ȡöʱ״̬ +} + +void Timer::setInterval(UINT ms) +{ + // öʱʱ + LARGE_INTEGER nFreq; + QueryPerformanceFrequency(&nFreq); + m_nAnimationInterval.QuadPart = (LONGLONG)(ms / 1000.0 * nFreq.QuadPart); + // ʱʱ + this->m_nMilliSeconds = ms; +} + +void Timer::setCallback(const TIMER_CALLBACK & callback) +{ + m_callback = callback; // ص +} + +void Timer::setName(tstring name) +{ + m_sName = name; // ޸Ķʱ +} + +UINT Timer::getInterval() const +{ + return m_nMilliSeconds; // ȡʱʱ +} + +tstring Timer::getName() const +{ + return m_sName; // ȡʱ +} + +void Timer::__exec() +{ + // ʱΪ + if (!s_nTimers.size()) + { + return; + } + // ȡǰʱ + static LARGE_INTEGER nNow; + QueryPerformanceCounter(&nNow); + // ѭеĶʱ + for (auto timer : s_nTimers) + { + // ʱδУʱ + if (!timer->m_bRunning) + { + continue; + } + // жʱǷ㹻 + if (nNow.QuadPart - timer->m_nLast.QuadPart > timer->m_nAnimationInterval.QuadPart) + { + // ķ¼¼ʱ + timer->m_nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % timer->m_nAnimationInterval.QuadPart); + // лص + timer->m_callback(); + } + } +} + +void Timer::addTimer(Timer * timer) +{ + // ʱ + timer->start(); + // öʱ + s_nTimers.push_back(timer); +} + +void Timer::addTimer(tstring name, UINT ms, const TIMER_CALLBACK & callback) +{ + // ʱ + auto timer = new Timer(name, ms, callback); + // Ӷʱ + addTimer(timer); +} + +Timer * Timer::getTimer(tstring name) +{ + // ǷͬƵĶʱ + for (auto timer : s_nTimers) + { + if (timer->m_sName == name) + { + // ҵظöʱָ + return timer; + } + } + // δҵؿָ + return nullptr; +} + +bool Timer::startTimer(tstring name) +{ + // ָƵĶʱҵöʱ + auto t = getTimer(name); + if (t) + { + // ʱ + t->start(); + return true; + } + // δҵͬƵĶʱ false + return false; +} + +bool Timer::stopTimer(tstring name) +{ + // ָֹͣƵĶʱҵöʱ + auto t = getTimer(name); + if (t) + { + // ֹͣʱ + t->stop(); + return true; + } + // δҵͬƵĶʱ false + return false; +} + +bool Timer::deleteTimer(tstring name) +{ + // + std::vector::iterator iter; + // ѭжʱ + for (iter = s_nTimers.begin(); iter != s_nTimers.end(); iter++) + { + // ͬƵĶʱ + if ((*iter)->m_sName == name) + { + // ɾöʱ + delete (*iter); + s_nTimers.erase(iter); + return true; + } + } + // δҵͬƵĶʱ false + return false; +} + +void Timer::clearAllTimers() +{ + // ɾжʱ + for (auto t : s_nTimers) + { + delete t; + } + // + s_nTimers.clear(); +} diff --git a/Easy2D/easy2d.h b/Easy2D/easy2d.h new file mode 100644 index 00000000..e3471e81 --- /dev/null +++ b/Easy2D/easy2d.h @@ -0,0 +1,946 @@ +/****************************************************** +* Easy2D Game Engine (v1.0.0) +* http://www.easy2d.cn +* +* Depends on EasyX (Ver:20170827(beta)) +******************************************************/ + +#pragma once + +#ifndef __cplusplus + #error Easy2D is only for C++ +#endif + + +// String macros + +#ifdef UNICODE + #define tstring std::wstring +#else + #define tstring std::string +#endif + + +// Safe macros + +#define SAFE_DELETE(p) { delete (p); (p) = nullptr; } +#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p) = nullptr; } } +#define SAFE_RELEASE(p) { if (p) p->release(); } + + +#include +#include +#include +#include +#include +#include + + +#if defined(UNICODE) && (_DEBUG) + #pragma comment(lib,"Easy2Ddw.lib") +#elif !defined(UNICODE) && (_DEBUG) + #pragma comment(lib,"Easy2Dd.lib") +#elif defined(UNICODE) + #pragma comment(lib,"Easy2Dw.lib") +#elif !defined(UNICODE) + #pragma comment(lib,"Easy2D.lib") +#endif + + +// Class Declare + +namespace easy2d { + +// +class Application; +class Scene; +class KeyMsg; +class MouseMsg; +class FreePool; +// ʽ +class Color; +class FontStyle; +// +class Timer; +class MusicUtils; +class FileUtils; +// +class Object; +class Node; +class BatchNode; +class MouseNode; +class Image; +class Text; +class Shape; +class Rect; +class Circle; +class Button; +class TextButton; +class ImageButton; + + +typedef unsigned int VK_KEY; +typedef std::function CLICK_CALLBACK; +typedef std::function TIMER_CALLBACK; +typedef std::function KEY_CALLBACK; + + +class Application +{ +protected: + tstring m_sTitle; + Scene* m_currentScene; + Scene* m_nextScene; + std::stack m_sceneStack; + LARGE_INTEGER m_nAnimationInterval; + int m_nWidth; + int m_nHeight; + int m_nWindowMode; + bool m_bRunning; + bool m_bPause; + bool m_bSaveScene; + +protected: + void _initGraph(); + void _mainLoop(); + void _enterNextScene(); + +public: + Application(); + ~Application(); + + // ڿѡģʽ + enum { SHOW_CONSOLE = 1, NO_CLOSE = 2, NO_MINI_MIZE = 4 }; + // ȡʵ + static Application * get(); + // ԭ + static void setOrigin(int originX, int originY); + // ȡԭ + static int getOriginX(); + // ȡԭ + static int getOriginY(); + // + int run(); + // ͣ + void pause(); + // ֹ + void quit(); + // ֹ + void end(); + // ͼ + void createWindow(int width, int height, int mode = 0); + // ͼ + void createWindow(tstring title, int width, int height, int mode = 0); + // ޸ĴڴС + void setWindowSize(int width, int height); + // ôڱ + void setWindowText(tstring title); + // رմ + void close(); + // ȡڿ + int getWidth() const; + // ȡڸ߶ + int getHeight() const; + // л + void enterScene(Scene *scene, bool save = true); + // һ + void backScene(); + // ϷǷ + bool isRunning(); + // ֡ + void setFPS(DWORD fps); + // ûͼʽΪĬֵ + void reset(); + // ͷڴԴ + void free(); + // ٸö + void destory(); + // ȡǰ + Scene * getCurrentScene(); + // ȡ Easy2D 汾 + LPCTSTR getVersion(); +}; + +class FreePool +{ + friend class Application; + +private: + static void __flush(); + +public: + // һڵͷų + static void add(Object * nptr); +}; + +class Scene +{ + friend class Application; + friend class MouseMsg; + +protected: + std::vector m_vChildren; + +protected: + void _exec(); + void _onDraw(); + +public: + Scene(); + ~Scene(); + + // ӳԱ + void add(Node * child, int zOrder = 0); + // ɾӳԱ + bool del(Node * child); + // ӳԱ + void clearAllChildren(); +}; + + +class MouseMsg +{ + friend class Application; + +private: + static void __exec(); + +public: + UINT uMsg; // ǰϢ + bool mkLButton; // Ƿ + bool mkMButton; // мǷ + bool mkRButton; // ҼǷ + short x; // ǰ x + short y; // ǰ y + short wheel; // ֵֹ (120 ı) + +public: + // ȡǰϢ + static MouseMsg getMsg(); + // Ƿ + static bool getLButtonDown(); + // ҼǷ + static bool getRButtonDown(); + // мǷ + static bool getMButtonDown(); + // ȡX + static int getMouseX(); + // ȡY + static int getMouseY(); + // ȡֵ + static int getMouseWheel(); + // ƶϢ + static bool getMouseMovedMsg(); + // ˫Ϣ + static bool getLButtonDBClickedMsg(); + // ҼϢ + static bool getLButtonDownMsg(); + // Ϣ + static bool getLButtonUpMsg(); + // Ҽ˫Ϣ + static bool getRButtonDBClicked(); + // ҼϢ + static bool getRButtonDownMsg(); + // ҼϢ + static bool getRButtonUpMsg(); + // м˫Ϣ + static bool getMButtonDBClicked(); + // мϢ + static bool getMButtonDownMsg(); + // мϢ + static bool getMButtonUpMsg(); + // ֲϢ + static bool getWheelMsg(); + // Ϣ + static void resetMouseMsg(); +}; + + +class KeyMsg +{ + friend class Application; + +public: + // ĸֵ + static const VK_KEY A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; + // ֵּ + static const VK_KEY NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9, NUM_0; + // Сֵּ + static const VK_KEY NUMPAD_1, NUMPAD_2, NUMPAD_3, NUMPAD_4, NUMPAD_5, NUMPAD_6, NUMPAD_7, NUMPAD_8, NUMPAD_9, NUMPAD_0, Decimal; + // Ƽֵ + static const VK_KEY Enter, Space, Up, Down, Left, Right, Esc, Shift, LShift, RShift, Ctrl, LCtrl, RCtrl; + // F ֵ + static const VK_KEY F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12; + +private: + static void __exec(); + +protected: + tstring m_sName; + KEY_CALLBACK m_callback; + +public: + KeyMsg(tstring name, const KEY_CALLBACK& callback); + ~KeyMsg(); + + // ִлص + void onKbHit(VK_KEY key); + + // Ӽ̼ + static void addListener(tstring name, const KEY_CALLBACK& callback); + // ɾ̼ + static bool delListener(tstring name); + // ɾм̼ + static void clearAllListener(); + // жϼǷ񱻰£·true + static bool isKeyDown(VK_KEY key); +}; + + +class FileUtils +{ +public: + // õļչСд + static tstring getFileExtension(const tstring& filePath); + /** + * 򿪱ļԻ򣬵õЧ· true + * ļ·ַڱ⣬չˣĬչ + */ + static bool getSaveFilePath(tstring& path, LPCTSTR title = _T("浽"), LPCTSTR defExt = NULL); +}; + + +class MusicUtils +{ +public: + // ű + static void playBackgroundMusic(tstring pszFilePath, bool bLoop = false); + // ֹͣ + static void stopBackgroundMusic(bool bReleaseData = false); + // ͣ + static void pauseBackgroundMusic(); + // ű + static void resumeBackgroundMusic(); + // ͷű + static void rewindBackgroundMusic(); + // Ƿڲ + static bool isBackgroundMusicPlaying(); + + // Ч + static unsigned int playMusic(tstring pszFilePath, bool loop = false); + // ֹͣЧ + static void stopMusic(unsigned int nSoundId); + // ԤЧ + static void preloadMusic(tstring pszFilePath); + // ͣЧ + static void pauseMusic(unsigned int nSoundId); + // Ч + static void resumeMusic(unsigned int nSoundId); + // жЧ + static void unloadMusic(LPCTSTR pszFilePath); + + // ͣ + static void pauseAllMusics(); + // + static void resumeAllMusics(); + // ֹͣ + static void stopAllMusics(); + // ֹ֣ͣͷڴ + static void end(); +}; + + +class Timer +{ + friend class Application; + +protected: + bool m_bRunning; + tstring m_sName; + TIMER_CALLBACK m_callback; + LARGE_INTEGER m_nLast; + LARGE_INTEGER m_nAnimationInterval; + UINT m_nMilliSeconds; + +private: + static void __exec(); + +public: + Timer(tstring name, UINT ms, const TIMER_CALLBACK & callback); + ~Timer(); + + // ʱ + void start(); + // ֹͣʱ + void stop(); + // ʱǷ + bool isRunning(); + // üʱ + void setInterval(UINT ms); + // ûص + void setCallback(const TIMER_CALLBACK& callback); + // öʱ + void setName(tstring name); + + // ȡʱʱ + UINT getInterval() const; + // ȡʱ + tstring getName() const; + + // Ӷʱ + static void addTimer(Timer * timer); + // Ӷʱ + static void addTimer(tstring name, UINT ms, const TIMER_CALLBACK & callback); + // ƻȡʱ + static Timer * getTimer(tstring name); + // ضʱ + static bool startTimer(tstring name); + // ֹͣضʱ + static bool stopTimer(tstring name); + // ɾضʱ + static bool deleteTimer(tstring name); + // ɾжʱ + static void clearAllTimers(); +}; + + +class Color +{ +public: + static const COLORREF black; // ɫ + static const COLORREF blue; // ɫ + static const COLORREF green; // ɫ + static const COLORREF cyan; // ɫ + static const COLORREF red; // ɫ + static const COLORREF magenta; // ɫ + static const COLORREF brown; // ɫ + static const COLORREF lightgray; // ɫ + static const COLORREF darkgray; // ɫ + static const COLORREF lightblue; // ɫ + static const COLORREF lightgreen; // ɫ + static const COLORREF lightcyan; // ɫ + static const COLORREF lightred; // ɫ + static const COLORREF lightmagenta; // ɫ + static const COLORREF yellow; // ɫ + static const COLORREF white; // ɫ + + // ͨ졢̡ɫϳɫ + static COLORREF getFromRGB(BYTE r, BYTE g, BYTE b); + // ͨɫࡢͶȡȺϳɫ + static COLORREF getFromHSL(float H, float S, float L); + // ͨɫࡢͶȡȺϳɫ + static COLORREF getFromHSV(float H, float S, float V); + + // ָɫеĺɫֵ + static BYTE getRValue(COLORREF color); + // ָɫеɫֵ + static BYTE getGValue(COLORREF color); + // ָɫеɫֵ + static BYTE getBValue(COLORREF color); + // ָɫӦĻҶֵɫ + static COLORREF getGray(COLORREF color); +}; + + +class Object +{ + friend class FreePool; + +protected: + int m_nRef; + +public: + Object(); + virtual ~Object(); + + void retain(); + void release(); +}; + + +class FontStyle : + public virtual Object +{ + friend class Text; + +protected: + LOGFONT m_font; + +public: + FontStyle(); + /** + * ʹ [ơֺšϸֿб塢»ߡɾߡַдǶȡ + * ÿַдǶȡ] Դʽ + */ + FontStyle(LPCTSTR fontfamily, LONG height = 18, LONG weight = 0, LONG width = 0, + bool italic = 0, bool underline = 0, bool strikeout = 0, LONG escapement = 0, + LONG orientation = 0, bool quality = true); + virtual ~FontStyle(); + + // ȡĬ + static FontStyle * getDefault(); + // ַƽ߶ + void setHeight(LONG value); + // ַƽȣ0ʾӦ + void setWidth(LONG value); + // + void setFontFamily(LPCTSTR value); + // ַʻϸΧ0~1000ĬΪ0 + void setWeight(LONG value); + // б + void setItalic(bool value); + // » + void setUnderline(bool value); + // ɾ + void setStrikeOut(bool value); + // ַдǶȣλ0.1ȣĬΪ0 + void setEscapement(LONG value); + // ÿַдǶȣλ0.1ȣĬΪ0 + void setOrientation(LONG value); + // 忹ݣĬΪtrue + void setQuality(bool value); +}; + + +class FontWeight +{ +public: + static const LONG dontcare; // ϸֵ 0 + static const LONG thin; // ϸֵ 100 + static const LONG extraLight; // ϸֵ 200 + static const LONG light; // ϸֵ 300 + static const LONG normal; // ϸֵ 400 + static const LONG regular; // ϸֵ 400 + static const LONG medium; // ϸֵ 500 + static const LONG demiBlod; // ϸֵ 600 + static const LONG blod; // ϸֵ 700 + static const LONG extraBold; // ϸֵ 800 + static const LONG black; // ϸֵ 900 + static const LONG heavy; // ϸֵ 900 +}; + + +class Node : + public virtual Object +{ + friend class Scene; + friend class Layer; + friend class BatchNode; + +protected: + int m_nZOrder; + bool m_bDisplay; + Scene* m_pScene; + int m_nX; + int m_nY; + +protected: + virtual bool _exec(bool active); + virtual void _onDraw() = 0; + void setParentScene(Scene * scene); + +public: + Node(); + Node(int x, int y); + virtual ~Node(); + + // ȡڵ + const int getX() const; + // ȡڵ + const int getY() const; + // ýڵ + virtual void setX(int x); + // ýڵ + virtual void setY(int y); + // ýڵ + virtual void setPos(int x, int y); + // ƶڵ + virtual void move(int x, int y); + // ڵǷʾ + bool display() const; + // ýڵǷʾ + void setDisplay(bool value); + // ȡڵͼ˳ + virtual int getZOrder() const; + // ýڵͼ˳0ΪȻƣʾײ㣩 + virtual void setZOrder(int z); + // ȡڵڳ + Scene * getParentScene(); +}; + + +class BatchNode : + public virtual Node +{ +protected: + std::vector m_vChildren; + +protected: + virtual bool _exec(bool active) override; + virtual void _onDraw() override; + +public: + BatchNode(); + virtual ~BatchNode(); + + // ӽڵ + void add(Node *child, int z_Order = 0); + // ɾӽڵ + bool del(Node * child); + // ӽڵ + void clearAllChildren(); +}; + + +class Image : + public virtual Node +{ + friend class ImageButton; + +protected: + CImage m_Image; + CRect m_rDest; + CRect m_rSrc; + float m_fScaleX; + float m_fScaleY; + +protected: + virtual void _onDraw() override; + +public: + Image(); + /** + * ͼƬļȡͼ(png/bmp/jpg/gif/emf/wmf/ico) + * ͼƬļͼƬü꣬ͼƬüȺ͸߶ + */ + Image(LPCTSTR ImageFile, int x = 0, int y = 0, int width = 0, int height = 0); + virtual ~Image(); + + // ȡͼ + int getWidth() const; + // ȡͼ߶ + int getHeight() const; + // ȡ + float getScaleX() const; + // ȡ + float getScaleY() const; + + /** + * ͼƬļȡͼ(png/bmp/jpg/gif/emf/wmf/ico) + * ͼƬļͼƬü꣬ͼƬüȺ͸߶ + */ + void setImageFile(LPCTSTR ImageFile, int x = 0, int y = 0, int width = 0, int height = 0); + /** + * Դļȡͼ񣬲֧ png (bmp/jpg/gif/emf/wmf/ico) + * ԴƣͼƬü꣬ͼƬüȺ͸߶ + */ + void setImageRes(LPCTSTR pResName, int x = 0, int y = 0, int width = 0, int height = 0); + // üͼƬüָ stretch 죩 + void crop(int x = 0, int y = 0, int width = 0, int height = 0); + // ͼƬ쵽̶ + void stretch(int width = 0, int height = 0); + // ͼƬ0 ~ 1.0f + void scale(float scaleX, float scaleY); + // ͼƬλ + void setPos(int x, int y) override; + // ƶͼƬ + void move(int x, int y) override; + // ͼƬ + void setX(int x) override; + // ͼƬ + void setY(int y) override; + // ͸ɫ + void setTransparentColor(COLORREF value); + // 浽ͼ + static void screenshot(); +}; + + +class Text : + public virtual Node +{ + friend class TextButton; + +protected: + tstring m_sText; + COLORREF m_color; + FontStyle * m_pFontStyle; + +protected: + virtual void _onDraw() override; + +public: + Text(); + // ַɫ崴 + Text(tstring text, COLORREF color = Color::white, FontStyle * font = FontStyle::getDefault()); + // ݺꡢַɫ崴 + Text(int x, int y, tstring text, COLORREF color = Color::white, FontStyle * font = FontStyle::getDefault()); + virtual ~Text(); + + // ȡǰɫ + COLORREF getColor() const; + // ȡǰ + tstring getText() const; + // ȡǰ + FontStyle * getFontStyle(); + // ȡֿ + int getWidth(); + // ȡָ߶ + int getHeight(); + // ıǷΪ + bool isEmpty() const; + + // + void setText(tstring text); + // ɫ + void setColor(COLORREF color); + // + void setFontStyle(FontStyle * style); +}; + + +class MouseNode : + public virtual Node +{ +private: + bool m_bTarget; + bool m_bBlock; + enum { NORMAL, MOUSEIN, SELECTED } m_eStatus; + CLICK_CALLBACK m_callback; + +protected: + virtual bool _exec(bool active) override; + virtual void _onDraw() override; + + void _setNormal(); + void _setMouseIn(); + void _setSelected(); + + // дúʵλõж + virtual void _judge() = 0; + // ״̬ + virtual void _onNormal() = 0; + // ʱ + virtual void _onMouseIn() = 0; + // ѡʱ + virtual void _onSelected() = 0; + +public: + MouseNode(); + virtual ~MouseNode(); + + // ʱ + virtual void onClicked(); + // Ƿ + virtual bool isMouseIn(); + // Ƿѡ + virtual bool isSelected(); + // ûص + virtual void setOnMouseClicked(const CLICK_CALLBACK & callback); + // ״̬ + virtual void reset(); + // ýڵǷϢ + void setBlock(bool block); +}; + + +class Button : + public virtual MouseNode +{ +protected: + int m_nWidth; + int m_nHeight; + bool m_bEnable; + +protected: + virtual bool _exec(bool active) override; + virtual void _onDraw() override; + virtual void _judge() override; + + virtual void _onNormal() = 0; + virtual void _onMouseIn() = 0; + virtual void _onSelected() = 0; + virtual void _onDisable() = 0; + +public: + Button(); + virtual ~Button(); + + // ťǷ + virtual bool isEnable(); + // Ƿ + virtual void setEnable(bool enable); +}; + + + +class TextButton : + public virtual Button +{ +protected: + Text * m_pNormalText; + Text * m_pMouseInText; + Text * m_pSelectedText; + Text * m_pUnableText; + +protected: + // λãʾ + void resetTextPosition(); + + virtual void _onNormal() override; + virtual void _onMouseIn() override; + virtual void _onSelected() override; + virtual void _onDisable() override; + +public: + TextButton(); + TextButton(Text * text); + virtual ~TextButton(); + + // ðť + void setNormalText(Text * text); + // ʱİť + void setMouseInText(Text * text); + // ѡʱİť + void setSelectedText(Text * text); + // ðťʱİť + void setUnableText(Text * text); + + // ðť + virtual void setX(int x) override; + // ðť + virtual void setY(int y) override; + // ðť + virtual void setPos(int x, int y) override; +}; + + + +class ImageButton : + public virtual Button +{ +protected: + Image * m_pNormalImage; + Image * m_pMouseInImage; + Image * m_pSelectedImage; + Image * m_pUnableImage; + +protected: + // ͼƬλãʾ + void resetImagePosition(); + + virtual void _onNormal() override; + virtual void _onMouseIn() override; + virtual void _onSelected() override; + virtual void _onDisable() override; + +public: + ImageButton(); + ImageButton(Image * image); + virtual ~ImageButton(); + + // ðťͼƬ + void setNormalImage(Image * image); + // ʱİťͼƬ + void setMouseInImage(Image * image); + // ѡʱİťͼƬ + void setSelectedImage(Image * image); + // ðťʱİťͼƬ + void setUnableImage(Image * image); + + // ðť + virtual void setX(int x) override; + // ðť + virtual void setY(int y) override; + // ðť + virtual void setPos(int x, int y) override; +}; + + +class Shape : + public virtual Node +{ +protected: + enum STYLE { round, solid, fill }; // ״ʽ + STYLE _style; + COLORREF fillColor = 0; + COLORREF lineColor = 0; + +protected: + virtual void _onDraw() override; + virtual void solidShape() = 0; + virtual void fillShape() = 0; + virtual void roundShape() = 0; + +public: + Shape(); + virtual ~Shape(); + + // ȡ״ɫ + COLORREF getFillColor() const; + // ȡ״ɫ + COLORREF getLineColor() const; + // ɫ + void setFillColor(COLORREF color); + // ɫ + void setLineColor(COLORREF color); +}; + + +class Rect : + public virtual Shape +{ +protected: + int m_nWidth; + int m_nHeight; + +protected: + virtual void solidShape() override; + virtual void fillShape() override; + virtual void roundShape() override; + +public: + Rect(); + Rect(int x, int y, int width, int height); + virtual ~Rect(); + + // ȡο + int getWidth() const; + // ȡθ߶ + int getHeight() const; + // þο + void setWidth(int width); + // þθ߶ + void setHeight(int height); + // þδС + void setSize(int width, int height); +}; + + +class Circle : + public virtual Shape +{ +protected: + int m_nRadius; + +protected: + virtual void solidShape() override; + virtual void fillShape() override; + virtual void roundShape() override; + +public: + Circle(); + Circle(int x, int y, int radius); + virtual ~Circle(); + + // ȡԲΰ뾶 + int getRadius() const; + // Բΰ뾶 + void setRadius(int m_nRadius); +}; + +} // End of easy2d namespace + + +// Ĭʹ easy2d ռ +using namespace easy2d; \ No newline at end of file