├── LICENSE ├── README.md ├── assets └── minecraft │ └── shaders │ ├── core │ ├── position_color.json │ ├── render │ │ ├── gui.fsh │ │ └── gui.vsh │ └── rendertype_gui.json │ └── include │ └── tooltip.glsl ├── pack.mcmeta └── tooltip.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Godlander 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # usage: 2 | 3 | make sure Python and Pillow is installed, and place the script in the same directory as the input tooltip texture file. 4 | 5 | ### script inputs: 6 | 7 | `file`: path to an image file used for the tooltip 8 | 9 | `corner`: corner square side length in pixels 10 | 11 | `pad`: vertical and horizontal padding when displaying ingame 12 | 13 | ### script output: 14 | 15 | the script will generate a file `tooltip.glsl` which should replace the existing one in the resourcepack `shaders/include` folder 16 | 17 | # examples: 18 | 19 | ### green tooltip 20 | 21 | ``` 22 | python tooltip.py --file green.png --corner 3 --pad 1 1 23 | ``` 24 | 25 | ![image](https://github.com/Godlander/tooltip/assets/16228717/ee9c3878-1e77-4ac1-bb0c-5c16804c2a7f) 26 | 27 | ingame: 28 | 29 | ![image](https://github.com/Godlander/tooltip/assets/16228717/30d308cf-3846-42c4-b2e0-469da82ccb40) 30 | 31 | ### gold tooltip 32 | 33 | due to the decoration on the top and bottom of the tooltip, some extra vertical padding is neccesary to make space 34 | ``` 35 | python tooltip.py --file gold.png --corner 7 --pad 1 3 36 | ``` 37 | 38 | ![image](https://github.com/Godlander/tooltip/assets/16228717/aebc2c12-9123-404e-8aee-635b573927d0) 39 | 40 | ingame: 41 | 42 | ![image](https://github.com/Godlander/tooltip/assets/16228717/9e807257-6e80-4d5b-99f1-041cbc3a759e) 43 | 44 | # credits: 45 | shader and tool commissioned by MatchaXP 46 | -------------------------------------------------------------------------------- /assets/minecraft/shaders/core/position_color.json: -------------------------------------------------------------------------------- 1 | { 2 | "blend": { 3 | "func": "add", 4 | "srcrgb": "srcalpha", 5 | "dstrgb": "1-srcalpha" 6 | }, 7 | "vertex": "render/gui", 8 | "fragment": "render/gui", 9 | "attributes": [ 10 | "Color" 11 | ], 12 | "samplers": [ 13 | ], 14 | "uniforms": [ 15 | { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, 16 | { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, 17 | { "name": "Scale", "type": "float", "count": 1, "values": [ -1.0 ] }, 18 | { "name": "GameTime", "type": "float", "count": 1, "values": [ 1.0 ] } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /assets/minecraft/shaders/core/render/gui.fsh: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | #define hex(i) vec4((i&0xFF000000u)>>24,(i&0xFF0000u)>>16,(i&0xFF00u)>>8,(i&0xFFu))/255. 4 | 5 | uniform float GameTime; 6 | 7 | in vec4 vertexColor; 8 | flat in int tooltip; 9 | in vec3 Pos; 10 | in vec3 Pos1; 11 | in vec3 Pos2; 12 | in vec3 Pos3; 13 | 14 | out vec4 fragColor; 15 | 16 | #moj_import 17 | 18 | void main() { 19 | vec4 color = vertexColor; 20 | float time = GameTime * 1200; 21 | 22 | vec2 p1 = Pos1.xy / Pos1.z; 23 | vec2 p2 = Pos2.xy / Pos2.z; 24 | vec2 p3 = Pos3.xy / Pos3.z; 25 | vec2 pmax = max(max(p1,p2),p3); 26 | vec2 pmin = min(min(p1,p2),p3); 27 | vec2 size = vec2(pmax - pmin); 28 | 29 | if (tooltip == 1) { 30 | if (all(greaterThan(size, vec2(1e3)))) {discard; return;} 31 | int i = 0; 32 | ivec4 corner = ivec4(abs(vec4(pmin, pmax) - Pos.xyxy)); 33 | ivec2 side = ivec2(clamp(abs(pmin - Pos.xy) - (size/2.) + (sizes.xy/2), ivec2(0), sizes.xy-1)); 34 | ivec4 edge = ivec4(lessThan(corner, sizes.zzzz)); 35 | switch ((edge.x<<0)+(edge.y<<1)+(edge.z<<2)+(edge.w<<3)) { 36 | case 1: //left, 0001 37 | i = (corner.x) + (side.y) * sizes.z; color = hex(l[i]); break; 38 | case 2: //top, 0010 39 | i = (side.x) + (corner.y) * sizes.x; color = hex(t[i]); break; 40 | case 4: //right, 0100 41 | i = (sizes.z-corner.z-1) + (side.y) * sizes.z; color = hex(r[i]); break; 42 | case 8: //bottom, 1000 43 | i = (side.x) + (sizes.z-corner.w-1) * sizes.x; color = hex(b[i]); break; 44 | case 3: //topleft, 0011 45 | i = (corner.x) + (corner.y) * sizes.z; color = hex(tl[i]); break; 46 | case 6: //topright, 0110 47 | i = (sizes.z-corner.z-1) + (corner.y) * sizes.z; color = hex(tr[i]); break; 48 | case 9: //botleft, 1001 49 | i = (corner.x) + (sizes.z-corner.w-1) * sizes.z; color = hex(bl[i]); break; 50 | case 12: //botright, 1100 51 | i = (sizes.z-corner.z-1) + (sizes.z-corner.w-1) * sizes.z; color = hex(br[i]); break; 52 | default: 53 | color = hex(base); 54 | } 55 | } 56 | if (color.a == 0) discard; 57 | fragColor = color; 58 | } 59 | -------------------------------------------------------------------------------- /assets/minecraft/shaders/core/render/gui.vsh: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | in vec3 Position; 4 | in vec4 Color; 5 | 6 | uniform mat4 ModelViewMat; 7 | uniform mat4 ProjMat; 8 | uniform float Scale; 9 | 10 | out vec4 vertexColor; 11 | flat out int tooltip; 12 | out vec3 Pos; 13 | out vec3 Pos1; 14 | out vec3 Pos2; 15 | out vec3 Pos3; 16 | 17 | #define hex(i) vec4((i&0xFF000000u)>>24,(i&0xFF0000u)>>16,(i&0xFF00u)>>8,(i&0xFFu))/255. 18 | const vec2[] corners = vec2[](vec2(1, 1),vec2(1, -1),vec2(-1, -1),vec2(-1, 1)); 19 | bool isgui(mat4 ProjMat) {return ProjMat[2][3] == 0.0;} 20 | 21 | #moj_import 22 | 23 | void main() { 24 | Pos = Position; 25 | vertexColor = Color; 26 | int corner = gl_VertexID % 4; 27 | 28 | tooltip = 0; 29 | if (isgui(ProjMat) && Position.z > 300 && Position.z < 500) { 30 | tooltip = 1; 31 | Pos.xy += pad * Scale * corners[corner]; 32 | if (gl_VertexID / 4 != 2) Pos = vec3(0); 33 | } 34 | 35 | Pos1 = Pos2 = Pos3 = vec3(0); 36 | switch (corner) { 37 | case 0: Pos1 = vec3(Pos.xy, 1); break; 38 | case 1: Pos2 = vec3(Pos.xy, 1); break; 39 | case 2: Pos3 = vec3(Pos.xy, 1); break; 40 | } 41 | 42 | gl_Position = ProjMat * ModelViewMat * vec4(Pos, 1.0); 43 | } -------------------------------------------------------------------------------- /assets/minecraft/shaders/core/rendertype_gui.json: -------------------------------------------------------------------------------- 1 | { 2 | "blend": { 3 | "func": "add", 4 | "srcrgb": "srcalpha", 5 | "dstrgb": "1-srcalpha" 6 | }, 7 | "vertex": "render/gui", 8 | "fragment": "render/gui", 9 | "attributes": [ 10 | "Color" 11 | ], 12 | "samplers": [ 13 | ], 14 | "uniforms": [ 15 | { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, 16 | { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, 17 | { "name": "Scale", "type": "float", "count": 1, "values": [ 1.0 ] }, 18 | { "name": "GameTime", "type": "float", "count": 1, "values": [ 1.0 ] } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /assets/minecraft/shaders/include/tooltip.glsl: -------------------------------------------------------------------------------- 1 | //generated for tooltip shader by Godlander 2 | vec2 pad = vec2(1,1); 3 | ivec3 sizes = ivec3(1,1,3); 4 | uint base = 0x1d121fffu; 5 | uint[] tl = uint[](0xffu,0xffu,0xffu,0xffu,0x86f98effu,0x86f98effu,0xffu,0x54cd8fffu,0xffu); 6 | uint[] tr = uint[](0xffu,0xffu,0xffu,0x86f98effu,0x86f98effu,0xffu,0xffu,0x54cd8fffu,0xffu); 7 | uint[] bl = uint[](0xffu,0x54cd8fffu,0xffu,0xffu,0x35a88affu,0x35a88affu,0xffu,0xffu,0xffu); 8 | uint[] br = uint[](0xffu,0x54cd8fffu,0xffu,0x35a88affu,0x35a88affu,0xffu,0xffu,0xffu,0xffu); 9 | uint[] t = uint[](0xffu,0x86f98effu,0xffu); 10 | uint[] l = uint[](0xffu,0x54cd8fffu,0xffu); 11 | uint[] r = uint[](0xffu,0x54cd8fffu,0xffu); 12 | uint[] b = uint[](0xffu,0x35a88affu,0xffu); 13 | -------------------------------------------------------------------------------- /pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "pack_format": 18, 4 | "description": "by Godlander" 5 | } 6 | } -------------------------------------------------------------------------------- /tooltip.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | from PIL import Image 4 | 5 | class vec: 6 | axis = "xyzw" 7 | def __init__(self, *args): 8 | if type(args[0]) in (list, tuple): args = args[0] 9 | self.points = list(args) 10 | def __getattr__(self, attr): 11 | if attr in self.axis: 12 | return self.points[self.axis.find(attr)] 13 | return super().getattr(self, attr) 14 | 15 | def tohex(color): 16 | color = (color[0] << 24) + (color[1] << 16) + (color[2] << 8) + (color[3]) 17 | return hex(color) + 'u' 18 | def encode(image, a, b): 19 | return ','.join([tohex(image.getpixel((x,y))) for y in range(b[0], b[1]) for x in range(a[0], a[1])]) 20 | 21 | def tooltip(image, corner, pad): 22 | size = vec(image.size) 23 | file = open("tooltip.glsl", "w") 24 | file.write("//generated for tooltip shader by Godlander\n") 25 | file.write("vec2 pad = vec2(" + str(pad[0]) + "," + str(pad[1]) + ");\n") 26 | file.write("ivec3 sizes = ivec3(" + str(size.x-corner*2) +"," + str(size.y-corner*2) + "," + str(corner) + ");\n") 27 | file.write("uint base = " + tohex(image.getpixel((corner, corner))) + ";\n") 28 | file.write("uint[] tl = uint[](" + encode(image, (0, corner), (0, corner)) + ");\n") 29 | file.write("uint[] tr = uint[](" + encode(image, (size.x-corner, size.x), (0, corner)) + ");\n") 30 | file.write("uint[] bl = uint[](" + encode(image, (0, corner), (size.y-corner, size.y)) + ");\n") 31 | file.write("uint[] br = uint[](" + encode(image, (size.x-corner, size.x), (size.y-corner, size.y)) + ");\n") 32 | file.write("uint[] t = uint[](" + encode(image, (corner, size.x-corner), (0, corner)) + ");\n") 33 | file.write("uint[] l = uint[](" + encode(image, (0, corner), (corner, size.y-corner)) + ");\n") 34 | file.write("uint[] r = uint[](" + encode(image, (size.x-corner, size.x), (corner, size.y-corner)) + ");\n") 35 | file.write("uint[] b = uint[](" + encode(image, (corner, size.x-corner), (size.y-corner, size.y)) + ");\n") 36 | file.close() 37 | 38 | path = os.getcwd() 39 | class ArgumentParserError(Exception): pass 40 | class ThrowingArgumentParser(argparse.ArgumentParser): 41 | def error(self, message): 42 | raise ArgumentParserError(message) 43 | parser = ThrowingArgumentParser(description="python script to generate a tooltip shader from image") 44 | parser.add_argument("--file", type=str, help="Tooltip image file", default='') 45 | parser.add_argument("--corner", type=int, help="Tooltip corner size", default=3) 46 | parser.add_argument("--pad", type=int, nargs=2, help="Tooltip horizontal/vertical padding", default=(0,0)) 47 | args = parser.parse_args() 48 | image = Image.open(args.file).convert("RGBA") 49 | tooltip(image, args.corner, args.pad) --------------------------------------------------------------------------------