summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRay <[email protected]>2018-08-09 22:42:05 +0200
committerGitHub <[email protected]>2018-08-09 22:42:05 +0200
commit00f5f2ead296f4efdc95b2fc394acd2649e9c803 (patch)
treeb54efaf103ac0d4cc814911e3f2f7bdd01ad15ee
parent7634cbeb224a064868084639aa557be0f521743e (diff)
parentdab78d59f34efcaae46966e35410687a13dd838e (diff)
downloadraylib-00f5f2ead296f4efdc95b2fc394acd2649e9c803.tar.gz
raylib-00f5f2ead296f4efdc95b2fc394acd2649e9c803.zip
Merge pull request #616 from overdev/master
[Feature Request] 9-patch drawing function
-rw-r--r--examples/textures/resources/ninepatch_button.pngbin0 -> 5923 bytes
-rw-r--r--examples/textures/textures_image_9patch.c108
-rw-r--r--examples/textures/textures_image_9patch.pngbin0 -> 18306 bytes
-rw-r--r--src/raylib.h17
-rw-r--r--src/textures.c196
5 files changed, 321 insertions, 0 deletions
diff --git a/examples/textures/resources/ninepatch_button.png b/examples/textures/resources/ninepatch_button.png
new file mode 100644
index 00000000..d1b59970
--- /dev/null
+++ b/examples/textures/resources/ninepatch_button.png
Binary files differ
diff --git a/examples/textures/textures_image_9patch.c b/examples/textures/textures_image_9patch.c
new file mode 100644
index 00000000..74eda6ad
--- /dev/null
+++ b/examples/textures/textures_image_9patch.c
@@ -0,0 +1,108 @@
+/*******************************************************************************************
+*
+* raylib [textures] example - 9-patch drawing
+*
+* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM)
+*
+* This example has been created using raylib 2.0 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2016 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ int screenWidth = 800;
+ int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [textures] example - 9-patch drawing");
+
+ // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
+ Texture2D nPatchTexture = LoadTexture("resources/ninepatch_button.png");
+ Vector2 mousePosition;
+ Vector2 origin = {0.0f, 0.0f};
+
+ // The location and size of the n-patches.
+ Rectangle dstRec1 = {480.0f, 160.0f, 32.0f, 32.0f};
+ Rectangle dstRec2 = {160.0f, 160.0f, 32.0f, 32.0f};
+ Rectangle dstRecH = {160.0f, 93.0f, 32.0f, 32.0f}; // this rec's height is ignored
+ Rectangle dstRecV = {92.0f, 160.0f, 32.0f, 32.0f}; // this rec's width is ignored
+
+ // A 9-patch (NPT_9PATCH) changes its sizes in both axis
+ NPatchInfo ninePatchInfo1 = {(Rectangle){0.0f, 0.0f, 64.0f, 64.0f}, 12, 40, 12, 12, NPT_9PATCH };
+ NPatchInfo ninePatchInfo2 = {(Rectangle){0.0f, 128.0f, 64.0f, 64.0f}, 16, 16, 16, 16, NPT_9PATCH };
+ // A horizontal 3-patch (NPT_3PATCH_HORIZONTAL) changes its sizes along the x axis only
+ NPatchInfo h3PatchInfo = {(Rectangle){0.0f, 64.0f, 64.0f, 64.0f}, 8, 8, 8, 8, NPT_3PATCH_HORIZONTAL };
+ // A vertical 3-patch (NPT_3PATCH_VERTICAL) changes its sizes along the y axis only
+ NPatchInfo v3PatchInfo = {(Rectangle){0.0f, 192.0f, 64.0f, 64.0f}, 6, 6, 6, 6, NPT_3PATCH_VERTICAL };
+
+ SetTargetFPS(60);
+ //---------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ mousePosition = GetMousePosition();
+ // resize the n-patches based on mouse position.
+ dstRec1.width = mousePosition.x - dstRec1.x;
+ dstRec1.height = mousePosition.y - dstRec1.y;
+ dstRec2.width = mousePosition.x - dstRec2.x;
+ dstRec2.height = mousePosition.y - dstRec2.y;
+ dstRecH.width = mousePosition.x - dstRecH.x;
+ dstRecV.height = mousePosition.y - dstRecV.y;
+
+ // set a minimum width and/or height
+ if (dstRec1.width < 1.0f) dstRec1.width = 1.0f;
+ if (dstRec1.width > 300.0f) dstRec1.width = 300.0f;
+ if (dstRec1.height < 1.0f) dstRec1.height = 1.0f;
+ if (dstRec2.width < 1.0f) dstRec2.width = 1.0f;
+ if (dstRec2.width > 300.0f) dstRec2.width = 300.0f;
+ if (dstRec2.height < 1.0f) dstRec2.height = 1.0f;
+ if (dstRecH.width < 1.0f) dstRecH.width = 1.0f;
+ if (dstRecV.height < 1.0f) dstRecV.height = 1.0f;
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ // Draw the n-patches
+ DrawTextureNPatch(nPatchTexture, ninePatchInfo2, dstRec2, origin, 0.0f, WHITE);
+ DrawTextureNPatch(nPatchTexture, ninePatchInfo1, dstRec1, origin, 0.0f, WHITE);
+ DrawTextureNPatch(nPatchTexture, h3PatchInfo, dstRecH, origin, 0.0f, WHITE);
+ DrawTextureNPatch(nPatchTexture, v3PatchInfo, dstRecV, origin, 0.0f, WHITE);
+
+ // Draw the source texture
+ DrawRectangleLines( 5, 88, 74, 266, BLUE);
+ DrawTexture(nPatchTexture, 10, 93, WHITE);
+ DrawText("TEXTURE", 15, 360, 10, DARKGRAY);
+
+ DrawRectangle( 10, 10, 250, 73, Fade(SKYBLUE, 0.5));
+ DrawRectangleLines( 10, 10, 250, 73, BLUE);
+
+ DrawText("9-Patch and 3-Patch example", 20, 20, 10, BLACK);
+ DrawText(" Move the mouse to stretch or", 40, 40, 10, DARKGRAY);
+ DrawText(" shrink the n-patches.", 40, 60, 10, DARKGRAY);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadTexture(nPatchTexture); // Texture unloading
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/examples/textures/textures_image_9patch.png b/examples/textures/textures_image_9patch.png
new file mode 100644
index 00000000..5258811b
--- /dev/null
+++ b/examples/textures/textures_image_9patch.png
Binary files differ
diff --git a/src/raylib.h b/src/raylib.h
index 8d1389f7..af31e779 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -412,6 +412,15 @@ typedef struct RenderTexture2D {
// RenderTexture type, same as RenderTexture2D
typedef RenderTexture2D RenderTexture;
+typedef struct NPatchInfo {
+ Rectangle sourceRec; // Region in the texture
+ int left; // left border offset
+ int top; // top border offset
+ int right; // right border offset
+ int bottom; // bottom border offset
+ int type; // layout of the n-patch: 3x3, 1x3 or 3x1
+} NPatchInfo;
+
// Font character info
typedef struct CharInfo {
int value; // Character value (Unicode)
@@ -729,6 +738,13 @@ typedef enum {
HMD_SONY_PSVR
} VrDeviceType;
+// Type of n-patch
+typedef enum {
+ NPT_9PATCH = 0, // 3x3
+ NPT_3PATCH_VERTICAL, // 1x3
+ NPT_3PATCH_HORIZONTAL // 3x1
+} NPatchType;
+
// Callbacks to be implemented by users
typedef void (*TraceLogCallback)(int msgType, const char *text, va_list args);
@@ -999,6 +1015,7 @@ RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint);
RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters
RLAPI void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle
RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters
+RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle destRec, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely.
//------------------------------------------------------------------------------------
// Font Loading and Text Drawing Functions (Module: text)
diff --git a/src/textures.c b/src/textures.c
index 1d052070..700b4be9 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -2331,6 +2331,202 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V
}
}
+void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle destRec, Vector2 origin, float rotation, Color tint)
+{
+ if (texture.id > 0)
+ {
+ float width = (float)texture.width;
+ float height = (float)texture.height;
+
+ float patchWidth = (destRec.width <= 0.0f)? 0.0f : destRec.width;
+ float patchHeight = (destRec.height <= 0.0f)? 0.0f : destRec.height;
+
+ if (nPatchInfo.sourceRec.width < 0) nPatchInfo.sourceRec.x -= nPatchInfo.sourceRec.width;
+ if (nPatchInfo.sourceRec.height < 0) nPatchInfo.sourceRec.y -= nPatchInfo.sourceRec.height;
+ if (nPatchInfo.type == NPT_3PATCH_HORIZONTAL) patchHeight = nPatchInfo.sourceRec.height;
+ if (nPatchInfo.type == NPT_3PATCH_VERTICAL) patchWidth = nPatchInfo.sourceRec.width;
+
+ bool drawCenter = true;
+ bool drawMiddle = true;
+ float leftBorder = (float)nPatchInfo.left;
+ float topBorder = (float)nPatchInfo.top;
+ float rightBorder = (float)nPatchInfo.right;
+ float bottomBorder = (float)nPatchInfo.bottom;
+
+ // adjust the lateral (left and right) border widths in case patchWidth < texture.width
+ if (patchWidth <= (leftBorder + rightBorder) && nPatchInfo.type != NPT_3PATCH_VERTICAL)
+ {
+ drawCenter = false;
+ leftBorder = (leftBorder / (leftBorder + rightBorder)) * patchWidth;
+ rightBorder = patchWidth - leftBorder;
+ }
+ // adjust the lateral (top and bottom) border heights in case patchHeight < texture.height
+ if (patchHeight <= (topBorder + bottomBorder) && nPatchInfo.type != NPT_3PATCH_HORIZONTAL)
+ {
+ drawMiddle = false;
+ topBorder = (topBorder / (topBorder + bottomBorder)) * patchHeight;
+ bottomBorder = patchHeight - topBorder;
+ }
+
+ Vector2 vertA, vertB, vertC, vertD;
+ vertA.x = 0.0f; // outer left
+ vertA.y = 0.0f; // outer top
+ vertB.x = leftBorder; // inner left
+ vertB.y = topBorder; // inner top
+ vertC.x = patchWidth - rightBorder; // inner right
+ vertC.y = patchHeight - bottomBorder; // inner bottom
+ vertD.x = patchWidth; // outer right
+ vertD.y = patchHeight; // outer bottom
+
+ Vector2 coordA, coordB, coordC, coordD;
+ coordA.x = nPatchInfo.sourceRec.x / width;
+ coordA.y = nPatchInfo.sourceRec.y / height;
+ coordB.x = (nPatchInfo.sourceRec.x + leftBorder) / width;
+ coordB.y = (nPatchInfo.sourceRec.y + topBorder) / height;
+ coordC.x = (nPatchInfo.sourceRec.x + nPatchInfo.sourceRec.width - rightBorder) / width;
+ coordC.y = (nPatchInfo.sourceRec.y + nPatchInfo.sourceRec.height - bottomBorder) / height;
+ coordD.x = (nPatchInfo.sourceRec.x + nPatchInfo.sourceRec.width) / width;
+ coordD.y = (nPatchInfo.sourceRec.y + nPatchInfo.sourceRec.height) / height;
+
+ rlEnableTexture(texture.id);
+
+ rlPushMatrix();
+ rlTranslatef(destRec.x, destRec.y, 0);
+ rlRotatef(rotation, 0, 0, 1);
+ rlTranslatef(-origin.x, -origin.y, 0);
+
+ rlBegin(RL_QUADS);
+ rlColor4ub(tint.r, tint.g, tint.b, tint.a);
+ rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
+
+ if (nPatchInfo.type == NPT_9PATCH)
+ {
+ // ------------------------------------------------------------
+ // TOP-LEFT QUAD
+ rlTexCoord2f(coordA.x, coordB.y); rlVertex2f(vertA.x, vertB.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordB.x, coordB.y); rlVertex2f(vertB.x, vertB.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordB.x, coordA.y); rlVertex2f(vertB.x, vertA.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordA.x, coordA.y); rlVertex2f(vertA.x, vertA.y); // Top-left corner for texture and quad
+ if (drawCenter)
+ {
+ // TOP-CENTER QUAD
+ rlTexCoord2f(coordB.x, coordB.y); rlVertex2f(vertB.x, vertB.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordC.x, coordB.y); rlVertex2f(vertC.x, vertB.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordC.x, coordA.y); rlVertex2f(vertC.x, vertA.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordB.x, coordA.y); rlVertex2f(vertB.x, vertA.y); // Top-left corner for texture and quad
+ }
+ // TOP-RIGHT QUAD
+ rlTexCoord2f(coordC.x, coordB.y); rlVertex2f(vertC.x, vertB.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordD.x, coordB.y); rlVertex2f(vertD.x, vertB.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordD.x, coordA.y); rlVertex2f(vertD.x, vertA.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordC.x, coordA.y); rlVertex2f(vertC.x, vertA.y); // Top-left corner for texture and quad
+ if (drawMiddle)
+ {
+ // ------------------------------------------------------------
+ // MIDDLE-LEFT QUAD
+ rlTexCoord2f(coordA.x, coordC.y); rlVertex2f(vertA.x, vertC.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordB.x, coordC.y); rlVertex2f(vertB.x, vertC.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordB.x, coordB.y); rlVertex2f(vertB.x, vertB.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordA.x, coordB.y); rlVertex2f(vertA.x, vertB.y); // Top-left corner for texture and quad
+ if (drawCenter)
+ {
+ // MIDDLE-CENTER QUAD
+ rlTexCoord2f(coordB.x, coordC.y); rlVertex2f(vertB.x, vertC.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordC.x, coordC.y); rlVertex2f(vertC.x, vertC.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordC.x, coordB.y); rlVertex2f(vertC.x, vertB.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordB.x, coordB.y); rlVertex2f(vertB.x, vertB.y); // Top-left corner for texture and quad
+ }
+
+ // MIDDLE-RIGHT QUAD
+ rlTexCoord2f(coordC.x, coordC.y); rlVertex2f(vertC.x, vertC.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordD.x, coordC.y); rlVertex2f(vertD.x, vertC.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordD.x, coordB.y); rlVertex2f(vertD.x, vertB.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordC.x, coordB.y); rlVertex2f(vertC.x, vertB.y); // Top-left corner for texture and quad
+ }
+
+ // ------------------------------------------------------------
+ // BOTTOM-LEFT QUAD
+ rlTexCoord2f(coordA.x, coordD.y); rlVertex2f(vertA.x, vertD.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordB.x, coordD.y); rlVertex2f(vertB.x, vertD.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordB.x, coordC.y); rlVertex2f(vertB.x, vertC.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordA.x, coordC.y); rlVertex2f(vertA.x, vertC.y); // Top-left corner for texture and quad
+ if (drawCenter)
+ {
+ // BOTTOM-CENTER QUAD
+ rlTexCoord2f(coordB.x, coordD.y); rlVertex2f(vertB.x, vertD.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordC.x, coordD.y); rlVertex2f(vertC.x, vertD.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordC.x, coordC.y); rlVertex2f(vertC.x, vertC.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordB.x, coordC.y); rlVertex2f(vertB.x, vertC.y); // Top-left corner for texture and quad
+ }
+
+ // BOTTOM-RIGHT QUAD
+ rlTexCoord2f(coordC.x, coordD.y); rlVertex2f(vertC.x, vertD.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordD.x, coordD.y); rlVertex2f(vertD.x, vertD.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordD.x, coordC.y); rlVertex2f(vertD.x, vertC.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordC.x, coordC.y); rlVertex2f(vertC.x, vertC.y); // Top-left corner for texture and quad
+ }
+ else if (nPatchInfo.type == NPT_3PATCH_VERTICAL)
+ {
+ // TOP QUAD
+ // -----------------------------------------------------------
+ // Texture coords Vertices
+ rlTexCoord2f(coordA.x, coordB.y); rlVertex2f(vertA.x, vertB.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordD.x, coordB.y); rlVertex2f(vertD.x, vertB.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordD.x, coordA.y); rlVertex2f(vertD.x, vertA.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordA.x, coordA.y); rlVertex2f(vertA.x, vertA.y); // Top-left corner for texture and quad
+ if (drawCenter)
+ {
+ // MIDDLE QUAD
+ // -----------------------------------------------------------
+ // Texture coords Vertices
+ rlTexCoord2f(coordA.x, coordC.y); rlVertex2f(vertA.x, vertC.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordD.x, coordC.y); rlVertex2f(vertD.x, vertC.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordD.x, coordB.y); rlVertex2f(vertD.x, vertB.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordA.x, coordB.y); rlVertex2f(vertA.x, vertB.y); // Top-left corner for texture and quad
+ }
+ // BOTTOM QUAD
+ // -----------------------------------------------------------
+ // Texture coords Vertices
+ rlTexCoord2f(coordA.x, coordD.y); rlVertex2f(vertA.x, vertD.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordD.x, coordD.y); rlVertex2f(vertD.x, vertD.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordD.x, coordC.y); rlVertex2f(vertD.x, vertC.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordA.x, coordC.y); rlVertex2f(vertA.x, vertC.y); // Top-left corner for texture and quad
+ }
+ else if (nPatchInfo.type == NPT_3PATCH_HORIZONTAL)
+ {
+ // LEFT QUAD
+ // -----------------------------------------------------------
+ // Texture coords Vertices
+ rlTexCoord2f(coordA.x, coordD.y); rlVertex2f(vertA.x, vertD.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordB.x, coordD.y); rlVertex2f(vertB.x, vertD.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordB.x, coordA.y); rlVertex2f(vertB.x, vertA.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordA.x, coordA.y); rlVertex2f(vertA.x, vertA.y); // Top-left corner for texture and quad
+ if (drawCenter)
+ {
+ // CENTER QUAD
+ // -----------------------------------------------------------
+ // Texture coords Vertices
+ rlTexCoord2f(coordB.x, coordD.y); rlVertex2f(vertB.x, vertD.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordC.x, coordD.y); rlVertex2f(vertC.x, vertD.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordC.x, coordA.y); rlVertex2f(vertC.x, vertA.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordB.x, coordA.y); rlVertex2f(vertB.x, vertA.y); // Top-left corner for texture and quad
+ }
+ // RIGHT QUAD
+ // -----------------------------------------------------------
+ // Texture coords Vertices
+ rlTexCoord2f(coordC.x, coordD.y); rlVertex2f(vertC.x, vertD.y); // Bottom-left corner for texture and quad
+ rlTexCoord2f(coordD.x, coordD.y); rlVertex2f(vertD.x, vertD.y); // Bottom-right corner for texture and quad
+ rlTexCoord2f(coordD.x, coordA.y); rlVertex2f(vertD.x, vertA.y); // Top-right corner for texture and quad
+ rlTexCoord2f(coordC.x, coordA.y); rlVertex2f(vertC.x, vertA.y); // Top-left corner for texture and quad
+ }
+ rlEnd();
+ rlPopMatrix();
+
+ rlDisableTexture();
+
+ }
+}
+
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------