mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-13 17:47:12 -04:00
Merge pull request #1136 from camthehaxman/3ds-dualscreen
Dual screen mode for 3DS
This commit is contained in:
commit
164958df36
@ -286,6 +286,7 @@ typedef cc_uint8 cc_bool;
|
||||
#define CC_BUILD_BEARSSL
|
||||
#define CC_BUILD_LOWMEM
|
||||
#define CC_BUILD_CONSOLE
|
||||
#define CC_BUILD_TOUCH
|
||||
#undef CC_BUILD_FREETYPE
|
||||
#elif defined GEKKO
|
||||
#define CC_BUILD_GCWII
|
||||
|
@ -238,6 +238,9 @@ void Gfx_OnWindowResize(void);
|
||||
/* NOTE: Each line is separated by \n */
|
||||
void Gfx_GetApiInfo(cc_string* info);
|
||||
|
||||
void Gfx_3DS_DrawToTopScreen(void);
|
||||
void Gfx_3DS_DrawToBottomScreen(void);
|
||||
|
||||
/* Raises ContextLost event and updates state for lost contexts */
|
||||
void Gfx_LoseContext(const char* reason);
|
||||
/* Raises ContextRecreated event and restores internal state */
|
||||
|
@ -106,7 +106,8 @@ static void SwitchProgram(void) {
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------General---------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static C3D_RenderTarget* target;
|
||||
static C3D_RenderTarget* topTarget;
|
||||
static C3D_RenderTarget* bottomTarget;
|
||||
|
||||
static void AllocShaders(void) {
|
||||
Shader_Alloc(&shaders[0], coloured_shbin, coloured_shbin_size);
|
||||
@ -129,9 +130,16 @@ static void SetDefaultState(void) {
|
||||
|
||||
static void InitCitro3D(void) {
|
||||
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
||||
target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||
C3D_RenderTargetSetOutput(target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
|
||||
|
||||
topTarget = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||
C3D_RenderTargetSetOutput(topTarget, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
|
||||
|
||||
// Even though the bottom screen is 320 pixels wide, we use 400 here so that the same ortho matrix
|
||||
// can be used for both screens. The output is clipped to the actual screen width, anyway.
|
||||
bottomTarget = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
||||
C3D_RenderTargetSetOutput(bottomTarget, GFX_BOTTOM, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
|
||||
|
||||
gfxSetDoubleBuffering(GFX_TOP, true);
|
||||
SetDefaultState();
|
||||
AllocShaders();
|
||||
}
|
||||
@ -173,6 +181,14 @@ void Gfx_FreeState(void) {
|
||||
Gfx_DeleteTexture(&white_square);
|
||||
}
|
||||
|
||||
void Gfx_3DS_DrawToTopScreen(void) {
|
||||
C3D_FrameDrawOn(topTarget);
|
||||
}
|
||||
|
||||
void Gfx_3DS_DrawToBottomScreen(void) {
|
||||
C3D_FrameDrawOn(bottomTarget);
|
||||
}
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Textures--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
@ -355,11 +371,12 @@ void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
|
||||
void Gfx_BeginFrame(void) {
|
||||
int flags = gfx_vsync ? C3D_FRAME_SYNCDRAW : 0;
|
||||
C3D_FrameBegin(flags);
|
||||
C3D_FrameDrawOn(topTarget);
|
||||
}
|
||||
|
||||
void Gfx_Clear(void) {
|
||||
C3D_RenderTargetClear(target, C3D_CLEAR_ALL, clear_color, 0);
|
||||
C3D_FrameDrawOn(target);
|
||||
C3D_RenderTargetClear(topTarget, C3D_CLEAR_ALL, clear_color, 0);
|
||||
C3D_RenderTargetClear(bottomTarget, C3D_CLEAR_ALL, 0, 0);
|
||||
}
|
||||
|
||||
void Gfx_EndFrame(void) {
|
||||
@ -780,4 +797,4 @@ void Gfx_Draw2DTexture(const struct Texture* tex, PackedCol color) {
|
||||
C3D_ImmSendAttrib(v[0].U, v[0].V, 0.0f, 0.0f);
|
||||
C3D_ImmDrawEnd();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
52
src/Gui.c
52
src/Gui.c
@ -21,7 +21,9 @@
|
||||
struct _GuiData Gui;
|
||||
struct Screen* Gui_Screens[GUI_MAX_SCREENS];
|
||||
static cc_uint8 priorities[GUI_MAX_SCREENS];
|
||||
|
||||
#ifdef __3DS__
|
||||
static struct Texture touchBgTex;
|
||||
#endif
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------------Gui------------------------------------------------------------*
|
||||
@ -32,10 +34,14 @@ static CC_NOINLINE int GetWindowScale(void) {
|
||||
|
||||
/* Use larger UI scaling on mobile */
|
||||
/* TODO move this DPI scaling elsewhere.,. */
|
||||
#ifndef __3DS__
|
||||
if (!Input_TouchMode) {
|
||||
#endif
|
||||
widthScale /= DisplayInfo.ScaleX;
|
||||
heightScale /= DisplayInfo.ScaleY;
|
||||
#ifndef __3DS__
|
||||
}
|
||||
#endif
|
||||
return 1 + (int)(min(widthScale, heightScale));
|
||||
}
|
||||
|
||||
@ -137,12 +143,16 @@ void Gui_LayoutAll(void) {
|
||||
struct Screen* s;
|
||||
int i;
|
||||
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN);
|
||||
|
||||
for (i = 0; i < Gui.ScreensCount; i++)
|
||||
{
|
||||
s = Gui_Screens[i];
|
||||
s->VTABLE->Layout(s);
|
||||
s->dirty = true;
|
||||
}
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
}
|
||||
|
||||
void Gui_RefreshAll(void) {
|
||||
@ -152,10 +162,14 @@ void Gui_RefreshAll(void) {
|
||||
}
|
||||
|
||||
void Gui_Refresh(struct Screen* s) {
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN);
|
||||
|
||||
s->VTABLE->ContextLost(s);
|
||||
s->VTABLE->ContextRecreated(s);
|
||||
s->VTABLE->Layout(s);
|
||||
s->dirty = true;
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
}
|
||||
|
||||
static void Gui_AddCore(struct Screen* s, int priority) {
|
||||
@ -179,6 +193,8 @@ static void Gui_AddCore(struct Screen* s, int priority) {
|
||||
priorities[i] = priority;
|
||||
Gui.ScreensCount++;
|
||||
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN);
|
||||
|
||||
s->dirty = true;
|
||||
s->VTABLE->Init(s);
|
||||
s->VTABLE->ContextRecreated(s);
|
||||
@ -189,6 +205,8 @@ static void Gui_AddCore(struct Screen* s, int priority) {
|
||||
{
|
||||
s->VTABLE->HandlesPointerMove(s, i, Pointers[i].x, Pointers[i].y);
|
||||
}
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
}
|
||||
|
||||
/* Returns index of the given screen in the screens list, -1 if not */
|
||||
@ -283,6 +301,12 @@ void Gui_RenderGui(double delta) {
|
||||
struct Screen* s;
|
||||
int i;
|
||||
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN);
|
||||
|
||||
#ifdef __3DS__
|
||||
Texture_Render(&touchBgTex);
|
||||
#endif
|
||||
|
||||
/* Draw back to front so highest priority screen is on top */
|
||||
for (i = Gui.ScreensCount - 1; i >= 0; i--)
|
||||
{
|
||||
@ -292,6 +316,8 @@ void Gui_RenderGui(double delta) {
|
||||
if (s->dirty) { s->VTABLE->BuildMesh(s); s->dirty = false; }
|
||||
s->VTABLE->Render(s, delta);
|
||||
}
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
}
|
||||
|
||||
|
||||
@ -449,22 +475,26 @@ int Screen_DoPointerDown(void* screen, int id, int x, int y) {
|
||||
struct Screen* s = (struct Screen*)screen;
|
||||
struct Widget** widgets = s->widgets;
|
||||
int i, count = s->numWidgets;
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN);
|
||||
|
||||
/* iterate backwards (because last elements rendered are shown over others) */
|
||||
for (i = count - 1; i >= 0; i--)
|
||||
{
|
||||
struct Widget* w = widgets[i];
|
||||
if (!w || !Widget_Contains(w, x, y)) continue;
|
||||
if (w->flags & WIDGET_FLAG_DISABLED) return i;
|
||||
if (w->flags & WIDGET_FLAG_DISABLED) break;
|
||||
|
||||
if (w->MenuClick) {
|
||||
w->MenuClick(s, w);
|
||||
} else {
|
||||
Elem_HandlesPointerDown(w, id, x, y);
|
||||
}
|
||||
return i;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int Screen_Index(void* screen, void* widget) {
|
||||
@ -568,7 +598,6 @@ static void TouchPngProcess(struct Stream* stream, const cc_string* name) {
|
||||
}
|
||||
static struct TextureEntry touch_entry = { "touch.png", TouchPngProcess };
|
||||
|
||||
|
||||
static void OnFontChanged(void* obj) { Gui_RefreshAll(); }
|
||||
|
||||
static void OnKeyPress(void* obj, int cp) {
|
||||
@ -612,6 +641,19 @@ static void OnInit(void) {
|
||||
TextureEntry_Register(&icons_entry);
|
||||
TextureEntry_Register(&touch_entry);
|
||||
|
||||
#ifdef __3DS__
|
||||
struct Context2D ctx;
|
||||
Context2D_Alloc(&ctx, 32, 32);
|
||||
Gradient_Noise(&ctx, BitmapColor_RGB(0x40, 0x30, 0x20), 6, 0, 0, ctx.width, ctx.height);
|
||||
Context2D_MakeTexture(&touchBgTex, &ctx);
|
||||
Context2D_Free(&ctx);
|
||||
// Tile the texture to fill the entire screen
|
||||
int tilesX = (320 + ctx.width - 1) / ctx.width;
|
||||
int tilesY = (240 + ctx.height - 1) / ctx.height;
|
||||
touchBgTex.Width *= tilesX; touchBgTex.Height *= tilesY;
|
||||
touchBgTex.uv.U2 *= tilesX; touchBgTex.uv.V2 *= tilesY;
|
||||
#endif
|
||||
|
||||
Event_Register_(&ChatEvents.FontChanged, NULL, OnFontChanged);
|
||||
Event_Register_(&GfxEvents.ContextLost, NULL, OnContextLost);
|
||||
Event_Register_(&GfxEvents.ContextRecreated, NULL, OnContextRecreated);
|
||||
|
@ -114,6 +114,7 @@ cc_bool Launcher_StartGame(const cc_string* user, const cc_string* mppass, const
|
||||
if (res) { Logger_SysWarn(res, "starting game"); return false; }
|
||||
|
||||
Launcher_ShouldExit = Platform_SingleProcess || Options_GetBool(LOPT_AUTO_CLOSE, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -235,6 +236,8 @@ void Launcher_Run(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN);
|
||||
|
||||
Drawer2D_Component.Init();
|
||||
SystemFonts_Component.Init();
|
||||
Drawer2D.BitmappedText = false;
|
||||
@ -295,6 +298,8 @@ void Launcher_Run(void) {
|
||||
|
||||
if (Window_Main.Exists) Window_RequestClose();
|
||||
#endif
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
}
|
||||
|
||||
|
||||
@ -527,17 +532,43 @@ void Launcher_DrawTitle(struct FontDesc* font, const char* text, struct Context2
|
||||
cc_string title = String_FromReadonly(text);
|
||||
struct DrawTextArgs args;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
/* Skip dragging logo when very small window to save space */
|
||||
if (Window_Main.Height < 240) return;
|
||||
|
||||
#ifdef __3DS__
|
||||
/* Put title on top screen */
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN);
|
||||
struct Bitmap bmp;
|
||||
struct Context2D topCtx;
|
||||
|
||||
ctx = &topCtx;
|
||||
bmp.width = max(Window_Main.Width, 1);
|
||||
bmp.height = max(Window_Main.Height, 1);
|
||||
Window_AllocFramebuffer(&bmp);
|
||||
Context2D_Wrap(ctx, &bmp);
|
||||
Launcher_DrawBackgroundAll(ctx);
|
||||
#endif
|
||||
|
||||
DrawTextArgs_Make(&args, &title, font, false);
|
||||
x = ctx->width / 2 - Drawer2D_TextWidth(&args) / 2;
|
||||
y = 0;
|
||||
|
||||
#ifdef __3DS__
|
||||
// vertically center the title
|
||||
y = ctx->height / 2 - Drawer2D_TextHeight(&args) / 2;
|
||||
#endif
|
||||
|
||||
Drawer2D.Colors['f'] = BITMAPCOLOR_BLACK;
|
||||
Context2D_DrawText(ctx, &args, x + Display_ScaleX(4), Display_ScaleY(4));
|
||||
Context2D_DrawText(ctx, &args, x + Display_ScaleX(4), y + Display_ScaleY(4));
|
||||
Drawer2D.Colors['f'] = BITMAPCOLOR_WHITE;
|
||||
Context2D_DrawText(ctx, &args, x, 0);
|
||||
Context2D_DrawText(ctx, &args, x, y);
|
||||
|
||||
#ifdef __3DS__
|
||||
Window_DrawFramebuffer((Rect2D){ 0, 0, bmp.width, bmp.height });
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Launcher_MakeTitleFont(struct FontDesc* font) {
|
||||
|
@ -56,6 +56,10 @@ void Platform_Log(const char* msg, int len) {
|
||||
|
||||
write(STDOUT_FILENO, msg, len);
|
||||
write(STDOUT_FILENO, "\n", 1);
|
||||
|
||||
// output to debug service (visible in Citra with log level set to "*:Debug", or on console via remote gdb)
|
||||
svcOutputDebugString(msg, len);
|
||||
svcOutputDebugString("\n", 1);
|
||||
}
|
||||
|
||||
#define UnixTime_TotalMS(time) ((cc_uint64)time.tv_sec * 1000 + UNIX_EPOCH + (time.tv_usec / 1000))
|
||||
|
@ -202,9 +202,11 @@ static void HUDScreen_ContextRecreated(void* screen) {
|
||||
}
|
||||
|
||||
static int HUDScreen_LayoutHotbar(void) {
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN);
|
||||
struct HUDScreen* s = &HUDScreen_Instance;
|
||||
s->hotbar.scale = Gui_GetHotbarScale();
|
||||
Widget_Layout(&s->hotbar);
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
return s->hotbar.height;
|
||||
}
|
||||
|
||||
@ -337,6 +339,7 @@ static void HUDScreen_BuildCrosshairsMesh(struct VertexTextured** ptr) {
|
||||
/* Only top quarter of icons.png is used */
|
||||
static struct Texture tex = { 0, Tex_Rect(0,0,0,0), Tex_UV(0.0f,0.0f, 15/256.0f,15/64.0f) };
|
||||
int extent;
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN);
|
||||
|
||||
extent = (int)(CH_EXTENT * Gui_Scale(Window_Main.Height / 480.0f));
|
||||
tex.x = (Window_Main.Width / 2) - extent;
|
||||
@ -345,6 +348,8 @@ static void HUDScreen_BuildCrosshairsMesh(struct VertexTextured** ptr) {
|
||||
tex.Width = extent * 2;
|
||||
tex.Height = extent * 2;
|
||||
Gfx_Make2DQuad(&tex, PACKEDCOL_WHITE, ptr);
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
}
|
||||
|
||||
static void HUDScreen_BuildMesh(void* screen) {
|
||||
@ -369,6 +374,8 @@ static void HUDScreen_Render(void* screen, double delta) {
|
||||
struct HUDScreen* s = (struct HUDScreen*)screen;
|
||||
if (Game_HideGui) return;
|
||||
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN);
|
||||
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
|
||||
Gfx_BindDynamicVb(s->vb);
|
||||
if (Gui.ShowFPS) Widget_Render2(&s->line1, 4);
|
||||
@ -382,15 +389,18 @@ static void HUDScreen_Render(void* screen, double delta) {
|
||||
/* TODO swap these two lines back */
|
||||
}
|
||||
|
||||
if (Gui_GetBlocksWorld()) return;
|
||||
Gfx_BindDynamicVb(s->vb);
|
||||
Widget_Render2(&s->hotbar, 12);
|
||||
if (!Gui_GetBlocksWorld()) {
|
||||
Gfx_BindDynamicVb(s->vb);
|
||||
Widget_Render2(&s->hotbar, 12);
|
||||
|
||||
if (Gui.IconsTex && !tablist_active) {
|
||||
Gfx_BindTexture(Gui.IconsTex);
|
||||
Gfx_BindDynamicVb(s->vb); /* Have to rebind for mobile right now... */
|
||||
Gfx_DrawVb_IndexedTris(4);
|
||||
if (Gui.IconsTex && !tablist_active) {
|
||||
Gfx_BindTexture(Gui.IconsTex);
|
||||
Gfx_BindDynamicVb(s->vb); /* Have to rebind for mobile right now... */
|
||||
Gfx_DrawVb_IndexedTris(4);
|
||||
}
|
||||
}
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
}
|
||||
|
||||
static const struct ScreenVTABLE HUDScreen_VTABLE = {
|
||||
@ -494,6 +504,8 @@ static void TabListOverlay_Layout(void* screen) {
|
||||
int i, x, y, width = 0, height = 0;
|
||||
int columns = Math_CeilDiv(s->usedCount, LIST_NAMES_PER_COLUMN);
|
||||
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN);
|
||||
|
||||
for (i = 0; i < columns; i++)
|
||||
{
|
||||
width += TabListOverlay_GetColumnWidth(s, i);
|
||||
@ -530,6 +542,8 @@ static void TabListOverlay_Layout(void* screen) {
|
||||
s->title.horAnchor = ANCHOR_CENTRE;
|
||||
s->title.yOffset = s->y + paddingY / 2;
|
||||
Widget_Layout(&s->title);
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
}
|
||||
|
||||
static void TabListOverlay_AddName(struct TabListOverlay* s, EntityID id, int index) {
|
||||
@ -804,6 +818,9 @@ static void TabListOverlay_Render(void* screen, double delta) {
|
||||
PackedCol bottomCol = PackedCol_Make(50, 50, 50, 205);
|
||||
|
||||
if (Game_HideGui || !IsOnlyChatActive()) return;
|
||||
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN);
|
||||
|
||||
Gfx_Draw2DGradient(s->x, s->y, s->width, s->height, topCol, bottomCol);
|
||||
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
|
||||
@ -818,6 +835,8 @@ static void TabListOverlay_Render(void* screen, double delta) {
|
||||
Gfx_DrawVb_IndexedTris_Range(4, offset);
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
}
|
||||
|
||||
static void TabListOverlay_Free(void* screen) {
|
||||
@ -1152,9 +1171,11 @@ static void ChatScreen_DrawChat(struct ChatScreen* s, double delta) {
|
||||
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
if (!Input_TouchMode) return;
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN);
|
||||
Elem_Render(&s->more, delta);
|
||||
Elem_Render(&s->send, delta);
|
||||
Elem_Render(&s->cancel, delta);
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -1218,6 +1239,8 @@ static void ChatScreen_BuildMesh(void* screen) {
|
||||
}
|
||||
|
||||
static void ChatScreen_Layout(void* screen) {
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN);
|
||||
|
||||
struct ChatScreen* s = (struct ChatScreen*)screen;
|
||||
if (ChatScreen_ChatUpdateFont(s)) ChatScreen_Redraw(s);
|
||||
|
||||
@ -1248,6 +1271,8 @@ static void ChatScreen_Layout(void* screen) {
|
||||
s->smallAnnouncement.yOffset = Window_Main.Height / 20;
|
||||
Widget_Layout(&s->smallAnnouncement);
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
if (Window_Main.SoftKeyboard == SOFT_KEYBOARD_SHIFT) {
|
||||
Widget_SetLocation(&s->send, ANCHOR_MAX, ANCHOR_MAX, 10, 60);
|
||||
@ -1456,17 +1481,19 @@ static void ChatScreen_Init(void* screen) {
|
||||
|
||||
static void ChatScreen_Render(void* screen, double delta) {
|
||||
struct ChatScreen* s = (struct ChatScreen*)screen;
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(TOP_SCREEN);
|
||||
|
||||
if (Game_HideGui && s->grabsInput) {
|
||||
Elem_Render(&s->input.base, delta);
|
||||
}
|
||||
if (Game_HideGui) return;
|
||||
if (!Game_HideGui) {
|
||||
if (s->grabsInput && !Gui.ClassicChat) {
|
||||
ChatScreen_DrawChatBackground(s);
|
||||
}
|
||||
|
||||
if (s->grabsInput && !Gui.ClassicChat) {
|
||||
ChatScreen_DrawChatBackground(s);
|
||||
ChatScreen_DrawChat(s, delta);
|
||||
}
|
||||
|
||||
ChatScreen_DrawChat(s, delta);
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
}
|
||||
|
||||
static void ChatScreen_Free(void* screen) {
|
||||
|
@ -448,16 +448,21 @@ static void HotbarWidget_RenderEntries(struct HotbarWidget* w, int offset) {
|
||||
}
|
||||
|
||||
static int HotbarWidget_Render2(void* widget, int offset) {
|
||||
enum Screen3DS scr = Window_3DS_SetRenderScreen(BOTTOM_SCREEN);
|
||||
|
||||
struct HotbarWidget* w = (struct HotbarWidget*)widget;
|
||||
HotbarWidget_RenderOutline(w, offset );
|
||||
HotbarWidget_RenderEntries(w, offset + 8);
|
||||
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
if (!Input_TouchMode) return HOTBAR_MAX_VERTICES;
|
||||
w->ellipsisTex.x = HotbarWidget_TileX(w, HOTBAR_MAX_INDEX) - w->ellipsisTex.Width / 2;
|
||||
w->ellipsisTex.y = w->y + (w->height / 2) - w->ellipsisTex.Height / 2;
|
||||
Texture_Render(&w->ellipsisTex);
|
||||
if (Input_TouchMode) {
|
||||
w->ellipsisTex.x = HotbarWidget_TileX(w, HOTBAR_MAX_INDEX) - w->ellipsisTex.Width / 2;
|
||||
w->ellipsisTex.y = w->y + (w->height / 2) - w->ellipsisTex.Height / 2;
|
||||
Texture_Render(&w->ellipsisTex);
|
||||
}
|
||||
#endif
|
||||
|
||||
Window_3DS_SetRenderScreen(scr);
|
||||
return HOTBAR_MAX_VERTICES;
|
||||
}
|
||||
|
||||
|
10
src/Window.h
10
src/Window.h
@ -233,4 +233,14 @@ void GLContext_SetFpsLimit(cc_bool vsync, float minFrameMs);
|
||||
/* Gets OpenGL context specific graphics information. */
|
||||
void GLContext_GetApiInfo(cc_string* info);
|
||||
#endif
|
||||
|
||||
enum Screen3DS { TOP_SCREEN, BOTTOM_SCREEN };
|
||||
#ifdef __3DS__
|
||||
/* Selects which screen on the 3DS to render to. Returns the previous screen */
|
||||
enum Screen3DS Window_3DS_SetRenderScreen(enum Screen3DS screen);
|
||||
#else
|
||||
static inline
|
||||
enum Screen3DS Window_3DS_SetRenderScreen(enum Screen3DS screen) { return TOP_SCREEN; }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -12,9 +12,9 @@
|
||||
#include "ExtMath.h"
|
||||
#include <3ds.h>
|
||||
|
||||
static int touchActive, touchBegX, touchBegY;
|
||||
static cc_bool launcherMode;
|
||||
static Result irrst_result;
|
||||
static enum Screen3DS renderScreen = TOP_SCREEN;
|
||||
|
||||
struct _DisplayData DisplayInfo;
|
||||
struct _WindowData WindowInfo;
|
||||
@ -32,7 +32,7 @@ void Window_Init(void) {
|
||||
gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, false);
|
||||
|
||||
//gfxInit(GSP_RGBA8_OES,GSP_RGBA8_OES,false);
|
||||
consoleInit(GFX_BOTTOM, NULL);
|
||||
//consoleInit(GFX_BOTTOM, NULL);
|
||||
|
||||
u16 width, height;
|
||||
gfxGetFramebuffer(GFX_TOP, GFX_LEFT, &width, &height);
|
||||
@ -48,6 +48,7 @@ void Window_Init(void) {
|
||||
Window_Main.Focused = true;
|
||||
Window_Main.Exists = true;
|
||||
|
||||
Input_SetTouchMode(true);
|
||||
Input.Sources = INPUT_SOURCE_GAMEPAD;
|
||||
irrst_result = irrstInit();
|
||||
|
||||
@ -58,6 +59,21 @@ void Window_Init(void) {
|
||||
|
||||
void Window_Free(void) { irrstExit(); }
|
||||
|
||||
enum Screen3DS Window_3DS_SetRenderScreen(enum Screen3DS screen) {
|
||||
enum Screen3DS prev = renderScreen;
|
||||
if (screen != prev)
|
||||
{
|
||||
renderScreen = screen;
|
||||
DisplayInfo.Width = (screen == TOP_SCREEN) ? 400 : 320;
|
||||
WindowInfo.Width = DisplayInfo.Width;
|
||||
if (screen == TOP_SCREEN)
|
||||
Gfx_3DS_DrawToTopScreen();
|
||||
else
|
||||
Gfx_3DS_DrawToBottomScreen();
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
void Window_Create2D(int width, int height) { launcherMode = true; }
|
||||
void Window_Create3D(int width, int height) { launcherMode = false; }
|
||||
|
||||
@ -112,27 +128,27 @@ static void ProcessJoystickInput(circlePosition* pos, double delta) {
|
||||
}
|
||||
|
||||
static void ProcessTouchInput(int mods) {
|
||||
static int currX, currY; // current touch position
|
||||
touchPosition touch;
|
||||
hidTouchRead(&touch);
|
||||
touchActive = mods & KEY_TOUCH;
|
||||
|
||||
if (touchActive) {
|
||||
// rescale X from [0, bottom_FB_width) to [0, top_FB_width)
|
||||
int x = touch.px * Window_Main.Width / GSP_SCREEN_HEIGHT_BOTTOM;
|
||||
int y = touch.py;
|
||||
Pointer_SetPosition(0, x, y);
|
||||
if (hidKeysDown() & KEY_TOUCH) { // stylus went down
|
||||
currX = touch.px;
|
||||
currY = touch.py;
|
||||
Input_AddTouch(0, currX, currY);
|
||||
}
|
||||
// Set starting position for camera movement
|
||||
if (hidKeysDown() & KEY_TOUCH) {
|
||||
touchBegX = touch.px;
|
||||
touchBegY = touch.py;
|
||||
else if (mods & KEY_TOUCH) { // stylus is down
|
||||
currX = touch.px;
|
||||
currY = touch.py;
|
||||
Input_UpdateTouch(0, currX, currY);
|
||||
}
|
||||
else if (hidKeysUp() & KEY_TOUCH) { // stylus was lifted
|
||||
Input_RemoveTouch(0, currX, currY);
|
||||
}
|
||||
}
|
||||
|
||||
void Window_ProcessEvents(double delta) {
|
||||
hidScanInput();
|
||||
/* TODO implement */
|
||||
|
||||
|
||||
if (!aptMainLoop()) {
|
||||
Window_Main.Exists = false;
|
||||
Window_RequestClose();
|
||||
@ -141,8 +157,7 @@ void Window_ProcessEvents(double delta) {
|
||||
|
||||
u32 mods = hidKeysDown() | hidKeysHeld();
|
||||
HandleButtons(mods);
|
||||
|
||||
Input_SetNonRepeatable(CCMOUSE_L, mods & KEY_TOUCH);
|
||||
|
||||
ProcessTouchInput(mods);
|
||||
|
||||
if (Input.RawMode) {
|
||||
@ -163,33 +178,29 @@ void Cursor_SetPosition(int x, int y) { } // Makes no sense for 3DS
|
||||
void Window_EnableRawMouse(void) { Input.RawMode = true; }
|
||||
void Window_DisableRawMouse(void) { Input.RawMode = false; }
|
||||
|
||||
void Window_UpdateRawMouse(void) {
|
||||
if (!touchActive) return;
|
||||
|
||||
touchPosition touch;
|
||||
hidTouchRead(&touch);
|
||||
|
||||
Event_RaiseRawMove(&PointerEvents.RawMoved,
|
||||
touch.px - touchBegX, touch.py - touchBegY);
|
||||
touchBegX = touch.px;
|
||||
touchBegY = touch.py;
|
||||
}
|
||||
|
||||
void Window_UpdateRawMouse(void) { }
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Framebuffer--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static struct Bitmap fb_bmp;
|
||||
static struct Bitmap top_fb_bmp;
|
||||
static struct Bitmap bottom_fb_bmp;
|
||||
void Window_AllocFramebuffer(struct Bitmap* bmp) {
|
||||
bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels");
|
||||
fb_bmp = *bmp;
|
||||
if (renderScreen == TOP_SCREEN) {
|
||||
top_fb_bmp = *bmp;
|
||||
}
|
||||
else {
|
||||
bottom_fb_bmp = *bmp;
|
||||
}
|
||||
}
|
||||
|
||||
void Window_DrawFramebuffer(Rect2D r) {
|
||||
u16 width, height;
|
||||
gfxSetDoubleBuffering(GFX_TOP, false);
|
||||
u8* fb = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, &width, &height);
|
||||
|
||||
gfxScreen_t screen = (renderScreen == TOP_SCREEN) ? GFX_TOP : GFX_BOTTOM;
|
||||
gfxSetDoubleBuffering(screen, false);
|
||||
u8* fb = gfxGetFramebuffer(screen, GFX_LEFT, &width, &height);
|
||||
struct Bitmap *bmp = (renderScreen == TOP_SCREEN) ? &top_fb_bmp : &bottom_fb_bmp;
|
||||
// SRC y = 0 to 240
|
||||
// SRC x = 0 to 400
|
||||
// DST X = 0 to 240
|
||||
@ -198,7 +209,7 @@ void Window_DrawFramebuffer(Rect2D r) {
|
||||
for (int y = r.y; y < r.y + r.Height; y++)
|
||||
for (int x = r.x; x < r.x + r.Width; x++)
|
||||
{
|
||||
BitmapCol color = Bitmap_GetPixel(&fb_bmp, x, y);
|
||||
BitmapCol color = Bitmap_GetPixel(bmp, x, y);
|
||||
int addr = (width - 1 - y + x * width) * 3; // TODO -1 or not
|
||||
fb[addr+0] = BitmapCol_B(color);
|
||||
fb[addr+1] = BitmapCol_G(color);
|
||||
@ -209,10 +220,12 @@ void Window_DrawFramebuffer(Rect2D r) {
|
||||
gfxFlushBuffers();
|
||||
//gfxSwapBuffers();
|
||||
// TODO: tearing??
|
||||
/*
|
||||
gfxSetDoubleBuffering(GFX_TOP, false);
|
||||
gfxScreenSwapBuffers(GFX_TOP, true);
|
||||
gfxSetDoubleBuffering(GFX_TOP, true);
|
||||
gfxScreenSwapBuffers(GFX_BOTTOM, true);
|
||||
*/
|
||||
}
|
||||
|
||||
void Window_FreeFramebuffer(struct Bitmap* bmp) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user