diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/UI/GameScreen.h b/UI/GameScreen.h new file mode 100644 index 0000000000..2bd9490501 --- /dev/null +++ b/UI/GameScreen.h @@ -0,0 +1,4 @@ +#pragma once + + +// Game screen: Contains options such as \ No newline at end of file diff --git a/UI/MenuScreens.cpp b/UI/MenuScreens.cpp index 5d197b16bb..16e90863dc 100644 --- a/UI/MenuScreens.cpp +++ b/UI/MenuScreens.cpp @@ -181,6 +181,7 @@ void LogoScreen::render() { // ================== MenuScreen::MenuScreen() : frames_(0) { + // dl.StartDownload("http://www.ppsspp.org/unofficial/Win32/at3plusdecoder.dll.gz", "D:/at3plusdecoder.dll"); } void MenuScreen::update(InputState &input_state) { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index ecb6c6d70e..e68d183ae8 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -30,6 +30,7 @@ #include #include "base/logging.h" +#include "base/mutex.h" #include "base/NativeApp.h" #include "file/vfs.h" #include "file/zip_read.h" @@ -43,17 +44,18 @@ #include "ui/screen.h" #include "ui/ui.h" #include "ui/ui_context.h" +#include "ui/view.h" -#include "base/mutex.h" -#include "FileUtil.h" -#include "LogManager.h" -#include "../../Core/PSPMixer.h" -#include "../../Core/CPU.h" -#include "../../Core/Config.h" -#include "../../Core/HLE/sceCtrl.h" -#include "../../Core/Host.h" -#include "../../Core/SaveState.h" -#include "../../Common/MemArena.h" +#include "Common/FileUtil.h" +#include "Common/LogManager.h" +#include "Core/PSPMixer.h" +#include "Core/CPU.h" +#include "Core/Config.h" +#include "Core/HLE/sceCtrl.h" +#include "Core/Host.h" +#include "Core/SaveState.h" +#include "Core/HW/atrac3plus.h" +#include "Common/MemArena.h" #include "ui_atlas.h" #include "EmuScreen.h" @@ -61,6 +63,12 @@ #include "GameInfoCache.h" #include "UIShader.h" +#include "UI/PluginScreen.h" + +// The new UI framework, for initialization + +static UI::Theme ui_theme; + #ifdef ARM #include "../../android/jni/ArmEmitterTest.h" #endif @@ -157,31 +165,24 @@ static AndroidLogger *logger = 0; std::string boot_filename = ""; -void NativeHost::InitSound(PMixer *mixer) -{ +void NativeHost::InitSound(PMixer *mixer) { g_mixer = mixer; } -void NativeHost::ShutdownSound() -{ +void NativeHost::ShutdownSound() { g_mixer = 0; } -int NativeMix(short *audio, int num_samples) -{ - if (g_mixer) - { +int NativeMix(short *audio, int num_samples) { + if (g_mixer) { return g_mixer->Mix(audio, num_samples); - } - else - { + } else { //memset(audio, 0, numSamples * 2); return 0; } } -void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape) -{ +void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape) { *app_nice_name = "PPSSPP"; *app_dir_name = "ppsspp"; *landscape = true; @@ -191,8 +192,8 @@ void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, boo #endif } -void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *external_directory, const char *installID) -{ +void NativeInit(int argc, const char *argv[], + const char *savegame_directory, const char *external_directory, const char *installID) { EnableFZ(); setlocale( LC_ALL, "C" ); std::string user_data_path = savegame_directory; @@ -344,22 +345,29 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co g_gameInfoCache.Init(); } -void NativeInitGraphics() -{ +void NativeInitGraphics() { gl_lost_manager_init(); ui_draw2d.SetAtlas(&ui_atlas); screenManager = new ScreenManager(); + if (boot_filename.empty()) { - screenManager->switchScreen(new LogoScreen(boot_filename)); + // If first run and can't autoinstall, let's send the user to the atrac3plus download screen. + if (Atrac3plus_Decoder::CanAutoInstall()) { + Atrac3plus_Decoder::DoAutoInstall(); + } else if ((true || g_Config.bFirstRun) && !Atrac3plus_Decoder::IsInstalled()) { + screenManager->switchScreen(new PluginScreen()); + } else { + screenManager->switchScreen(new LogoScreen(boot_filename)); + } } else { // Go directly into the game. screenManager->switchScreen(new EmuScreen(boot_filename)); } - // screenManager->switchScreen(new FileSelectScreen()); UIShader_Init(); + // Old style theme, to be removed later UITheme theme = {0}; theme.uiFont = UBUNTU24; theme.uiFontSmall = UBUNTU24; @@ -369,6 +377,21 @@ void NativeInitGraphics() theme.checkOn = I_CHECKEDBOX; theme.checkOff = I_SQUARE; + // New style theme + ui_theme.uiFont = UBUNTU24; + ui_theme.uiFontSmall = UBUNTU24; + ui_theme.uiFontSmaller = UBUNTU24; + ui_theme.buttonImage = I_BUTTON; + ui_theme.buttonSelected = I_BUTTON_SELECTED; + ui_theme.checkOn = I_CHECKEDBOX; + ui_theme.checkOff = I_SQUARE; + ui_theme.whiteImage = SOLIDWHITE; + ui_theme.buttonFocusedStyle.bgColor = 0xFFc0c0c0; + ui_theme.buttonDownStyle.bgColor = 0xFFFF00c0; + ui_theme.itemFocusedStyle.bgColor = 0xFF808080; + ui_theme.itemDownStyle.bgColor = 0xFFFFc080; + ui_theme.itemDownStyle.fgColor = 0xFF000000; + ui_draw2d.Init(); ui_draw2d_front.Init(); @@ -383,6 +406,7 @@ void NativeInitGraphics() uiTexture->Bind(0); uiContext = new UIContext(); + uiContext->theme = &ui_theme; uiContext->Init(UIShader_Get(), UIShader_GetPlain(), uiTexture, &ui_draw2d, &ui_draw2d_front); screenManager->setUIContext(uiContext); @@ -395,9 +419,9 @@ void NativeInitGraphics() glstate.viewport.set(0, 0, pixel_xres, pixel_yres); } -void NativeRender() -{ +void NativeRender() { EnableFZ(); + glstate.depthWrite.set(GL_TRUE); glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -416,8 +440,7 @@ void NativeRender() screenManager->render(); } -void NativeUpdate(InputState &input) -{ +void NativeUpdate(InputState &input) { { lock_guard lock(pendingMutex); if (isMessagePending) { @@ -430,8 +453,7 @@ void NativeUpdate(InputState &input) screenManager->update(input); } -void NativeDeviceLost() -{ +void NativeDeviceLost() { g_gameInfoCache.Clear(); screenManager->deviceLost(); gl_lost(); @@ -439,19 +461,16 @@ void NativeDeviceLost() // Should dirty EVERYTHING } -bool NativeIsAtTopLevel() -{ +bool NativeIsAtTopLevel() { // TODO return false; } -void NativeTouch(const TouchInput &touch) -{ +void NativeTouch(const TouchInput &touch) { screenManager->touch(touch); } -void NativeMessageReceived(const char *message, const char *value) -{ +void NativeMessageReceived(const char *message, const char *value) { // We can only have one message queued. lock_guard lock(pendingMutex); if (!isMessagePending) { @@ -461,8 +480,7 @@ void NativeMessageReceived(const char *message, const char *value) } } -void NativeShutdownGraphics() -{ +void NativeShutdownGraphics() { delete uiTexture; uiTexture = NULL; @@ -478,8 +496,7 @@ void NativeShutdownGraphics() gl_lost_manager_shutdown(); } -void NativeShutdown() -{ +void NativeShutdown() { g_gameInfoCache.Shutdown(); delete host; diff --git a/UI/PluginScreen.cpp b/UI/PluginScreen.cpp new file mode 100644 index 0000000000..1a4bc77682 --- /dev/null +++ b/UI/PluginScreen.cpp @@ -0,0 +1,118 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "UI/PluginScreen.h" +#include "ext/vjson/json.h" +#include "i18n/i18n.h" +#include "ui/view.h" +#include "ui/viewgroup.h" +#include "ui/ui_context.h" + + +void UIScreen::update(InputState &input) { + UpdateViewHierarchy(input, root_); +} + +void UIScreen::render() { + UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_); + + screenManager()->getUIContext()->Begin(); + root_->Draw(*screenManager()->getUIContext()); + screenManager()->getUIContext()->End(); + screenManager()->getUIContext()->Flush(); +} + +void UIScreen::touch(const TouchInput &touch) { + root_->Touch(touch); +} + +PluginScreen::PluginScreen() { + // Let's start by downloading the json. We'll find out in Update when it's finished. + json_ = downloader_.StartDownload("http://www.ppsspp.org/update/at3plusdecoder.json", ""); + + I18NCategory *c = GetI18NCategory("Plugin"); + // Build the UI. + + using namespace UI; + + root_ = new LinearLayout(ORIENT_VERTICAL); + + + Margins textMargins(20,17); + + tvDescription_ = root_->Add(new TextView(0, "Audio decoding support", ALIGN_HCENTER, 1.0f, new LinearLayoutParams(textMargins))); + tvDescription_ = root_->Add(new TextView(0, + "Would you like to install Atrac3+ decoding support by Mai?\n" + "Note that there may be legality issues around non-clean-room\n" + "reverse engineered code in the US and some other countries.\n" + "Choose \"More Information\" for more info.\n", ALIGN_LEFT, 1.0f, new LinearLayoutParams(1.0, textMargins))); + + ViewGroup *buttonBar = new LinearLayout(ORIENT_HORIZONTAL); + root_->Add(buttonBar); + + buttonDownload_ = new Button(c->T("Download"), new LinearLayoutParams(1.0)); + buttonBar->Add(buttonDownload_)->OnClick.Add(std::bind(&PluginScreen::OnDownload, this, p::_1)); + buttonBar->Add(new Button(c->T("More Information"), new LinearLayoutParams(1.0)))->OnClick.Add(std::bind(&PluginScreen::OnInformation, this, p::_1)); +} + +void PluginScreen::update(InputState &input) { + downloader_.Update(); + + if (json_.get() && json_->Done()) { + std::string json; + json_->buffer().TakeAll(&json); + + JsonReader reader(json.data(), json.size()); + reader.parse(); + const json_value *root = reader.root(); +#if 0 +#if defined(_M_IX86) && defined(_WIN32) + at3plusdecoder_ = downloader_.StartDownload(root->getString("Win32"), "D:\at3.dll"); +#elif defined(_M_X64) && defined(_WIN32) + at3plusdecoder_ = downloader_.StartDownload(root->getString("Win64"), "D:\at364.dll"); +#elif defined(ARMEABI) + at3plusdecoder_ = downloader_.StartDownload(root->getString("armeabi"), "D:\at364.so"); +#elif defined(ARMEABI_V7A) + at3plusdecoder_ = downloader_.StartDownload(root->getString("armeabi-v7a"), "D:\at364.so"); +#else + // No decoder available for this arch + // #error Unable to identify architecture +#endif +#endif + + json_.reset(); + } + + if (at3plusdecoder_.get() && at3plusdecoder_->Done()) { + // Done! yay. + + } + + UIScreen::update(input); +} + +UI::EventReturn PluginScreen::OnDownload(UI::EventParams &e) { + buttonDownload_->SetEnabled(false); + return UI::EVENT_DONE; +} + + +UI::EventReturn PluginScreen::OnInformation(UI::EventParams &e) { + return UI::EVENT_DONE; +} \ No newline at end of file diff --git a/UI/PluginScreen.h b/UI/PluginScreen.h new file mode 100644 index 0000000000..9948f71663 --- /dev/null +++ b/UI/PluginScreen.h @@ -0,0 +1,58 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once +#include +#include +#include + +#include "ui/screen.h" +#include "ui/ui.h" +#include "ui/viewgroup.h" +#include "file/file_util.h" +#include "net/http_client.h" + + +class UIScreen : public Screen { +public: + UIScreen() : Screen(), root_(0) {} + virtual void update(InputState &input); + virtual void render(); + virtual void touch(const TouchInput &touch); + +protected: + UI::ViewGroup *root_; +}; + +class PluginScreen : public UIScreen { +public: + PluginScreen(); + + virtual void update(InputState &input); + +private: + UI::EventReturn OnDownload(UI::EventParams &e); + UI::EventReturn OnInformation(UI::EventParams &e); + + http::Downloader downloader_; + std::shared_ptr json_; + std::shared_ptr at3plusdecoder_; + + // UI widgets that need updating + UI::TextView *tvDescription_; + UI::Button *buttonDownload_; +}; \ No newline at end of file diff --git a/UI/UI.vcxproj b/UI/UI.vcxproj index f672b79b56..aad40f2b4b 100644 --- a/UI/UI.vcxproj +++ b/UI/UI.vcxproj @@ -22,9 +22,11 @@ + + @@ -32,8 +34,10 @@ + + diff --git a/UI/UI.vcxproj.filters b/UI/UI.vcxproj.filters index 58a6a583d1..3063e7e919 100644 --- a/UI/UI.vcxproj.filters +++ b/UI/UI.vcxproj.filters @@ -1,22 +1,47 @@  - - + + Screens + + + Screens + + + Screens + + + Screens + - - + + Screens + + + Screens + + + Screens + + + Screens + + + + + {faee5dce-633b-4ba6-b19d-ea70ee3c1c38} + \ No newline at end of file diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 5ca843cff2..ef5e7b7f63 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -300,32 +300,42 @@ namespace MainWindow case WM_ERASEBKGND: return DefWindowProc(hWnd, message, wParam, lParam); + // Poor man's touch - mouse input. We send the data both as an input_state pointer, + // and as asynchronous touch events for minimal latency. + case WM_LBUTTONDOWN: { lock_guard guard(input_state.lock); input_state.mouse_valid = true; input_state.pointer_down[0] = true; - input_state.pointer_x[0] = GET_X_LPARAM(lParam); - input_state.pointer_y[0] = GET_Y_LPARAM(lParam); - if (g_Config.iWindowZoom == 1) - { - input_state.pointer_x[0] *= 2; - input_state.pointer_y[0] *= 2; - } + int factor = g_Config.iWindowZoom == 1 ? 2 : 1; + input_state.pointer_x[0] = GET_X_LPARAM(lParam) * factor; + input_state.pointer_y[0] = GET_Y_LPARAM(lParam) * factor; + + TouchInput touch; + touch.id = 0; + touch.flags = TOUCH_DOWN; + touch.x = GET_X_LPARAM(lParam); + touch.y = GET_Y_LPARAM(lParam); + NativeTouch(touch); } break; case WM_MOUSEMOVE: { lock_guard guard(input_state.lock); - input_state.pointer_x[0] = GET_X_LPARAM(lParam); - input_state.pointer_y[0] = GET_Y_LPARAM(lParam); + int factor = g_Config.iWindowZoom == 1 ? 2 : 1; + input_state.pointer_x[0] = GET_X_LPARAM(lParam) * factor; + input_state.pointer_y[0] = GET_Y_LPARAM(lParam) * factor; - if (g_Config.iWindowZoom == 1) - { - input_state.pointer_x[0] *= 2; - input_state.pointer_y[0] *= 2; + if (wParam & MK_LBUTTON) { + TouchInput touch; + touch.id = 0; + touch.flags = TOUCH_MOVE; + touch.x = GET_X_LPARAM(lParam); + touch.y = GET_Y_LPARAM(lParam); + NativeTouch(touch); } } break; @@ -334,17 +344,22 @@ namespace MainWindow { lock_guard guard(input_state.lock); input_state.pointer_down[0] = false; - input_state.pointer_x[0] = GET_X_LPARAM(lParam); - input_state.pointer_y[0] = GET_Y_LPARAM(lParam); + int factor = g_Config.iWindowZoom == 1 ? 2 : 1; + input_state.pointer_x[0] = GET_X_LPARAM(lParam) * factor; + input_state.pointer_y[0] = GET_Y_LPARAM(lParam) * factor; - if (g_Config.iWindowZoom == 1) - { - input_state.pointer_x[0] *= 2; - input_state.pointer_y[0] *= 2; - } + TouchInput touch; + touch.id = 0; + touch.flags = TOUCH_UP; + touch.x = GET_X_LPARAM(lParam); + touch.y = GET_Y_LPARAM(lParam); + NativeTouch(touch); } break; + + // Actual touch! Unfinished + case WM_TOUCH: { // TODO: Enabling this section will probably break things on Windows XP.