Cavestory Mod API
WelcomeMode.cpp

An example of a GUI mode.

#include "WelcomeMode.h"
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//========> Error Code # 0001: Failure to allocate a surface. Might not be enough memory, or they might have opened a bunch of menus at the same time somehow.
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define DATA ((__WELCOME_MODE_DATA_STRUCT__*)(this->m_PrivData))
#define PDATA(x) ((__WELCOME_MODE_DATA_STRUCT__*)(x->m_PrivData))
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
using namespace GUI_SourceRects;
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define WELCOME_MODE_MARGIN 4
#define WELCOME_MODE_WIDTH 268
#define WELCOME_MODE_HEIGHT 217
#define WELCOME_MODE_HEADER "Cavestory... MULTIPLAYER?!"
#define WELCOME_MODE_BODY "Welcome to Cavestory Multiplayer! Excited to see you!"
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
struct __WELCOME_MODE_DATA_STRUCT__
{
GUI_RECT WM_Entire_Rect;
// Fonts
FontObject* WM_Font_Header;
FontObject* WM_Font_Body;
// Elements
CenteredTextInfo WM_Text_Header;
CenteredTextInfo WM_Text_Description;
ButtonInfo WM_Button_OK;
};
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int WelcomeMode::Init()
{
// Allocate our private data
m_PrivData = (void*)new __WELCOME_MODE_DATA_STRUCT__();
// Configure ourselves
m_ModeConfig.AllowKeyControl = true;
m_ModeConfig.AllowMouseControl = true;
m_ModeConfig.ProcessMouseOnMove = true;
// Load fonts
DATA->WM_Font_Header = FontManager::LoadFont("Courier New", 20, 16);
DATA->WM_Font_Body = FontManager::LoadFont("Arial", 18, 9);
// Configure our rect
DATA->WM_Entire_Rect = GUI_RECT(0, 0, WELCOME_MODE_WIDTH, WELCOME_MODE_HEIGHT);
// Configure the button
DATA->WM_Button_OK.setFont(BaseModeInstance::GetDefaultFont());
strcpy(DATA->WM_Button_OK.text, "OK!");
// Place the button in the bottom of the GUI, and stretch its width to be the entire width.
DATA->WM_Button_OK.rect = GUI_RECT(
WELCOME_MODE_MARGIN,
WELCOME_MODE_HEIGHT - (WELCOME_MODE_MARGIN + (DATA->WM_Button_OK.vmargin * 2) + TEXT_HEIGHT_2S(BaseModeInstance::GetDefaultFont(), DATA->WM_Button_OK.text)),
WELCOME_MODE_WIDTH - (WELCOME_MODE_MARGIN * 2),
(DATA->WM_Button_OK.vmargin * 2) + TEXT_HEIGHT_2S(BaseModeInstance::GetDefaultFont(), DATA->WM_Button_OK.text)
);
// Calculate the rect. ALWAYS call calculate on every GUI element before you start using them.
DATA->WM_Button_OK.calculate();
// Configure the centered header text
DATA->WM_Text_Header.setFont(DATA->WM_Font_Header);
DATA->WM_Text_Header.rect = GUI_RECT(WELCOME_MODE_MARGIN, WELCOME_MODE_MARGIN, WELCOME_MODE_WIDTH - (WELCOME_MODE_MARGIN * 2), TEXT_HEIGHT_2S(DATA->WM_Font_Header, WELCOME_MODE_HEADER));
DATA->WM_Text_Header.setText(WELCOME_MODE_HEADER);
DATA->WM_Text_Header.calculate();
// Configure the centered body text
DATA->WM_Text_Description.setFont(DATA->WM_Font_Body);
DATA->WM_Text_Description.rect = GUI_RECT(WELCOME_MODE_MARGIN, DATA->WM_Text_Header.rect.bottom() + WELCOME_MODE_MARGIN, WELCOME_MODE_WIDTH - (WELCOME_MODE_MARGIN * 2), TEXT_HEIGHT_2S(DATA->WM_Font_Body, WELCOME_MODE_BODY));
DATA->WM_Text_Description.setText(WELCOME_MODE_BODY);
DATA->WM_Text_Description.calculate();
// Allocate the window surface
if (AllocSurface(-1, WELCOME_MODE_WIDTH, WELCOME_MODE_HEIGHT) == -1)
{
#ifdef _DEBUG
CSM_Log(__FUNCTION__ "() - Failed to allocate a surface for the escape menu.");
#endif
return 1;
}
// Show the cursor
ShowCursor();
// Done!
return 0;
}
int WelcomeMode::Free()
{
// Free fonts
FontManager::UnloadFont(DATA->WM_Font_Body);
FontManager::UnloadFont(DATA->WM_Font_Header);
// Delete our private data
delete m_PrivData;
// Free surfaces
FreeAllSurfaces();
// Hide our cursor
HideCursor();
// Done!
return 0;
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void WelcomeMode::ProcessLogic()
{
// If we're NOT the currently focused mode, then we shouldn't be calling the functions below,
// as the ACTUAL focused mode will probably be calling them, too.
if (!IsFocusedMode())
return;
// Process networking
CaveNet::ProcessNet();
// Process text scripts (if we're connected -- If we're in singleplayer, then an open GUI should freeze everything)
if (CaveNet::Client::IsConnected())
{
// Process the text script
int iRetCode = TextScriptProc();
if (iRetCode == 0)
{
// Close the game
m_RetValue = 0;
m_End = true;
return;
}
if (iRetCode == 2)
{
// Return to the title screen
m_RetValue = 1;
m_End = true;
return;
}
}
}
void WelcomeMode::ProcessMouse(GUI_POINT mouse_point)
{
mouse_point = GUI_POINT((Mouse::GetMousePosition().x / magnification) - GetCenteredX(0), (Mouse::GetMousePosition().y / magnification) - GetCenteredY(0));
int prt = DATA->WM_Button_OK.process(mouse_point);
// Process different types of return types
if (prt & GuiBase::ProcessReturnType::PRT_DIRTY)
{
// The button's graphics are dirty and needs to be updated!
SetDirty();
}
if (prt & GuiBase::ProcessReturnType::PRT_SELECTED)
{
// Button was pressed!
DATA->NL_SelectedButton = 0;
HandleSelection();
}
// The button wants us to not process any other mouse stuff!
if (prt & GuiBase::ProcessReturnType::PRT_IGNORE_MOUSE)
{
return;
}
}
void WelcomeMode::ProcessKeys()
{
// If the 'OK' button, 'ESCAPE' or the 'Cancel' button are pressed, then stop this mode.
if (m_ModeInput.KeyTrg & (gKeyOk | KEY_ESCAPE | gKeyCancel))
{
// Remove keypress afterwards.
//
// We do this because the key will probably mess stuff up after this GUI closes (since keypresses are kept after GUI closes)
m_ModeInput.KeyTrg &= ~(gKeyOk | KEY_ESCAPE | gKeyCancel);
m_ModeInput.Key &= ~(gKeyOk | KEY_ESCAPE | gKeyCancel);
gKeyTrg &= ~(gKeyOk | KEY_ESCAPE | gKeyCancel);
gKey &= ~(gKeyOk | KEY_ESCAPE | gKeyCancel);
// Stop the mode on the next frame
m_End = true;
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void WelcomeMode::PreRender()
{
// Here, we will update all of our allocated surfaces.
// This function is only called the frame after we call SetDirty().
// Basically, we are just updating all of our surfaces because we have new data to display.
// Select the main surface, so we can draw on it
//
// We're using 0 here because BaseModeInstance uses a local surface lookup table, and we want to use the first allocated surface.
//
// This is a wrapper for CacheSurface::SetSurfaceID for QOL purposes.
SelectSurface(0);
// Clear the surface so nothing is left over from the last frame
// Using NULL here to clear the entire surface
NULL,
// No alpha color
0x00000000
);
// Draw the UI background
// Draw the bitmap box to the entire surface
&DATA->WM_Entire_Rect,
// Use a preset rect from GUI_SourceRects
GUI_SourceRects::rc_FRAME_EscapeBox,
// The rect above uses both dynamic width AND dynamic height, so specify it as 'BMPBOX_TYPE_BOTH'.
CacheSurface::BitmapBoxType::BMPBOX_TYPE_BOTH,
// Get the source rect from GUI.png
);
// Render GUI elements
//
// Calling 'render' on GuiBase classes always renders them with CacheSurface, so whatever
// surface passed to 'SelectSurface()' ( which is a wrapper for CacheSurface::SetSurfaceID )
// will be the one it's drawn on.
DATA->WM_Text_Header.render();
DATA->WM_Text_Description.render();
DATA->WM_Button_OK.render();
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void WelcomeMode::Draw()
{
// Here, we will actually draw the mode to the renderer.
// Just draw the actual background, and then draw all the surfaces you want to draw..
// Draw the actual game elements
if (CaveNet::Client::IsConnected())
// We're connected to a server, so we want to be able to see the game progressing behind the mode.
// However, since we're in a GUI, we shouldn't be able to control our character at the same time, so pass 'false' as the first arg.
DrawGame(false);
else
// We're in singleplayer, so just draw the screengrab.
DrawScreenGrab();
// Draw the text script
// Draw the main surface
//
// We can use MODE_DRAW_CENTERED_SURFACE in place of the x & y parameters for this function to center the surface in the middle of the screen.
// It's not exclusive to both, either; You can have 'x' set to 'MODE_DRAW_CENTERED_SURFACE' and 'y' set to an actual value.
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define MODE_DRAW_CENTERED_SURFACE
The center flag for DrawSurface(). Do not change this.
Definition: CSMAPI_BaseModeInstance.h:91
@ SURFACE_ID_GUI
GUI.
Definition: CSMAPI_enums.h:812
@ KEY_ESCAPE
Escape button.
Definition: CSMAPI_enums.h:201
static FontObject * GetDefaultFont(unsigned int iMagnification=0)
Get the default font that all GUIs should use.
Show a clickable button.
Definition: CSMAPI_types.h:4595
Draw centered text.
Definition: CSMAPI_types.h:2961
static void UnloadFont(FontObject *fo)
Unload a font object.
static FontObject * LoadFont(const char *font_name, int font_width, int font_height, bool bDoNotUse=false, VideoTexture *pTexture=NULL, FontManager **resultingManager=NULL, unsigned int iMagnification=0xFFFFFFFF)
Load a font by name & size.
#define TEXT_HEIGHT_2S(font_object, string)
Get the rendered height of a string, automatically divide it by the current global magnification leve...
Definition: CSMAPI_drawing.h:86
CAVESTORY_MOD_API void PutTextScript()
Put text script on the screen.
CAVESTORY_MOD_API int TextScriptProc()
Process text scripts.
void CSM_Log(const char *pFormat,...)
Log a message to the console.
Definition: CavestoryModAPI.cpp:50
static void DrawBitmapBox(GUI_RECT *out_rect, GUI_RECT *bmp_rects, BitmapBoxType type, Surface_Ids bmp_id)
Draw a bitmap box.
static void DrawFilledRect(GUI_RECT *r, unsigned long color, bool bAbsolutePos=false)
Fill a given rect.
Manages points.
Definition: CSMAPI_types.h:546
Definition: CSMAPI_types.h:842