From 3728e5fcc8bd745ef0268312a808fab6c82d7d91 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 23 Mar 2024 23:06:36 -0400 Subject: [PATCH 01/11] Color naming prototype --- css_colors.txt | 157 +++++++ generate_color_table.py | 76 ++++ wikicrayons_colors.txt | 168 +++++++ xkcd_colors.txt | 949 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1350 insertions(+) create mode 100644 css_colors.txt create mode 100644 generate_color_table.py create mode 100644 wikicrayons_colors.txt create mode 100644 xkcd_colors.txt diff --git a/css_colors.txt b/css_colors.txt new file mode 100644 index 0000000..6e14aa2 --- /dev/null +++ b/css_colors.txt @@ -0,0 +1,157 @@ +aqua #00FFFF +black #000000 +blue #0000FF +fuchsia #FF00FF +gray #808080 +green #008000 +lime #00FF00 +maroon #800000 +navy #000080 +olive #808000 +purple #800080 +red #FF0000 +silver #C0C0C0 +teal #008080 +white #FFFFFF +yellow #FFFF00 +aliceblue #F0F8FF +antiquewhite #FAEBD7 +aqua #00FFFF +aquamarine #7FFFD4 +azure #F0FFFF +beige #F5F5DC +bisque #FFE4C4 +black #000000 +blanchedalmond #FFEBCD +blue #0000FF +blueviolet #8A2BE2 +brown #A52A2A +burlywood #DEB887 +cadetblue #5F9EA0 +chartreuse #7FFF00 +chocolate #D2691E +coral #FF7F50 +cornflowerblue #6495ED +cornsilk #FFF8DC +crimson #DC143C +cyan #00FFFF +darkblue #00008B +darkcyan #008B8B +darkgoldenrod #B8860B +darkgray #A9A9A9 +darkgreen #006400 +darkkhaki #BDB76B +darkmagenta #8B008B +darkolivegreen #556B2F +darkorange #FF8C00 +darkorchid #9932CC +darkred #8B0000 +darksalmon #E9967A +darkseagreen #8FBC8F +darkslateblue #483D8B +darkslategray #2F4F4F +darkturquoise #00CED1 +darkviolet #9400D3 +deeppink #FF1493 +deepskyblue #00BFFF +dimgray #696969 +dodgerblue #1E90FF +firebrick #B22222 +floralwhite #FFFAF0 +forestgreen #228B22 +fuchsia #FF00FF +gainsboro #DCDCDC +ghostwhite #F8F8FF +gold #FFD700 +goldenrod #DAA520 +gray #7F7F7F +green #008000 +greenyellow #ADFF2F +honeydew #F0FFF0 +hotpink #FF69B4 +indianred #CD5C5C +indigo #4B0082 +ivory #FFFFF0 +khaki #F0E68C +lavender #E6E6FA +lavenderblush #FFF0F5 +lawngreen #7CFC00 +lemonchiffon #FFFACD +lightblue #ADD8E6 +lightcoral #F08080 +lightcyan #E0FFFF +lightgoldenrodyellow #FAFAD2 +lightgreen #90EE90 +lightgrey #D3D3D3 +lightpink #FFB6C1 +lightsalmon #FFA07A +lightseagreen #20B2AA +lightskyblue #87CEFA +lightslategray #778899 +lightsteelblue #B0C4DE +lightyellow #FFFFE0 +lime #00FF00 +limegreen #32CD32 +linen #FAF0E6 +magenta #FF00FF +maroon #800000 +mediumaquamarine #66CDAA +mediumblue #0000CD +mediumorchid #BA55D3 +mediumpurple #9370DB +mediumseagreen #3CB371 +mediumslateblue #7B68EE +mediumspringgreen #00FA9A +mediumturquoise #48D1CC +mediumvioletred #C71585 +midnightblue #191970 +mintcream #F5FFFA +mistyrose #FFE4E1 +moccasin #FFE4B5 +navajowhite #FFDEAD +navy #000080 +navyblue #9FAFDF +oldlace #FDF5E6 +olive #808000 +olivedrab #6B8E23 +orange #FFA500 +orangered #FF4500 +orchid #DA70D6 +palegoldenrod #EEE8AA +palegreen #98FB98 +paleturquoise #AFEEEE +palevioletred #DB7093 +papayawhip #FFEFD5 +peachpuff #FFDAB9 +peru #CD853F +pink #FFC0CB +plum #DDA0DD +powderblue #B0E0E6 +purple #800080 +red #FF0000 +rosybrown #BC8F8F +royalblue #4169E1 +saddlebrown #8B4513 +salmon #FA8072 +sandybrown #FA8072 +seagreen #2E8B57 +seashell #FFF5EE +sienna #A0522D +silver #C0C0C0 +skyblue #87CEEB +slateblue #6A5ACD +slategray #708090 +snow #FFFAFA +springgreen #00FF7F +steelblue #4682B4 +tan #D2B48C +teal #008080 +thistle #D8BFD8 +tomato #FF6347 +turquoise #40E0D0 +violet #EE82EE +wheat #F5DEB3 +white #FFFFFF +whitesmoke #F5F5F5 +yellow #FFFF00 +yellowgreen #9ACD32 diff --git a/generate_color_table.py b/generate_color_table.py new file mode 100644 index 0000000..fb0d411 --- /dev/null +++ b/generate_color_table.py @@ -0,0 +1,76 @@ +# data sources: CSS docs, jennyscrayoncollection 2017 article on Crayola colors, XKCD color survey + +# target: Single C++ header file to provide a struct of color RGB codes and names. +# This file pre-computes the nearest neighbor of every color. +# if an RGB code being searched for is closer than the nearest neighbor, it's the closest color name. + +def hex_to_rgb(txt): + if '#' in txt: txt = txt.replace('#', '') + r = txt[0:2] + g = txt[2:4] + b = txt[4:6] + return tuple([int(s, 16) for s in (r,g,b)]) + +class palette: + def __init__(self, name, filename, priority): + self.name = name + self.priority = priority + with open(filename, "r") as f: + print(f"scanning {filename}") + self.colors = {} + for line in f.read().split('\n'): + if len(line.split('\t')) < 2: continue + name, code = line.split('\t') + #print(name, code) + self.colors[name] = hex_to_rgb(code) + + def __repr__(self): + return f"" + +palettes = [ + #palette("jenny", "jenny_colors.txt", 3), # I should probably use wikipedia as a source for copyright reasons + palette("crayon", "wikicrayons_colors.txt", 2), + palette("xkcd", "xkcd_colors.txt", 1), + palette("css", "css_colors.txt", 0), + #palette("matplotlib", "matplotlib_colors.txt", 2) # there's like 10 colors total, I think we'll survive without them + ] + +all_colors = [] + +from math import sqrt +def rgbdist(c1, c2): + return sqrt((c1.r - c2.r)**2 + (c1.g - c2.g)**2 + (c1.b - c2.b)**2) + +class Color: + def __init__(self, r, g, b, name, prefix, priority): + self.r = r + self.g = g + self.b = b + self.name = name + self.prefix = prefix + self.priority = priority + self.nearest_neighbor = None + + def __repr__(self): + return f"" + + def nn(self, colors): + nearest = None + nearest_dist = 999999 + for c in colors: + dist = rgbdist(self, c) + if dist == 0: continue + if dist < nearest_dist: + nearest = c + nearest_dist = dist + self.nearest_neighbor = nearest + +for p in palettes: + prefix = p.name + priority = p.priority + for name, rgb in p.colors.items(): + all_colors.append(Color(*rgb, name, prefix, priority)) + print(f"{prefix}->{len(all_colors)}") + +for c in all_colors: + c.nn(all_colors) \ No newline at end of file diff --git a/wikicrayons_colors.txt b/wikicrayons_colors.txt new file mode 100644 index 0000000..2bbfe43 --- /dev/null +++ b/wikicrayons_colors.txt @@ -0,0 +1,168 @@ +Red #ED0A3F +Maroon #C32148 +Scarlet #FD0E35 +Brick Red #C62D42 +English Vermilion #CC474B +Madder Lake #CC3336 +Permanent Geranium Lake #E12C2C +Maximum Red #D92121 +Chestnut #B94E48 +Orange-Red #FF5349 +Sunset Orange #FE4C40 +Bittersweet #FE6F5E +Dark Venetian Red #B33B24 +Venetian Red #CC553D +Light Venetian Red #E6735C +Vivid Tangerine #FF9980 +Middle Red #E58E73 +Burnt Orange #FF7034 +Red-Orange #FF3F34 +Orange #FF8833 +Macaroni and Cheese #FFB97B +Middle Yellow Red #ECAC76 +Mango Tango #E77200 +Yellow-Orange #FFAE42 +Maximum Yellow Red #F2BA49 +Banana Mania #FBE7B2 +Maize #F2C649 +Orange-Yellow #F8D568 +Goldenrod #FCD667 +Dandelion #FED85D +Yellow #FBE870 +Green-Yellow #F1E788 +Middle Yellow #FFEB00 +Olive Green #B5B35C +Spring Green #ECEBBD +Maximum Yellow #FAFA37 +Canary #FFFF99 +Lemon Yellow #FFFF9F +Maximum Green Yellow #D9E650 +Middle Green Yellow #ACBF60 +Inchworm #B0E313 +Light Chrome Green #BEE64B +Yellow-Green #C5E17A +Maximum Green #5E8C31 +Asparagus #7BA05B +Granny Smith Apple #9DE093 +Fern #63B76C +Middle Green #4D8C57 +Green #01A638 +Medium Chrome Green #6CA67C +Forest Green #5FA777 +Sea Green #93DFB8 +Shamrock #33CC99 +Mountain Meadow #1AB385 +Jungle Green #29AB87 +Caribbean Green #00CC99 +Tropical Rain Forest #00755E +Middle Blue Green #8DD9CC +Pine Green #01796F +Maximum Blue Green #30BFBF +Robin's Egg Blue #00CCCC +Teal Blue #008080 +Light Blue #8FD8D8 +Aquamarine #458B74 +Turquoise Blue #6CDAE7 +Outer Space #2D383A +Sky Blue #76D7EA +Middle Blue #7ED4E6 +Blue-Green #0095B7 +Pacific Blue #009DC4 +Cerulean #02A4D3 +Maximum Blue #47ABCC +Blue (I) #2EB4E6 +Cerulean Blue #339ACC +Cornflower #93CCEA +Green-Blue #2887C8 +Midnight Blue #003366 +Navy Blue #0066CC +Denim #1560BD +Blue (III) #0066FF +Cadet Blue #A9B2C3 +Periwinkle #C3CDE6 +Blue (II) #4570E6 +Bluetiful #3C69E7 +Wild Blue Yonder #7A89B8 +Indigo #4F69C6 +Manatee #8D90A1 +Cobalt Blue #8C90C8 +Celestial Blue #7070CC +Blue Bell #9999CC +Maximum Blue Purple #ACACE6 +Violet-Blue #766EC8 +Blue-Violet #6456B7 +Ultramarine Blue #3F26BF +Middle Blue Purple #8B72BE +Purple Heart #652DC1 +Royal Purple #6B3FA0 +Violet (II) #8359A3 +Medium Violet #8F47B3 +Wisteria #C9A0DC +Lavender (I) #BF8FCC +Vivid Violet #803790 +Maximum Purple #733380 +Purple Mountains' Majesty #D6AEDD +Fuchsia #C154C1 +Pink Flamingo #F2583E +Violet (I) #732E6C +Brilliant Rose #E667CE +Orchid #E29CD2 +Plum #843179 +Medium Rose #D96CBE +Thistle #D8BFD8 +Mulberry #C8509B +Red-Violet #BB3385 +Middle Purple #D982B5 +Maximum Red Purple #A63A79 +Jazzberry Jam #A50B5E +Eggplant #614051 +Magenta #F653A6 +Cerise #DA3287 +Wild Strawberry #FF3399 +Lavender (II) #FBAED2 +Cotton Candy #FFB7D5 +Carnation Pink #FFA6C9 +Violet-Red #F7468A +Razzmatazz #E30B5C +Piggy Pink #FDD7E4 +Carmine #E62E6B +Blush #DB5079 +Tickle Me Pink #FC80A5 +Mauvelous #F091A9 +Salmon #FF91A4 +Middle Red Purple #A55353 +Mahogany #CA3435 +Melon #FEBAAD +Pink Sherbert #F7A38E +Burnt Sienna #E97451 +Brown #AF593E +Sepia #9E5B40 +Fuzzy Wuzzy #87421F +Beaver #926F5B +Tumbleweed #DEA681 +Raw Sienna #D27D46 +Van Dyke Brown #664228 +Tan #FA9D5A +Desert Sand #EDC9AF +Peach #FFCBA4 +Burnt Umber #805533 +Apricot #FDD5B1 +Almond #EED9C4 +Raw Umber #665233 +Shadow #837050 +Raw Sienna (I) #E6BC5C +Gold (I) #92926E +Gold (II) #E6BE8A +Silver #C9C0BB +Copper #DA8A67 +Antique Brass #C88A65 +Black #000000 +Charcoal Gray #736A62 +Gray #8B8680 +Blue-Gray #C8C8CD +Timberwolf #D9D6CF +White #FFFFFF +Crayellow #F1D651[6] +Cool Mint #DDEBEC[6] +Oatmeal #D9DAD2[6] +Powder Blue #C0D5F0[6] diff --git a/xkcd_colors.txt b/xkcd_colors.txt new file mode 100644 index 0000000..eb3cd41 --- /dev/null +++ b/xkcd_colors.txt @@ -0,0 +1,949 @@ +cloudy blue #acc2d9 +dark pastel green #56ae57 +dust #b2996e +electric lime #a8ff04 +fresh green #69d84f +light eggplant #894585 +nasty green #70b23f +really light blue #d4ffff +tea #65ab7c +warm purple #952e8f +yellowish tan #fcfc81 +cement #a5a391 +dark grass green #388004 +dusty teal #4c9085 +grey teal #5e9b8a +macaroni and cheese #efb435 +pinkish tan #d99b82 +spruce #0a5f38 +strong blue #0c06f7 +toxic green #61de2a +windows blue #3778bf +blue blue #2242c7 +blue with a hint of purple #533cc6 +booger #9bb53c +bright sea green #05ffa6 +dark green blue #1f6357 +deep turquoise #017374 +green teal #0cb577 +strong pink #ff0789 +bland #afa88b +deep aqua #08787f +lavender pink #dd85d7 +light moss green #a6c875 +light seafoam green #a7ffb5 +olive yellow #c2b709 +pig pink #e78ea5 +deep lilac #966ebd +desert #ccad60 +dusty lavender #ac86a8 +purpley grey #947e94 +purply #983fb2 +candy pink #ff63e9 +light pastel green #b2fba5 +boring green #63b365 +kiwi green #8ee53f +light grey green #b7e1a1 +orange pink #ff6f52 +tea green #bdf8a3 +very light brown #d3b683 +egg shell #fffcc4 +eggplant purple #430541 +powder pink #ffb2d0 +reddish grey #997570 +baby shit brown #ad900d +liliac #c48efd +stormy blue #507b9c +ugly brown #7d7103 +custard #fffd78 +darkish pink #da467d +deep brown #410200 +greenish beige #c9d179 +manilla #fffa86 +off blue #5684ae +battleship grey #6b7c85 +browny green #6f6c0a +bruise #7e4071 +kelley green #009337 +sickly yellow #d0e429 +sunny yellow #fff917 +azul #1d5dec +darkgreen #054907 +green/yellow #b5ce08 +lichen #8fb67b +light light green #c8ffb0 +pale gold #fdde6c +sun yellow #ffdf22 +tan green #a9be70 +burple #6832e3 +butterscotch #fdb147 +toupe #c7ac7d +dark cream #fff39a +indian red #850e04 +light lavendar #efc0fe +poison green #40fd14 +baby puke green #b6c406 +bright yellow green #9dff00 +charcoal grey #3c4142 +squash #f2ab15 +cinnamon #ac4f06 +light pea green #c4fe82 +radioactive green #2cfa1f +raw sienna #9a6200 +baby purple #ca9bf7 +cocoa #875f42 +light royal blue #3a2efe +orangeish #fd8d49 +rust brown #8b3103 +sand brown #cba560 +swamp #698339 +tealish green #0cdc73 +burnt siena #b75203 +camo #7f8f4e +dusk blue #26538d +fern #63a950 +old rose #c87f89 +pale light green #b1fc99 +peachy pink #ff9a8a +rosy pink #f6688e +light bluish green #76fda8 +light bright green #53fe5c +light neon green #4efd54 +light seafoam #a0febf +tiffany blue #7bf2da +washed out green #bcf5a6 +browny orange #ca6b02 +nice blue #107ab0 +sapphire #2138ab +greyish teal #719f91 +orangey yellow #fdb915 +parchment #fefcaf +straw #fcf679 +very dark brown #1d0200 +terracota #cb6843 +ugly blue #31668a +clear blue #247afd +creme #ffffb6 +foam green #90fda9 +grey/green #86a17d +light gold #fddc5c +seafoam blue #78d1b6 +topaz #13bbaf +violet pink #fb5ffc +wintergreen #20f986 +yellow tan #ffe36e +dark fuchsia #9d0759 +indigo blue #3a18b1 +light yellowish green #c2ff89 +pale magenta #d767ad +rich purple #720058 +sunflower yellow #ffda03 +green/blue #01c08d +leather #ac7434 +racing green #014600 +vivid purple #9900fa +dark royal blue #02066f +hazel #8e7618 +muted pink #d1768f +booger green #96b403 +canary #fdff63 +cool grey #95a3a6 +dark taupe #7f684e +darkish purple #751973 +true green #089404 +coral pink #ff6163 +dark sage #598556 +dark slate blue #214761 +flat blue #3c73a8 +mushroom #ba9e88 +rich blue #021bf9 +dirty purple #734a65 +greenblue #23c48b +icky green #8fae22 +light khaki #e6f2a2 +warm blue #4b57db +dark hot pink #d90166 +deep sea blue #015482 +carmine #9d0216 +dark yellow green #728f02 +pale peach #ffe5ad +plum purple #4e0550 +golden rod #f9bc08 +neon red #ff073a +old pink #c77986 +very pale blue #d6fffe +blood orange #fe4b03 +grapefruit #fd5956 +sand yellow #fce166 +clay brown #b2713d +dark blue grey #1f3b4d +flat green #699d4c +light green blue #56fca2 +warm pink #fb5581 +dodger blue #3e82fc +gross green #a0bf16 +ice #d6fffa +metallic blue #4f738e +pale salmon #ffb19a +sap green #5c8b15 +algae #54ac68 +bluey grey #89a0b0 +greeny grey #7ea07a +highlighter green #1bfc06 +light light blue #cafffb +light mint #b6ffbb +raw umber #a75e09 +vivid blue #152eff +deep lavender #8d5eb7 +dull teal #5f9e8f +light greenish blue #63f7b4 +mud green #606602 +pinky #fc86aa +red wine #8c0034 +shit green #758000 +tan brown #ab7e4c +darkblue #030764 +rosa #fe86a4 +lipstick #d5174e +pale mauve #fed0fc +claret #680018 +dandelion #fedf08 +orangered #fe420f +poop green #6f7c00 +ruby #ca0147 +dark #1b2431 +greenish turquoise #00fbb0 +pastel red #db5856 +piss yellow #ddd618 +bright cyan #41fdfe +dark coral #cf524e +algae green #21c36f +darkish red #a90308 +reddy brown #6e1005 +blush pink #fe828c +camouflage green #4b6113 +lawn green #4da409 +putty #beae8a +vibrant blue #0339f8 +dark sand #a88f59 +purple/blue #5d21d0 +saffron #feb209 +twilight #4e518b +warm brown #964e02 +bluegrey #85a3b2 +bubble gum pink #ff69af +duck egg blue #c3fbf4 +greenish cyan #2afeb7 +petrol #005f6a +royal #0c1793 +butter #ffff81 +dusty orange #f0833a +off yellow #f1f33f +pale olive green #b1d27b +orangish #fc824a +leaf #71aa34 +light blue grey #b7c9e2 +dried blood #4b0101 +lightish purple #a552e6 +rusty red #af2f0d +lavender blue #8b88f8 +light grass green #9af764 +light mint green #a6fbb2 +sunflower #ffc512 +velvet #750851 +brick orange #c14a09 +lightish red #fe2f4a +pure blue #0203e2 +twilight blue #0a437a +violet red #a50055 +yellowy brown #ae8b0c +carnation #fd798f +muddy yellow #bfac05 +dark seafoam green #3eaf76 +deep rose #c74767 +dusty red #b9484e +grey/blue #647d8e +lemon lime #bffe28 +purple/pink #d725de +brown yellow #b29705 +purple brown #673a3f +wisteria #a87dc2 +banana yellow #fafe4b +lipstick red #c0022f +water blue #0e87cc +brown grey #8d8468 +vibrant purple #ad03de +baby green #8cff9e +barf green #94ac02 +eggshell blue #c4fff7 +sandy yellow #fdee73 +cool green #33b864 +pale #fff9d0 +blue/grey #758da3 +hot magenta #f504c9 +greyblue #77a1b5 +purpley #8756e4 +baby shit green #889717 +brownish pink #c27e79 +dark aquamarine #017371 +diarrhea #9f8303 +light mustard #f7d560 +pale sky blue #bdf6fe +turtle green #75b84f +bright olive #9cbb04 +dark grey blue #29465b +greeny brown #696006 +lemon green #adf802 +light periwinkle #c1c6fc +seaweed green #35ad6b +sunshine yellow #fffd37 +ugly purple #a442a0 +medium pink #f36196 +puke brown #947706 +very light pink #fff4f2 +viridian #1e9167 +bile #b5c306 +faded yellow #feff7f +very pale green #cffdbc +vibrant green #0add08 +bright lime #87fd05 +spearmint #1ef876 +light aquamarine #7bfdc7 +light sage #bcecac +yellowgreen #bbf90f +baby poo #ab9004 +dark seafoam #1fb57a +deep teal #00555a +heather #a484ac +rust orange #c45508 +dirty blue #3f829d +fern green #548d44 +bright lilac #c95efb +weird green #3ae57f +peacock blue #016795 +avocado green #87a922 +faded orange #f0944d +grape purple #5d1451 +hot green #25ff29 +lime yellow #d0fe1d +mango #ffa62b +shamrock #01b44c +bubblegum #ff6cb5 +purplish brown #6b4247 +vomit yellow #c7c10c +pale cyan #b7fffa +key lime #aeff6e +tomato red #ec2d01 +lightgreen #76ff7b +merlot #730039 +night blue #040348 +purpleish pink #df4ec8 +apple #6ecb3c +baby poop green #8f9805 +green apple #5edc1f +heliotrope #d94ff5 +yellow/green #c8fd3d +almost black #070d0d +cool blue #4984b8 +leafy green #51b73b +mustard brown #ac7e04 +dusk #4e5481 +dull brown #876e4b +frog green #58bc08 +vivid green #2fef10 +bright light green #2dfe54 +fluro green #0aff02 +kiwi #9cef43 +seaweed #18d17b +navy green #35530a +ultramarine blue #1805db +iris #6258c4 +pastel orange #ff964f +yellowish orange #ffab0f +perrywinkle #8f8ce7 +tealish #24bca8 +dark plum #3f012c +pear #cbf85f +pinkish orange #ff724c +midnight purple #280137 +light urple #b36ff6 +dark mint #48c072 +greenish tan #bccb7a +light burgundy #a8415b +turquoise blue #06b1c4 +ugly pink #cd7584 +sandy #f1da7a +electric pink #ff0490 +muted purple #805b87 +mid green #50a747 +greyish #a8a495 +neon yellow #cfff04 +banana #ffff7e +carnation pink #ff7fa7 +tomato #ef4026 +sea #3c9992 +muddy brown #886806 +turquoise green #04f489 +buff #fef69e +fawn #cfaf7b +muted blue #3b719f +pale rose #fdc1c5 +dark mint green #20c073 +amethyst #9b5fc0 +blue/green #0f9b8e +chestnut #742802 +sick green #9db92c +pea #a4bf20 +rusty orange #cd5909 +stone #ada587 +rose red #be013c +pale aqua #b8ffeb +deep orange #dc4d01 +earth #a2653e +mossy green #638b27 +grassy green #419c03 +pale lime green #b1ff65 +light grey blue #9dbcd4 +pale grey #fdfdfe +asparagus #77ab56 +blueberry #464196 +purple red #990147 +pale lime #befd73 +greenish teal #32bf84 +caramel #af6f09 +deep magenta #a0025c +light peach #ffd8b1 +milk chocolate #7f4e1e +ocher #bf9b0c +off green #6ba353 +purply pink #f075e6 +lightblue #7bc8f6 +dusky blue #475f94 +golden #f5bf03 +light beige #fffeb6 +butter yellow #fffd74 +dusky purple #895b7b +french blue #436bad +ugly yellow #d0c101 +greeny yellow #c6f808 +orangish red #f43605 +shamrock green #02c14d +orangish brown #b25f03 +tree green #2a7e19 +deep violet #490648 +gunmetal #536267 +blue/purple #5a06ef +cherry #cf0234 +sandy brown #c4a661 +warm grey #978a84 +dark indigo #1f0954 +midnight #03012d +bluey green #2bb179 +grey pink #c3909b +soft purple #a66fb5 +blood #770001 +brown red #922b05 +medium grey #7d7f7c +berry #990f4b +poo #8f7303 +purpley pink #c83cb9 +light salmon #fea993 +snot #acbb0d +easter purple #c071fe +light yellow green #ccfd7f +dark navy blue #00022e +drab #828344 +light rose #ffc5cb +rouge #ab1239 +purplish red #b0054b +slime green #99cc04 +baby poop #937c00 +irish green #019529 +pink/purple #ef1de7 +dark navy #000435 +greeny blue #42b395 +light plum #9d5783 +pinkish grey #c8aca9 +dirty orange #c87606 +rust red #aa2704 +pale lilac #e4cbff +orangey red #fa4224 +primary blue #0804f9 +kermit green #5cb200 +brownish purple #76424e +murky green #6c7a0e +wheat #fbdd7e +very dark purple #2a0134 +bottle green #044a05 +watermelon #fd4659 +deep sky blue #0d75f8 +fire engine red #fe0002 +yellow ochre #cb9d06 +pumpkin orange #fb7d07 +pale olive #b9cc81 +light lilac #edc8ff +lightish green #61e160 +carolina blue #8ab8fe +mulberry #920a4e +shocking pink #fe02a2 +auburn #9a3001 +bright lime green #65fe08 +celadon #befdb7 +pinkish brown #b17261 +poo brown #885f01 +bright sky blue #02ccfe +celery #c1fd95 +dirt brown #836539 +strawberry #fb2943 +dark lime #84b701 +copper #b66325 +medium brown #7f5112 +muted green #5fa052 +robin's egg #6dedfd +bright aqua #0bf9ea +bright lavender #c760ff +ivory #ffffcb +very light purple #f6cefc +light navy #155084 +pink red #f5054f +olive brown #645403 +poop brown #7a5901 +mustard green #a8b504 +ocean green #3d9973 +very dark blue #000133 +dusty green #76a973 +light navy blue #2e5a88 +minty green #0bf77d +adobe #bd6c48 +barney #ac1db8 +jade green #2baf6a +bright light blue #26f7fd +light lime #aefd6c +dark khaki #9b8f55 +orange yellow #ffad01 +ocre #c69c04 +maize #f4d054 +faded pink #de9dac +british racing green #05480d +sandstone #c9ae74 +mud brown #60460f +light sea green #98f6b0 +robin egg blue #8af1fe +aqua marine #2ee8bb +dark sea green #11875d +soft pink #fdb0c0 +orangey brown #b16002 +cherry red #f7022a +burnt yellow #d5ab09 +brownish grey #86775f +camel #c69f59 +purplish grey #7a687f +marine #042e60 +greyish pink #c88d94 +pale turquoise #a5fbd5 +pastel yellow #fffe71 +bluey purple #6241c7 +canary yellow #fffe40 +faded red #d3494e +sepia #985e2b +coffee #a6814c +bright magenta #ff08e8 +mocha #9d7651 +ecru #feffca +purpleish #98568d +cranberry #9e003a +darkish green #287c37 +brown orange #b96902 +dusky rose #ba6873 +melon #ff7855 +sickly green #94b21c +silver #c5c9c7 +purply blue #661aee +purpleish blue #6140ef +hospital green #9be5aa +shit brown #7b5804 +mid blue #276ab3 +amber #feb308 +easter green #8cfd7e +soft blue #6488ea +cerulean blue #056eee +golden brown #b27a01 +bright turquoise #0ffef9 +red pink #fa2a55 +red purple #820747 +greyish brown #7a6a4f +vermillion #f4320c +russet #a13905 +steel grey #6f828a +lighter purple #a55af4 +bright violet #ad0afd +prussian blue #004577 +slate green #658d6d +dirty pink #ca7b80 +dark blue green #005249 +pine #2b5d34 +yellowy green #bff128 +dark gold #b59410 +bluish #2976bb +darkish blue #014182 +dull red #bb3f3f +pinky red #fc2647 +bronze #a87900 +pale teal #82cbb2 +military green #667c3e +barbie pink #fe46a5 +bubblegum pink #fe83cc +pea soup green #94a617 +dark mustard #a88905 +shit #7f5f00 +medium purple #9e43a2 +very dark green #062e03 +dirt #8a6e45 +dusky pink #cc7a8b +red violet #9e0168 +lemon yellow #fdff38 +pistachio #c0fa8b +dull yellow #eedc5b +dark lime green #7ebd01 +denim blue #3b5b92 +teal blue #01889f +lightish blue #3d7afd +purpley blue #5f34e7 +light indigo #6d5acf +swamp green #748500 +brown green #706c11 +dark maroon #3c0008 +hot purple #cb00f5 +dark forest green #002d04 +faded blue #658cbb +drab green #749551 +light lime green #b9ff66 +snot green #9dc100 +yellowish #faee66 +light blue green #7efbb3 +bordeaux #7b002c +light mauve #c292a1 +ocean #017b92 +marigold #fcc006 +muddy green #657432 +dull orange #d8863b +steel #738595 +electric purple #aa23ff +fluorescent green #08ff08 +yellowish brown #9b7a01 +blush #f29e8e +soft green #6fc276 +bright orange #ff5b00 +lemon #fdff52 +purple grey #866f85 +acid green #8ffe09 +pale lavender #eecffe +violet blue #510ac9 +light forest green #4f9153 +burnt red #9f2305 +khaki green #728639 +cerise #de0c62 +faded purple #916e99 +apricot #ffb16d +dark olive green #3c4d03 +grey brown #7f7053 +green grey #77926f +true blue #010fcc +pale violet #ceaefa +periwinkle blue #8f99fb +light sky blue #c6fcff +blurple #5539cc +green brown #544e03 +bluegreen #017a79 +bright teal #01f9c6 +brownish yellow #c9b003 +pea soup #929901 +forest #0b5509 +barney purple #a00498 +ultramarine #2000b1 +purplish #94568c +puke yellow #c2be0e +bluish grey #748b97 +dark periwinkle #665fd1 +dark lilac #9c6da5 +reddish #c44240 +light maroon #a24857 +dusty purple #825f87 +terra cotta #c9643b +avocado #90b134 +marine blue #01386a +teal green #25a36f +slate grey #59656d +lighter green #75fd63 +electric green #21fc0d +dusty blue #5a86ad +golden yellow #fec615 +bright yellow #fffd01 +light lavender #dfc5fe +umber #b26400 +poop #7f5e00 +dark peach #de7e5d +jungle green #048243 +eggshell #ffffd4 +denim #3b638c +yellow brown #b79400 +dull purple #84597e +chocolate brown #411900 +wine red #7b0323 +neon blue #04d9ff +dirty green #667e2c +light tan #fbeeac +ice blue #d7fffe +cadet blue #4e7496 +dark mauve #874c62 +very light blue #d5ffff +grey purple #826d8c +pastel pink #ffbacd +very light green #d1ffbd +dark sky blue #448ee4 +evergreen #05472a +dull pink #d5869d +aubergine #3d0734 +mahogany #4a0100 +reddish orange #f8481c +deep green #02590f +vomit green #89a203 +purple pink #e03fd8 +dusty pink #d58a94 +faded green #7bb274 +camo green #526525 +pinky purple #c94cbe +pink purple #db4bda +brownish red #9e3623 +dark rose #b5485d +mud #735c12 +brownish #9c6d57 +emerald green #028f1e +pale brown #b1916e +dull blue #49759c +burnt umber #a0450e +medium green #39ad48 +clay #b66a50 +light aqua #8cffdb +light olive green #a4be5c +brownish orange #cb7723 +dark aqua #05696b +purplish pink #ce5dae +dark salmon #c85a53 +greenish grey #96ae8d +jade #1fa774 +ugly green #7a9703 +dark beige #ac9362 +emerald #01a049 +pale red #d9544d +light magenta #fa5ff7 +sky #82cafc +light cyan #acfffc +yellow orange #fcb001 +reddish purple #910951 +reddish pink #fe2c54 +orchid #c875c4 +dirty yellow #cdc50a +orange red #fd411e +deep red #9a0200 +orange brown #be6400 +cobalt blue #030aa7 +neon pink #fe019a +rose pink #f7879a +greyish purple #887191 +raspberry #b00149 +aqua green #12e193 +salmon pink #fe7b7c +tangerine #ff9408 +brownish green #6a6e09 +red brown #8b2e16 +greenish brown #696112 +pumpkin #e17701 +pine green #0a481e +charcoal #343837 +baby pink #ffb7ce +cornflower #6a79f7 +blue violet #5d06e9 +chocolate #3d1c02 +greyish green #82a67d +scarlet #be0119 +green yellow #c9ff27 +dark olive #373e02 +sienna #a9561e +pastel purple #caa0ff +terracotta #ca6641 +aqua blue #02d8e9 +sage green #88b378 +blood red #980002 +deep pink #cb0162 +grass #5cac2d +moss #769958 +pastel blue #a2bffe +bluish green #10a674 +green blue #06b48b +dark tan #af884a +greenish blue #0b8b87 +pale orange #ffa756 +vomit #a2a415 +forrest green #154406 +dark lavender #856798 +dark violet #34013f +purple blue #632de9 +dark cyan #0a888a +olive drab #6f7632 +pinkish #d46a7e +cobalt #1e488f +neon purple #bc13fe +light turquoise #7ef4cc +apple green #76cd26 +dull green #74a662 +wine #80013f +powder blue #b1d1fc +off white #ffffe4 +electric blue #0652ff +dark turquoise #045c5a +blue purple #5729ce +azure #069af3 +bright red #ff000d +pinkish red #f10c45 +cornflower blue #5170d7 +light olive #acbf69 +grape #6c3461 +greyish blue #5e819d +purplish blue #601ef9 +yellowish green #b0dd16 +greenish yellow #cdfd02 +medium blue #2c6fbb +dusty rose #c0737a +light violet #d6b4fc +midnight blue #020035 +bluish purple #703be7 +red orange #fd3c06 +dark magenta #960056 +greenish #40a368 +ocean blue #03719c +coral #fc5a50 +cream #ffffc2 +reddish brown #7f2b0a +burnt sienna #b04e0f +brick #a03623 +sage #87ae73 +grey green #789b73 +white #ffffff +robin's egg blue #98eff9 +moss green #658b38 +steel blue #5a7d9a +eggplant #380835 +light yellow #fffe7a +leaf green #5ca904 +light grey #d8dcd6 +puke #a5a502 +pinkish purple #d648d7 +sea blue #047495 +pale purple #b790d4 +slate blue #5b7c99 +blue grey #607c8e +hunter green #0b4008 +fuchsia #ed0dd9 +crimson #8c000f +pale yellow #ffff84 +ochre #bf9005 +mustard yellow #d2bd0a +light red #ff474c +cerulean #0485d1 +pale pink #ffcfdc +deep blue #040273 +rust #a83c09 +light teal #90e4c1 +slate #516572 +goldenrod #fac205 +dark yellow #d5b60a +dark grey #363737 +army green #4b5d16 +grey blue #6b8ba4 +seafoam #80f9ad +puce #a57e52 +spring green #a9f971 +dark orange #c65102 +sand #e2ca76 +pastel green #b0ff9d +mint #9ffeb0 +light orange #fdaa48 +bright pink #fe01b1 +chartreuse #c1f80a +deep purple #36013f +dark brown #341c02 +taupe #b9a281 +pea green #8eab12 +puke green #9aae07 +kelly green #02ab2e +seafoam green #7af9ab +blue green #137e6d +khaki #aaa662 +burgundy #610023 +dark teal #014d4e +brick red #8f1402 +royal purple #4b006e +plum #580f41 +mint green #8fff9f +gold #dbb40c +baby blue #a2cffe +yellow green #c0fb2d +bright purple #be03fd +dark red #840000 +pale blue #d0fefe +grass green #3f9b0b +navy #01153e +aquamarine #04d8b2 +burnt orange #c04e01 +neon green #0cff0c +bright blue #0165fc +rose #cf6275 +light pink #ffd1df +mustard #ceb301 +indigo #380282 +lime #aaff32 +sea green #53fca1 +periwinkle #8e82fe +dark pink #cb416b +olive green #677a04 +peach #ffb07c +pale green #c7fdb5 +light brown #ad8150 +hot pink #ff028d +black #000000 +lilac #cea2fd +navy blue #001146 +royal blue #0504aa +beige #e6daa6 +salmon #ff796c +olive #6e750e +maroon #650021 +bright green #01ff07 +dark purple #35063e +mauve #ae7181 +forest green #06470c +aqua #13eac9 +cyan #00ffff +tan #d1b26f +dark blue #00035b +lavender #c79fef +turquoise #06c2ac +dark green #033500 +violet #9a0eea +light purple #bf77f6 +lime green #89fe05 +grey #929591 +sky blue #75bbfd +yellow #ffff14 +magenta #c20078 +light green #96f97b +orange #f97306 +teal #029386 +light blue #95d0fc +red #e50000 +brown #653700 +pink #ff81c0 +blue #0343df +green #15b01a +purple #7e1e9c From 2cac6f03c601de4591dbd8205418a1cbfe7e7e9f Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 23 Mar 2024 23:07:10 -0400 Subject: [PATCH 02/11] untested PyColor base implementation --- src/PyColor.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ src/PyColor.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 src/PyColor.cpp create mode 100644 src/PyColor.h diff --git a/src/PyColor.cpp b/src/PyColor.cpp new file mode 100644 index 0000000..17b4a3f --- /dev/null +++ b/src/PyColor.cpp @@ -0,0 +1,42 @@ +#include "PyColor.h" + + +PyColor::PyColor() +{ +} + +PyObject* PyTexture::pyObject() +{ + PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyColorType, 0); + try { + ((PyTextureObject*)obj)->data = shared_from_this(); + } + catch (std::bad_weak_ptr& e) + { + std::cout << "Bad weak ptr: shared_from_this() failed in PyTexture::pyObject(); did you create a PyTexture outside of std::make_shared? enjoy your segfault, soon!" << std::endl; + } + // TODO - shared_from_this will raise an exception if the object does not have a shared pointer. Constructor should be made private; write a factory function + return obj; +} + +Py_hash_t PyTexture::hash(PyObject* obj) +{ + auto self = (PyTextureObject*)obj; + return reinterpret_cast(self->data.get()); +} + +int PyTexture::init(PyTextureObject* self, PyObject* args, PyObject* kwds) +{ + static const char* keywords[] = { "filename", "sprite_width", "sprite_height", nullptr }; + char* filename; + int sprite_width, sprite_height; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sii", const_cast(keywords), &filename, &sprite_width, &sprite_height)) + return -1; + self->data = std::make_shared(filename, sprite_width, sprite_height); + return 0; +} + +PyObject* PyTexture::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds) +{ + return (PyObject*)type->tp_alloc(type, 0); +} diff --git a/src/PyColor.h b/src/PyColor.h new file mode 100644 index 0000000..067c323 --- /dev/null +++ b/src/PyColor.h @@ -0,0 +1,40 @@ +#pragma once +#include "Common.h" +#include "Python.h" + +class PyColor; + +typedef struct { + sf::Color* target; // color target to set/get + std::weak_ptr parent; // lifetime management: parent must still exist + int index; // specific to the parent class, which color is it? +} _PyColorData; + +typedef struct { + PyObject_HEAD + _PyColorData data; +} PyTextureObject; + +class PyColor +{ +private: + _PyColorData data; +public: + PyObject* pyObject(); + static Py_hash_t hash(PyObject*); + static int init(PyColorObject*, PyObject*, PyObject*); + static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL); +}; + +namespace mcrfpydef { + static PyTypeObject PyColorType = { + .tp_name = "mcrfpy.Color", + .tp_basicsize = sizeof(PyColorObject), + .tp_itemsize = 0, + .tp_hash = PyColor::hash, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = PyDoc_STR("SFML Color Object"), + .tp_init = (initproc)PyColor::init, + .tp_new = PyTColor::pynew, + }; +} From 79090b553f08af7dd03892c2153073d8457a566d Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sun, 24 Mar 2024 08:36:06 -0400 Subject: [PATCH 03/11] Unsaved changes from last night --- src/PyColor.cpp | 27 ++++++++++++++------------- src/PyColor.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/PyColor.cpp b/src/PyColor.cpp index 17b4a3f..1180c94 100644 --- a/src/PyColor.cpp +++ b/src/PyColor.cpp @@ -5,29 +5,30 @@ PyColor::PyColor() { } -PyObject* PyTexture::pyObject() +PyObject* PyColor::pyObject() { PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyColorType, 0); - try { - ((PyTextureObject*)obj)->data = shared_from_this(); - } - catch (std::bad_weak_ptr& e) - { - std::cout << "Bad weak ptr: shared_from_this() failed in PyTexture::pyObject(); did you create a PyTexture outside of std::make_shared? enjoy your segfault, soon!" << std::endl; - } - // TODO - shared_from_this will raise an exception if the object does not have a shared pointer. Constructor should be made private; write a factory function + ((PyColorObject*)obj.data = data; return obj; } -Py_hash_t PyTexture::hash(PyObject* obj) +Py_hash_t PyColor::hash(PyObject* obj) { auto self = (PyTextureObject*)obj; - return reinterpret_cast(self->data.get()); + Py_hash_t value = 0; + value += obj.data.r; + value << 8; value += obj.data.g; + value << 8; value += obj.data.b; + value << 8; value += obj.data.a; + value << (sizeof(*UIDrawable) * 8); + if (auto ptr = self.data.parent.lock()) + value += reinterpret_cast(ptr); + return value; } -int PyTexture::init(PyTextureObject* self, PyObject* args, PyObject* kwds) +int PyColor::init(PyColorObject* self, PyObject* args, PyObject* kwds) { - static const char* keywords[] = { "filename", "sprite_width", "sprite_height", nullptr }; + static const char* keywords[] = { "r", "g", "b", "a", nullptr }; char* filename; int sprite_width, sprite_height; if (!PyArg_ParseTupleAndKeywords(args, kwds, "sii", const_cast(keywords), &filename, &sprite_width, &sprite_height)) diff --git a/src/PyColor.h b/src/PyColor.h index 067c323..09e46d4 100644 --- a/src/PyColor.h +++ b/src/PyColor.h @@ -20,12 +20,54 @@ class PyColor private: _PyColorData data; public: + void set(sf::Color); + sf::Color get(); PyObject* pyObject(); static Py_hash_t hash(PyObject*); static int init(PyColorObject*, PyObject*, PyObject*); static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL); + + static PyGetSetDef getsetters[] = { + {"r", (getter)PyColor_get_member, (setter)PyColor_set_member, "Red component", (void*)0}, + {"g", (getter)PyColor_get_member, (setter)PyColor_set_member, "Green component", (void*)1}, + {"b", (getter)PyColor_get_member, (setter)PyColor_set_member, "Blue component", (void*)2}, + {"a", (getter)PyColor_get_member, (setter)PyColor_set_member, "Alpha component", (void*)3}, + {NULL} + }; }; + + +// static PyTypeObject PyColorType = { +// //PyVarObject_HEAD_INIT(NULL, 0) +// .tp_name = "mcrfpy.Color", +// .tp_basicsize = sizeof(PyColorObject), +// .tp_itemsize = 0, +// .tp_dealloc = (destructor)[](PyObject* self) +// { +// PyColorObject* obj = (PyColorObject*)self; +// obj->data.reset(); +// Py_TYPE(self)->tp_free(self); +// }, +// //.tp_repr = (reprfunc)PyUIFrame_repr, +// //.tp_hash = NULL, +// //.tp_iter +// //.tp_iternext +// .tp_flags = Py_TPFLAGS_DEFAULT, +// .tp_doc = PyDoc_STR("SFML Color object (RGBA)"), +// //.tp_methods = PyUIFrame_methods, +// //.tp_members = PyColor_members, +// .tp_getset = PyColor_getsetters, +// //.tp_base = NULL, +// //.tp_init = (initproc)PyUIFrame_init, +// .tp_new = [](PyTypeObject* type, PyObject* args, PyObject* kwds) -> PyObject* +// { +// PyColorObject* self = (PyColorObject*)type->tp_alloc(type, 0); +// if (self) self->data = std::make_shared(); +// return (PyObject*)self; +// } +// }; + namespace mcrfpydef { static PyTypeObject PyColorType = { .tp_name = "mcrfpy.Color", @@ -34,6 +76,7 @@ namespace mcrfpydef { .tp_hash = PyColor::hash, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = PyDoc_STR("SFML Color Object"), + .tp_getset = PyColor::getsetters, .tp_init = (initproc)PyColor::init, .tp_new = PyTColor::pynew, }; From 13672c8fdbe7f3db385c93234331bb16267ef18b Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sun, 24 Mar 2024 21:19:37 -0400 Subject: [PATCH 04/11] Dabbling around this morning; still not building --- src/PyColor.cpp | 50 +++++++++----- src/PyColor.h | 19 ++++-- src/UI.h | 168 ++++++++++++++++++++++++------------------------ 3 files changed, 132 insertions(+), 105 deletions(-) diff --git a/src/PyColor.cpp b/src/PyColor.cpp index 1180c94..f42c19e 100644 --- a/src/PyColor.cpp +++ b/src/PyColor.cpp @@ -1,43 +1,61 @@ #include "PyColor.h" - -PyColor::PyColor() +PyColor::PyColor(sf::Color* target, std::weak_ptr parent, int index) { + data.index = index; + data.parent = parent; + data.target = target; +} + +PyColor::PyColor(sf::Color target) +{ + data.index = PyColor::SELF_OWNED; + data.parent = std::weak_ptr(); + data.target = new sf::Color; +} + +PyColor::~PyColor() +{ + if (data.index == PyColor::SELF_OWNED) + delete data.target; } PyObject* PyColor::pyObject() { PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyColorType, 0); - ((PyColorObject*)obj.data = data; + ((PyColorObject*)obj->data = data; return obj; } Py_hash_t PyColor::hash(PyObject* obj) { - auto self = (PyTextureObject*)obj; + auto self = (PyColorObject*)obj; Py_hash_t value = 0; - value += obj.data.r; - value << 8; value += obj.data.g; - value << 8; value += obj.data.b; - value << 8; value += obj.data.a; - value << (sizeof(*UIDrawable) * 8); - if (auto ptr = self.data.parent.lock()) + auto ptr = self.data.parent.lock(); + if (ptr || self->data.index == PyColor::SELF_OWNED) + { + value += self->data.target->r; + value << 8; value += self->data.target->g; + value << 8; value += self->data.target->b; + value << 8; value += self->data.target->a; + } + if (ptr) + { + + value << (sizeof(*UIDrawable) * 8); value += reinterpret_cast(ptr); + } + return value; } int PyColor::init(PyColorObject* self, PyObject* args, PyObject* kwds) { static const char* keywords[] = { "r", "g", "b", "a", nullptr }; - char* filename; - int sprite_width, sprite_height; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sii", const_cast(keywords), &filename, &sprite_width, &sprite_height)) - return -1; - self->data = std::make_shared(filename, sprite_width, sprite_height); return 0; } -PyObject* PyTexture::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds) +PyObject* PyColor::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds) { return (PyObject*)type->tp_alloc(type, 0); } diff --git a/src/PyColor.h b/src/PyColor.h index 09e46d4..d47c2e7 100644 --- a/src/PyColor.h +++ b/src/PyColor.h @@ -3,6 +3,7 @@ #include "Python.h" class PyColor; +class UIDrawable; // forward declare for pointer typedef struct { sf::Color* target; // color target to set/get @@ -13,13 +14,16 @@ typedef struct { typedef struct { PyObject_HEAD _PyColorData data; -} PyTextureObject; +} PyColorObject; class PyColor { private: _PyColorData data; + static int SELF_OWNED = -1; public: + PyColor(sf::Color* target, std::weak_ptr parent, int index) // linked constructor + PyColor::PyColor(sf::Color target) // simple color container void set(sf::Color); sf::Color get(); PyObject* pyObject(); @@ -27,11 +31,14 @@ public: static int init(PyColorObject*, PyObject*, PyObject*); static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL); + static PyObject* get_member(PyObject*, void*); + static int set_member(PyObject*, PyObject*, void*); + static PyGetSetDef getsetters[] = { - {"r", (getter)PyColor_get_member, (setter)PyColor_set_member, "Red component", (void*)0}, - {"g", (getter)PyColor_get_member, (setter)PyColor_set_member, "Green component", (void*)1}, - {"b", (getter)PyColor_get_member, (setter)PyColor_set_member, "Blue component", (void*)2}, - {"a", (getter)PyColor_get_member, (setter)PyColor_set_member, "Alpha component", (void*)3}, + {"r", (getter)PyColor::get_member, (setter)PyColor::set_member, "Red component", (void*)0}, + {"g", (getter)PyColor::get_member, (setter)PyColor::set_member, "Green component", (void*)1}, + {"b", (getter)PyColor::get_member, (setter)PyColor::set_member, "Blue component", (void*)2}, + {"a", (getter)PyColor::get_member, (setter)PyColor::set_member, "Alpha component", (void*)3}, {NULL} }; }; @@ -78,6 +85,6 @@ namespace mcrfpydef { .tp_doc = PyDoc_STR("SFML Color Object"), .tp_getset = PyColor::getsetters, .tp_init = (initproc)PyColor::init, - .tp_new = PyTColor::pynew, + .tp_new = PyColor::pynew, }; } diff --git a/src/UI.h b/src/UI.h index c45fe42..c6b68b4 100644 --- a/src/UI.h +++ b/src/UI.h @@ -46,10 +46,12 @@ typedef struct { } PyColorObject; */ +/* // Moved to PyColor.h typedef struct { PyObject_HEAD std::shared_ptr data; } PyColorObject; +*/ class UIFrame: public UIDrawable { @@ -444,89 +446,89 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c */ - static PyObject* PyColor_get_member(PyColorObject* self, void* closure) - { - auto member_ptr = reinterpret_cast(closure); - if (member_ptr == 0) - return PyLong_FromLong(self->data->r); - else if (member_ptr == 1) - return PyLong_FromLong(self->data->g); - else if (member_ptr == 2) - return PyLong_FromLong(self->data->b); - else if (member_ptr == 3) - return PyLong_FromLong(self->data->a); - else - { - PyErr_SetString(PyExc_AttributeError, "Invalid attribute"); - return nullptr; - } - } - - static int PyColor_set_member(PyColorObject* self, PyObject* value, void* closure) - { - if (PyLong_Check(value)) - { - long int_val = PyLong_AsLong(value); - if (int_val < 0) - int_val = 0; - else if (int_val > 255) - int_val = 255; - auto member_ptr = reinterpret_cast(closure); - if (member_ptr == 0) - self->data->r = static_cast(int_val); - else if (member_ptr == 1) - self->data->g = static_cast(int_val); - else if (member_ptr == 2) - self->data->b = static_cast(int_val); - else if (member_ptr == 3) - self->data->a = static_cast(int_val); - } - else - { - PyErr_SetString(PyExc_TypeError, "Value must be an integer."); - return -1; - } - return 0; - } - - static PyGetSetDef PyColor_getsetters[] = { - {"r", (getter)PyColor_get_member, (setter)PyColor_set_member, "Red component", (void*)0}, - {"g", (getter)PyColor_get_member, (setter)PyColor_set_member, "Green component", (void*)1}, - {"b", (getter)PyColor_get_member, (setter)PyColor_set_member, "Blue component", (void*)2}, - {"a", (getter)PyColor_get_member, (setter)PyColor_set_member, "Alpha component", (void*)3}, - {NULL} - }; - - - static PyTypeObject PyColorType = { - //PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "mcrfpy.Color", - .tp_basicsize = sizeof(PyColorObject), - .tp_itemsize = 0, - .tp_dealloc = (destructor)[](PyObject* self) - { - PyColorObject* obj = (PyColorObject*)self; - obj->data.reset(); - Py_TYPE(self)->tp_free(self); - }, - //.tp_repr = (reprfunc)PyUIFrame_repr, - //.tp_hash = NULL, - //.tp_iter - //.tp_iternext - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = PyDoc_STR("SFML Color object (RGBA)"), - //.tp_methods = PyUIFrame_methods, - //.tp_members = PyColor_members, - .tp_getset = PyColor_getsetters, - //.tp_base = NULL, - //.tp_init = (initproc)PyUIFrame_init, - .tp_new = [](PyTypeObject* type, PyObject* args, PyObject* kwds) -> PyObject* - { - PyColorObject* self = (PyColorObject*)type->tp_alloc(type, 0); - if (self) self->data = std::make_shared(); - return (PyObject*)self; - } - }; +// static PyObject* PyColor_get_member(PyColorObject* self, void* closure) +// { +// auto member_ptr = reinterpret_cast(closure); +// if (member_ptr == 0) +// return PyLong_FromLong(self->data->r); +// else if (member_ptr == 1) +// return PyLong_FromLong(self->data->g); +// else if (member_ptr == 2) +// return PyLong_FromLong(self->data->b); +// else if (member_ptr == 3) +// return PyLong_FromLong(self->data->a); +// else +// { +// PyErr_SetString(PyExc_AttributeError, "Invalid attribute"); +// return nullptr; +// } +// } +// +// static int PyColor_set_member(PyColorObject* self, PyObject* value, void* closure) +// { +// if (PyLong_Check(value)) +// { +// long int_val = PyLong_AsLong(value); +// if (int_val < 0) +// int_val = 0; +// else if (int_val > 255) +// int_val = 255; +// auto member_ptr = reinterpret_cast(closure); +// if (member_ptr == 0) +// self->data->r = static_cast(int_val); +// else if (member_ptr == 1) +// self->data->g = static_cast(int_val); +// else if (member_ptr == 2) +// self->data->b = static_cast(int_val); +// else if (member_ptr == 3) +// self->data->a = static_cast(int_val); +// } +// else +// { +// PyErr_SetString(PyExc_TypeError, "Value must be an integer."); +// return -1; +// } +// return 0; +// } +// +// static PyGetSetDef PyColor_getsetters[] = { +// {"r", (getter)PyColor_get_member, (setter)PyColor_set_member, "Red component", (void*)0}, +// {"g", (getter)PyColor_get_member, (setter)PyColor_set_member, "Green component", (void*)1}, +// {"b", (getter)PyColor_get_member, (setter)PyColor_set_member, "Blue component", (void*)2}, +// {"a", (getter)PyColor_get_member, (setter)PyColor_set_member, "Alpha component", (void*)3}, +// {NULL} +// }; +// +// +// static PyTypeObject PyColorType = { +// //PyVarObject_HEAD_INIT(NULL, 0) +// .tp_name = "mcrfpy.Color", +// .tp_basicsize = sizeof(PyColorObject), +// .tp_itemsize = 0, +// .tp_dealloc = (destructor)[](PyObject* self) +// { +// PyColorObject* obj = (PyColorObject*)self; +// obj->data.reset(); +// Py_TYPE(self)->tp_free(self); +// }, +// //.tp_repr = (reprfunc)PyUIFrame_repr, +// //.tp_hash = NULL, +// //.tp_iter +// //.tp_iternext +// .tp_flags = Py_TPFLAGS_DEFAULT, +// .tp_doc = PyDoc_STR("SFML Color object (RGBA)"), +// //.tp_methods = PyUIFrame_methods, +// //.tp_members = PyColor_members, +// .tp_getset = PyColor_getsetters, +// //.tp_base = NULL, +// //.tp_init = (initproc)PyUIFrame_init, +// .tp_new = [](PyTypeObject* type, PyObject* args, PyObject* kwds) -> PyObject* +// { +// PyColorObject* self = (PyColorObject*)type->tp_alloc(type, 0); +// if (self) self->data = std::make_shared(); +// return (PyObject*)self; +// } +// }; /* * From 1601fc7faba53e8d0d5814688b80e5cbfec2a700 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Mon, 25 Mar 2024 20:48:08 -0400 Subject: [PATCH 05/11] Still doesn't compile, but now the issue is in UI.h overcoupling. Progress! --- src/PyColor.cpp | 16 ++++++++++++---- src/PyColor.h | 11 ++++++----- src/UI.h | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/PyColor.cpp b/src/PyColor.cpp index f42c19e..651fbd6 100644 --- a/src/PyColor.cpp +++ b/src/PyColor.cpp @@ -1,5 +1,13 @@ #include "PyColor.h" +PyGetSetDef PyColor::getsetters[] = { + {"r", (getter)PyColor::get_member, (setter)PyColor::set_member, "Red component", (void*)0}, + {"g", (getter)PyColor::get_member, (setter)PyColor::set_member, "Green component", (void*)1}, + {"b", (getter)PyColor::get_member, (setter)PyColor::set_member, "Blue component", (void*)2}, + {"a", (getter)PyColor::get_member, (setter)PyColor::set_member, "Alpha component", (void*)3}, + {NULL} +}; + PyColor::PyColor(sf::Color* target, std::weak_ptr parent, int index) { data.index = index; @@ -34,10 +42,10 @@ Py_hash_t PyColor::hash(PyObject* obj) auto ptr = self.data.parent.lock(); if (ptr || self->data.index == PyColor::SELF_OWNED) { - value += self->data.target->r; - value << 8; value += self->data.target->g; - value << 8; value += self->data.target->b; - value << 8; value += self->data.target->a; + value += self->data.target.r; + value << 8; value += self->data.target.g; + value << 8; value += self->data.target.b; + value << 8; value += self->data.target.a; } if (ptr) { diff --git a/src/PyColor.h b/src/PyColor.h index d47c2e7..28a40f3 100644 --- a/src/PyColor.h +++ b/src/PyColor.h @@ -20,10 +20,10 @@ class PyColor { private: _PyColorData data; - static int SELF_OWNED = -1; + static const int SELF_OWNED = -1; public: - PyColor(sf::Color* target, std::weak_ptr parent, int index) // linked constructor - PyColor::PyColor(sf::Color target) // simple color container + PyColor(sf::Color* target, std::weak_ptr parent, int index); // linked constructor + PyColor(sf::Color target); // simple color container void set(sf::Color); sf::Color get(); PyObject* pyObject(); @@ -34,13 +34,14 @@ public: static PyObject* get_member(PyObject*, void*); static int set_member(PyObject*, PyObject*, void*); - static PyGetSetDef getsetters[] = { + static PyGetSetDef getsetters[]; + /*static PyGetSetDef getsetters[] = { {"r", (getter)PyColor::get_member, (setter)PyColor::set_member, "Red component", (void*)0}, {"g", (getter)PyColor::get_member, (setter)PyColor::set_member, "Green component", (void*)1}, {"b", (getter)PyColor::get_member, (setter)PyColor::set_member, "Blue component", (void*)2}, {"a", (getter)PyColor::get_member, (setter)PyColor::set_member, "Alpha component", (void*)3}, {NULL} - }; + };*/ }; diff --git a/src/UI.h b/src/UI.h index c6b68b4..70a28f0 100644 --- a/src/UI.h +++ b/src/UI.h @@ -7,6 +7,7 @@ #include #include "PyCallable.h" #include "PyTexture.h" +#include "PyColor.h" enum PyObjectsEnum : int { From 13a4ddf41b41dfc123a00468377b4f8fae0da845 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Tue, 26 Mar 2024 23:02:00 -0400 Subject: [PATCH 06/11] Build runs again. PyColor objects are being instantiated, with bugs and no test of color changing --- src/PyColor.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++++---- src/PyColor.h | 20 +++++-- src/UI.h | 14 ++++- 3 files changed, 159 insertions(+), 14 deletions(-) diff --git a/src/PyColor.cpp b/src/PyColor.cpp index 651fbd6..9d001df 100644 --- a/src/PyColor.cpp +++ b/src/PyColor.cpp @@ -8,11 +8,19 @@ PyGetSetDef PyColor::getsetters[] = { {NULL} }; +PyColor::PyColor(_PyColorData d) +{ + data = d; + if (data.index == PyColor::SELF_OWNED) data.index = PyColor::BORROWED; // I think this is a bad idea, but the alternatives come with their own mess +} + PyColor::PyColor(sf::Color* target, std::weak_ptr parent, int index) { data.index = index; data.parent = parent; data.target = target; + data.setter = NULL; + data.getter = NULL; } PyColor::PyColor(sf::Color target) @@ -20,6 +28,18 @@ PyColor::PyColor(sf::Color target) data.index = PyColor::SELF_OWNED; data.parent = std::weak_ptr(); data.target = new sf::Color; + data.setter = NULL; + data.getter = NULL; +} + +PyColor::PyColor(sf::Color (*getter)(), void (*setter)(sf::Color), std::weak_ptr parent, int index) +{ + data.index = index; + data.parent = parent; + data.target = NULL; + data.setter = setter; + data.getter = getter; + } PyColor::~PyColor() @@ -31,32 +51,123 @@ PyColor::~PyColor() PyObject* PyColor::pyObject() { PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyColorType, 0); - ((PyColorObject*)obj->data = data; + PyColorObject* self = (PyColorObject*)obj; + self->data = data; + if (data.index == PyColor::SELF_OWNED) self->data.index = PyColor::BORROWED; return obj; } +PyColor PyColor::fromPy(PyObject* obj) +{ + PyColorObject* self = (PyColorObject*)obj; + return PyColor(self->data); +} + +PyColor PyColor::fromPy(PyColorObject* self) +{ + return PyColor(self->data); +} + +void PyColor::set(sf::Color color) +{ + auto ptr = data.parent.lock(); + if (ptr || data.index == PyColor::SELF_OWNED) + { + if (data.setter) + data.setter(color); + else + *data.target = color; + } +} + +sf::Color PyColor::get() +{ + auto ptr = data.parent.lock(); + if (ptr || data.index == PyColor::SELF_OWNED) + { + if (data.getter) + return data.getter(); + else + return *(data.target); + } + return sf::Color(0, 0, 0, 0); +} + +bool PyColor::alive() +{ + if (data.index == PyColor::SELF_OWNED) return true; + return !data.parent.lock(); +} + +std::string PyColor::field() +{ + switch (data.index) + { + case PyColor::SELF_OWNED: + return "None"; + break; + case 0: + return "fill"; + break; + case 1: + return "outline"; + break; + case 2: + return "background"; + break; + default: + return "unknown"; + break; + } +} + +std::string PyColor::mode() +{ + if (data.index == PyColor::SELF_OWNED) return "self-owned value"; + else if (data.index == PyColor::BORROWED) return "self-owned value (borrowed)"; + else if (data.getter || data.setter) + { + if (alive()) return "callback passthrough"; + else return "callback passthrough (dangling; parent dead)"; + } + else if (alive()) return "linked pointer"; + else return "linked pointer (dangling; parent dead)"; +} + Py_hash_t PyColor::hash(PyObject* obj) { auto self = (PyColorObject*)obj; Py_hash_t value = 0; - auto ptr = self.data.parent.lock(); + auto ptr = self->data.parent.lock(); if (ptr || self->data.index == PyColor::SELF_OWNED) { - value += self->data.target.r; - value << 8; value += self->data.target.g; - value << 8; value += self->data.target.b; - value << 8; value += self->data.target.a; + value += self->data.target->r; + value << 8; value += self->data.target->g; + value << 8; value += self->data.target->b; + value << 8; value += self->data.target->a; } if (ptr) { - - value << (sizeof(*UIDrawable) * 8); - value += reinterpret_cast(ptr); + //value << (sizeof(*UIDrawable) * 8); + value += reinterpret_cast(&ptr); } return value; } +PyObject* PyColor::repr(PyObject* obj) +{ + PyColorObject* self = (PyColorObject*)obj; + std::ostringstream ss; + PyColor color = PyColor(self->data); + sf::Color c = color.get(); + ss << ""; + + std::string repr_str = ss.str(); + return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace"); +} + + int PyColor::init(PyColorObject* self, PyObject* args, PyObject* kwds) { static const char* keywords[] = { "r", "g", "b", "a", nullptr }; @@ -67,3 +178,13 @@ PyObject* PyColor::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds) { return (PyObject*)type->tp_alloc(type, 0); } + +PyObject* PyColor::get_member(PyObject* obj, void* closure) +{ + return Py_None; +} + +int PyColor::set_member(PyObject* obj, PyObject* value, void* closure) +{ + return 0; +} diff --git a/src/PyColor.h b/src/PyColor.h index 28a40f3..6d0d35a 100644 --- a/src/PyColor.h +++ b/src/PyColor.h @@ -9,6 +9,8 @@ typedef struct { sf::Color* target; // color target to set/get std::weak_ptr parent; // lifetime management: parent must still exist int index; // specific to the parent class, which color is it? + sf::Color(*getter)(); + void(*setter)(sf::Color); } _PyColorData; typedef struct { @@ -21,16 +23,27 @@ class PyColor private: _PyColorData data; static const int SELF_OWNED = -1; + static const int BORROWED = -2; + PyColor(_PyColorData); // private constructor / for operations transferring between C++ and Python + public: PyColor(sf::Color* target, std::weak_ptr parent, int index); // linked constructor PyColor(sf::Color target); // simple color container - void set(sf::Color); - sf::Color get(); + PyColor(sf::Color (*)(), void (*)(sf::Color), std::weak_ptr, int); + ~PyColor(); + void set(sf::Color); // change target value, behavior determined by the mode + sf::Color get(); // retrieve target value, behavior determined by the mode + PyObject* pyParent(); // UIDrawable derived parent object or None + std::string field(); // interpret the index as a field's name on UIDrawable + std::string mode(); // "value" for SELF_OWNED, "linked" for pointer, and "passthrough" for callbacks + bool alive(); // true if SELF_OWNED or parent still exists PyObject* pyObject(); + static PyColor fromPy(PyObject*); + static PyColor fromPy(PyColorObject*); + static PyObject* repr(PyObject*); static Py_hash_t hash(PyObject*); static int init(PyColorObject*, PyObject*, PyObject*); static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL); - static PyObject* get_member(PyObject*, void*); static int set_member(PyObject*, PyObject*, void*); @@ -81,6 +94,7 @@ namespace mcrfpydef { .tp_name = "mcrfpy.Color", .tp_basicsize = sizeof(PyColorObject), .tp_itemsize = 0, + .tp_repr = PyColor::repr, .tp_hash = PyColor::hash, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = PyDoc_STR("SFML Color Object"), diff --git a/src/UI.h b/src/UI.h index 70a28f0..39d3e8b 100644 --- a/src/UI.h +++ b/src/UI.h @@ -617,7 +617,8 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c } // initialize new mcrfpy.Color instance - pyColorObj->data = std::make_shared(color); + //pyColorObj->data = std::make_shared(color); + PyColor::fromPy(pyColorObj).set(color); return pyColor; } @@ -630,11 +631,15 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c if (PyObject_IsInstance(value, (PyObject*)&PyColorType)) { // get value from mcrfpy.Color instance + /* PyColorObject* color = reinterpret_cast(value); r = color->data->r; g = color->data->g; b = color->data->b; a = color->data->a; + */ + sf::Color c = PyColor::fromPy(value).get(); + r = c.r; g = c.g; b = c.b; a = c.a; } else if (!PyTuple_Check(value) || PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4) { @@ -901,7 +906,8 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c } // initialize new mcrfpy.Color instance - pyColorObj->data = std::make_shared(color); + //pyColorObj->data = std::make_shared(color); + PyColor::fromPy(pyColorObj).set(color); return pyColor; } @@ -914,12 +920,16 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c if (PyObject_IsInstance(value, (PyObject*)&PyColorType)) { // get value from mcrfpy.Color instance + /* PyColorObject* color = reinterpret_cast(value); r = color->data->r; g = color->data->g; b = color->data->b; a = color->data->a; std::cout << "using color: " << r << " " << g << " " << b << " " << a << std::endl; + */ + sf::Color c = PyColor::fromPy(value).get(); + r = c.r; g = c.g; b = c.b; a = c.a; } else if (!PyTuple_Check(value) || PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4) { From 41509dfe9640a67f924c5f843fe6bceb0cdb8f78 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Wed, 27 Mar 2024 21:10:03 -0400 Subject: [PATCH 07/11] Addressing issues with PyColor by splitting behavior off into PyLinkedColor --- src/PyLinkedColor.cpp | 144 ++++++++++++++++++++++++++++++++++++++++++ src/PyLinkedColor.h | 58 +++++++++++++++++ src/UI.h | 34 ++++++---- 3 files changed, 225 insertions(+), 11 deletions(-) create mode 100644 src/PyLinkedColor.cpp create mode 100644 src/PyLinkedColor.h diff --git a/src/PyLinkedColor.cpp b/src/PyLinkedColor.cpp new file mode 100644 index 0000000..f349816 --- /dev/null +++ b/src/PyLinkedColor.cpp @@ -0,0 +1,144 @@ +#include "PyLinkedColor.h" + +PyGetSetDef PyLinkedColor::getsetters[] = { + {"r", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Red component", (void*)0}, + {"g", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Green component", (void*)1}, + {"b", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Blue component", (void*)2}, + {"a", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Alpha component", (void*)3}, + {NULL} +}; + +PyLinkedColor::PyLinkedColor(_PyLinkedColorData d) +{ + data = d; +} + +PyLinkedColor::PyLinkedColor(sf::Color (*getter)(), void (*setter)(sf::Color), std::weak_ptr parent, int index) +{ + data.index = index; + data.parent = parent; + data.setter = setter; + data.getter = getter; +} + +PyObject* PyLinkedColor::pyObject() +{ + PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyLinkedColorType, 0); + PyLinkedColorObject* self = (PyLinkedColorObject*)obj; + self->data = data; + return obj; +} + +PyLinkedColor PyLinkedColor::fromPy(PyObject* obj) +{ + PyLinkedColorObject* self = (PyLinkedColorObject*)obj; + return PyLinkedColor(self->data); +} + +PyLinkedColor PyLinkedColor::fromPy(PyLinkedColorObject* self) +{ + return PyLinkedColor(self->data); +} + +void PyLinkedColor::set(sf::Color color) +{ + auto ptr = data.parent.lock(); + if (ptr) + { + if (data.setter) + data.setter(color); + } +} + +sf::Color PyLinkedColor::get() +{ + auto ptr = data.parent.lock(); + if (ptr) + { + if (data.getter) + return data.getter(); + } + return sf::Color(0, 0, 0, 0); +} + +bool PyLinkedColor::alive() +{ + return !data.parent.lock(); +} + +std::string PyLinkedColor::field() +{ + switch (data.index) + { + case 0: + return "fill"; + break; + case 1: + return "outline"; + break; + case 2: + return "background"; + break; + default: + return "unknown"; + break; + } +} + +Py_hash_t PyLinkedColor::hash(PyObject* obj) +{ + auto self = (PyLinkedColorObject*)obj; + Py_hash_t value = 0; + auto ptr = self->data.parent.lock(); + if (ptr) + { + auto color = PyLinkedColor(self->data); + auto c = linkedcolor.get(); + value += c.r; + value << 8; value += c.g; + value << 8; value += c.b; + value << 8; value += c.a; + } + if (ptr) + { + //value << (sizeof(*UIDrawable) * 8); + value += reinterpret_cast(&ptr); + } + + return value; +} + +PyObject* PyLinkedColor::repr(PyObject* obj) +{ + PyLinkedColorObject* self = (PyLinkedColorObject*)obj; + std::ostringstream ss; + PyLinkedColor color = PyLinkedColor(self->data); + sf::Color c = color.get(); + ss << ""; + + std::string repr_str = ss.str(); + return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace"); +} + + +int PyLinkedColor::init(PyLinkedColorObject* self, PyObject* args, PyObject* kwds) +{ + // TODO + static const char* keywords[] = { "r", "g", "b", "a", nullptr }; + return 0; +} + +PyObject* PyLinkedColor::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds) +{ + return (PyObject*)type->tp_alloc(type, 0); +} + +PyObject* PyLinkedColor::get_member(PyObject* obj, void* closure) +{ + return Py_None; // TODO +} + +int PyLinkedColor::set_member(PyObject* obj, PyObject* value, void* closure) +{ + return 0; // TODO +} diff --git a/src/PyLinkedColor.h b/src/PyLinkedColor.h new file mode 100644 index 0000000..8b0d498 --- /dev/null +++ b/src/PyLinkedColor.h @@ -0,0 +1,58 @@ +#pragma once +#include "Common.h" +#include "Python.h" + +class PyLinkedColor; +class UIDrawable; // forward declare for pointer + +typedef struct { + std::weak_ptr parent; // lifetime management: parent must still exist + int index; // specific to the parent class, which color is it? + sf::Color(*getter)(); + void(*setter)(sf::Color); +} _PyLinkedColorData; + +typedef struct { + PyObject_HEAD + _PyLinkedColorData data; +} PyLinkedColorObject; + +class PyLinkedColor +{ +private: + _PyLinkedColorData data; + PyColor(_PyColorData); // private constructor / for operations transferring between C++ and Python + +public: + PyLinkedColor(sf::Color (*)(), void (*)(sf::Color), std::weak_ptr, int); + void set(sf::Color); // change target value, behavior determined by the mode + sf::Color get(); // retrieve target value, behavior determined by the mode + PyObject* pyParent(); // UIDrawable derived parent object or None + std::string field(); // interpret the index as a field's name on UIDrawable + bool alive(); // true if SELF_OWNED or parent still exists + PyObject* pyObject(); + static PyLinkedColor fromPy(PyObject*); + static PyLinkedColor fromPy(PyLinkedColorObject*); + static PyObject* repr(PyObject*); + static Py_hash_t hash(PyObject*); + static int init(PyLinkedColorObject*, PyObject*, PyObject*); + static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL); + static PyObject* get_member(PyObject*, void*); + static int set_member(PyObject*, PyObject*, void*); + static PyGetSetDef getsetters[]; +}; + +namespace mcrfpydef { + static PyTypeObject PyLinkedColorType = { + .tp_name = "mcrfpy.LinkedColor", + .tp_basicsize = sizeof(PyLinkedColorObject), + .tp_itemsize = 0, + .tp_repr = PyLinkedColor::repr, + .tp_hash = PyLinkedColor::hash, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = PyDoc_STR("SFML Color Object - Linked to UIDrawable Field"), + .tp_getset = PyLinkedColor::getsetters, + .tp_init = (initproc)PyLinkedColor::init, + .tp_new = PyLinkedColor::pynew, + }; +} diff --git a/src/UI.h b/src/UI.h index 39d3e8b..aa0b335 100644 --- a/src/UI.h +++ b/src/UI.h @@ -8,6 +8,7 @@ #include "PyCallable.h" #include "PyTexture.h" #include "PyColor.h" +#include "PyLinkedColor.h" enum PyObjectsEnum : int { @@ -594,33 +595,44 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c } // TODO: manually calling tp_alloc to create a PyColorObject seems like an antipattern - PyTypeObject* colorType = &PyColorType; - PyObject* pyColor = colorType->tp_alloc(colorType, 0); + /* + PyTypeObject* colorType = &PyLinkedColorType; + PyObject* pyColor = colorType->tp_alloc(colorLinkedType, 0); if (pyColor == NULL) { - std::cout << "failure to allocate mcrfpy.Color / PyColorType" << std::endl; + std::cout << "failure to allocate mcrfpy.LinkedColor / PyLinkedColorType" << std::endl; return NULL; } - PyColorObject* pyColorObj = reinterpret_cast(pyColor); + PyColorObject* pyColorObj = reinterpret_cast(pyColor); + */ // fetch correct member data - sf::Color color; + //sf::Color color; + sf::Color (*cgetter)(); + void (*csetter)(sf::Color); if (member_ptr == 0) { - color = self->data->text.getFillColor(); + //color = self->data->text.getFillColor(); //return Py_BuildValue("(iii)", color.r, color.g, color.b); + csetter = &self->data->text.setFillColor; + cgetter = &self->data->text.getFillColor; } else if (member_ptr == 1) { - color = self->data->text.getOutlineColor(); + //color = self->data->text.getOutlineColor(); //return Py_BuildValue("(iii)", color.r, color.g, color.b); + csetter = &self->data->text.setOutlineColor; + cgetter = &self->data->text.getOutlineColor; } // initialize new mcrfpy.Color instance //pyColorObj->data = std::make_shared(color); - PyColor::fromPy(pyColorObj).set(color); + //PyLinkedColor::fromPy(pyColorObj).set(color); + auto linkedcolor = PyLinkedColor(getter, setter, self->data, member_ptr); + //linkedcolor.set(color); // don't need to set a linked color! - return pyColor; + //return pyColor; + return linkedcolor.pyObject(); } static int PyUICaption_set_color_member(PyUICaptionObject* self, PyObject* value, void* closure) @@ -628,7 +640,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c auto member_ptr = reinterpret_cast(closure); //TODO: this logic of (PyColor instance OR tuple -> sf::color) should be encapsulated for reuse int r, g, b, a; - if (PyObject_IsInstance(value, (PyObject*)&PyColorType)) + if (PyObject_IsInstance(value, (PyObject*)&PyLinkedColorType)) { // get value from mcrfpy.Color instance /* @@ -638,7 +650,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c b = color->data->b; a = color->data->a; */ - sf::Color c = PyColor::fromPy(value).get(); + sf::Color c = PyLinkedColor::fromPy(value).get(); r = c.r; g = c.g; b = c.b; a = c.a; } else if (!PyTuple_Check(value) || PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4) From 06e24a1b27c2f1ec520537f3a5b9b08d68d07829 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Thu, 28 Mar 2024 20:53:49 -0400 Subject: [PATCH 08/11] LinkedColor now reflecting changes to the linked color value. Needs set method + RGBA / color properties --- src/McRFPy_API.cpp | 2 +- src/PyLinkedColor.cpp | 14 ++++++++------ src/PyLinkedColor.h | 12 ++++++++---- src/UI.h | 26 ++++++++++++++++++-------- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/McRFPy_API.cpp b/src/McRFPy_API.cpp index 51bd3c7..019ab74 100644 --- a/src/McRFPy_API.cpp +++ b/src/McRFPy_API.cpp @@ -56,7 +56,7 @@ PyObject* PyInit_mcrfpy() using namespace mcrfpydef; PyTypeObject* pytypes[] = { /*SFML exposed types*/ - &PyColorType, &PyFontType, &PyTextureType, + &PyColorType, &PyLinkedColorType, &PyFontType, &PyTextureType, /*UI widgets*/ &PyUICaptionType, &PyUISpriteType, &PyUIFrameType, &PyUIEntityType, &PyUIGridType, diff --git a/src/PyLinkedColor.cpp b/src/PyLinkedColor.cpp index f349816..d509ab8 100644 --- a/src/PyLinkedColor.cpp +++ b/src/PyLinkedColor.cpp @@ -13,12 +13,12 @@ PyLinkedColor::PyLinkedColor(_PyLinkedColorData d) data = d; } -PyLinkedColor::PyLinkedColor(sf::Color (*getter)(), void (*setter)(sf::Color), std::weak_ptr parent, int index) +PyLinkedColor::PyLinkedColor(std::function _s, std::function _g, std::weak_ptr parent, int index) { - data.index = index; + data.setter = _s; + data.getter = _g; data.parent = parent; - data.setter = setter; - data.getter = getter; + data.index = index; } PyObject* PyLinkedColor::pyObject() @@ -42,6 +42,7 @@ PyLinkedColor PyLinkedColor::fromPy(PyLinkedColorObject* self) void PyLinkedColor::set(sf::Color color) { + std::cout << "PyLinkedColor: call to set()" << std::endl; auto ptr = data.parent.lock(); if (ptr) { @@ -52,6 +53,7 @@ void PyLinkedColor::set(sf::Color color) sf::Color PyLinkedColor::get() { + std::cout << "PyLinkedColor: call to get()" << std::endl; auto ptr = data.parent.lock(); if (ptr) { @@ -92,7 +94,7 @@ Py_hash_t PyLinkedColor::hash(PyObject* obj) auto ptr = self->data.parent.lock(); if (ptr) { - auto color = PyLinkedColor(self->data); + auto linkedcolor = PyLinkedColor(self->data); auto c = linkedcolor.get(); value += c.r; value << 8; value += c.g; @@ -114,7 +116,7 @@ PyObject* PyLinkedColor::repr(PyObject* obj) std::ostringstream ss; PyLinkedColor color = PyLinkedColor(self->data); sf::Color c = color.get(); - ss << ""; + ss << ""; std::string repr_str = ss.str(); return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace"); diff --git a/src/PyLinkedColor.h b/src/PyLinkedColor.h index 8b0d498..f41331e 100644 --- a/src/PyLinkedColor.h +++ b/src/PyLinkedColor.h @@ -1,6 +1,7 @@ #pragma once #include "Common.h" #include "Python.h" +#include class PyLinkedColor; class UIDrawable; // forward declare for pointer @@ -8,8 +9,10 @@ class UIDrawable; // forward declare for pointer typedef struct { std::weak_ptr parent; // lifetime management: parent must still exist int index; // specific to the parent class, which color is it? - sf::Color(*getter)(); - void(*setter)(sf::Color); + //sf::Color(*getter)(); + //void(*setter)(sf::Color); + std::function setter; + std::function getter; } _PyLinkedColorData; typedef struct { @@ -21,10 +24,11 @@ class PyLinkedColor { private: _PyLinkedColorData data; - PyColor(_PyColorData); // private constructor / for operations transferring between C++ and Python + PyLinkedColor(_PyLinkedColorData); // private constructor / for operations transferring between C++ and Python public: - PyLinkedColor(sf::Color (*)(), void (*)(sf::Color), std::weak_ptr, int); + //PyLinkedColor(sf::Color (*)(), void (*)(sf::Color), std::weak_ptr, int); + PyLinkedColor(std::function setter, std::function getter, std::weak_ptr parent, int index); void set(sf::Color); // change target value, behavior determined by the mode sf::Color get(); // retrieve target value, behavior determined by the mode PyObject* pyParent(); // UIDrawable derived parent object or None diff --git a/src/UI.h b/src/UI.h index aa0b335..82610f0 100644 --- a/src/UI.h +++ b/src/UI.h @@ -608,27 +608,33 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c // fetch correct member data //sf::Color color; - sf::Color (*cgetter)(); - void (*csetter)(sf::Color); + //sf::Color (*cgetter)(); + //void (*csetter)(sf::Color); + std::function csetter; + std::function cgetter; if (member_ptr == 0) { //color = self->data->text.getFillColor(); //return Py_BuildValue("(iii)", color.r, color.g, color.b); - csetter = &self->data->text.setFillColor; - cgetter = &self->data->text.getFillColor; + //csetter = &self->data->text.setFillColor; + //cgetter = &self->data->text.getFillColor; + csetter = [s = self->data](sf::Color c){s->text.setFillColor(c);}; + cgetter = [s = self->data](){return s->text.getFillColor();}; } else if (member_ptr == 1) { //color = self->data->text.getOutlineColor(); //return Py_BuildValue("(iii)", color.r, color.g, color.b); - csetter = &self->data->text.setOutlineColor; - cgetter = &self->data->text.getOutlineColor; + //csetter = &self->data->text.setOutlineColor; + //cgetter = &self->data->text.getOutlineColor; + csetter = [s = self->data](sf::Color c){s->text.setOutlineColor(c);}; + cgetter = [s = self->data](){return s->text.getOutlineColor();}; } // initialize new mcrfpy.Color instance //pyColorObj->data = std::make_shared(color); //PyLinkedColor::fromPy(pyColorObj).set(color); - auto linkedcolor = PyLinkedColor(getter, setter, self->data, member_ptr); + auto linkedcolor = PyLinkedColor(csetter, cgetter, self->data, member_ptr); //linkedcolor.set(color); // don't need to set a linked color! //return pyColor; @@ -650,8 +656,12 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c b = color->data->b; a = color->data->a; */ - sf::Color c = PyLinkedColor::fromPy(value).get(); + std::cout << "Build LinkedColor" << std::endl; + auto lc = PyLinkedColor::fromPy(value); + std::cout << "Fetch value" << std::endl; + auto c = lc.get(); r = c.r; g = c.g; b = c.b; a = c.a; + std::cout << "got " << int(r) << ", " << int(g) << ", " << int(b) << ", " << int(a) << std::endl; } else if (!PyTuple_Check(value) || PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4) { From 3991ac13d6471e491cbccf2ddb8d36bad528b2f7 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Thu, 28 Mar 2024 23:50:50 -0400 Subject: [PATCH 09/11] Still having segfaults with LinkedColor and captions (specifically outline color, but that might not be the actual cause). PyColor shaping back up in simplified form. --- src/PyColor.cpp | 131 +++++------------------------------------- src/PyColor.h | 72 +++-------------------- src/PyLinkedColor.cpp | 71 +++++++++++++++++++++-- src/PyLinkedColor.h | 31 +++++++++- src/UI.h | 10 +++- src/scripts/game.py | 4 +- 6 files changed, 126 insertions(+), 193 deletions(-) diff --git a/src/PyColor.cpp b/src/PyColor.cpp index 9d001df..434a963 100644 --- a/src/PyColor.cpp +++ b/src/PyColor.cpp @@ -8,149 +8,46 @@ PyGetSetDef PyColor::getsetters[] = { {NULL} }; -PyColor::PyColor(_PyColorData d) -{ - data = d; - if (data.index == PyColor::SELF_OWNED) data.index = PyColor::BORROWED; // I think this is a bad idea, but the alternatives come with their own mess -} - -PyColor::PyColor(sf::Color* target, std::weak_ptr parent, int index) -{ - data.index = index; - data.parent = parent; - data.target = target; - data.setter = NULL; - data.getter = NULL; -} - PyColor::PyColor(sf::Color target) -{ - data.index = PyColor::SELF_OWNED; - data.parent = std::weak_ptr(); - data.target = new sf::Color; - data.setter = NULL; - data.getter = NULL; -} - -PyColor::PyColor(sf::Color (*getter)(), void (*setter)(sf::Color), std::weak_ptr parent, int index) -{ - data.index = index; - data.parent = parent; - data.target = NULL; - data.setter = setter; - data.getter = getter; - -} - -PyColor::~PyColor() -{ - if (data.index == PyColor::SELF_OWNED) - delete data.target; -} +:data(target) {} PyObject* PyColor::pyObject() { PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyColorType, 0); PyColorObject* self = (PyColorObject*)obj; self->data = data; - if (data.index == PyColor::SELF_OWNED) self->data.index = PyColor::BORROWED; return obj; } -PyColor PyColor::fromPy(PyObject* obj) +sf::Color PyColor::fromPy(PyObject* obj) { PyColorObject* self = (PyColorObject*)obj; - return PyColor(self->data); + return self->data; } -PyColor PyColor::fromPy(PyColorObject* self) +sf::Color PyColor::fromPy(PyColorObject* self) { - return PyColor(self->data); + return self->data; } void PyColor::set(sf::Color color) { - auto ptr = data.parent.lock(); - if (ptr || data.index == PyColor::SELF_OWNED) - { - if (data.setter) - data.setter(color); - else - *data.target = color; - } + data = color; } sf::Color PyColor::get() { - auto ptr = data.parent.lock(); - if (ptr || data.index == PyColor::SELF_OWNED) - { - if (data.getter) - return data.getter(); - else - return *(data.target); - } - return sf::Color(0, 0, 0, 0); -} - -bool PyColor::alive() -{ - if (data.index == PyColor::SELF_OWNED) return true; - return !data.parent.lock(); -} - -std::string PyColor::field() -{ - switch (data.index) - { - case PyColor::SELF_OWNED: - return "None"; - break; - case 0: - return "fill"; - break; - case 1: - return "outline"; - break; - case 2: - return "background"; - break; - default: - return "unknown"; - break; - } -} - -std::string PyColor::mode() -{ - if (data.index == PyColor::SELF_OWNED) return "self-owned value"; - else if (data.index == PyColor::BORROWED) return "self-owned value (borrowed)"; - else if (data.getter || data.setter) - { - if (alive()) return "callback passthrough"; - else return "callback passthrough (dangling; parent dead)"; - } - else if (alive()) return "linked pointer"; - else return "linked pointer (dangling; parent dead)"; + return data; } Py_hash_t PyColor::hash(PyObject* obj) { auto self = (PyColorObject*)obj; Py_hash_t value = 0; - auto ptr = self->data.parent.lock(); - if (ptr || self->data.index == PyColor::SELF_OWNED) - { - value += self->data.target->r; - value << 8; value += self->data.target->g; - value << 8; value += self->data.target->b; - value << 8; value += self->data.target->a; - } - if (ptr) - { - //value << (sizeof(*UIDrawable) * 8); - value += reinterpret_cast(&ptr); - } + value += self->data.r; + value << 8; value += self->data.g; + value << 8; value += self->data.b; + value << 8; value += self->data.a; return value; } @@ -159,9 +56,8 @@ PyObject* PyColor::repr(PyObject* obj) { PyColorObject* self = (PyColorObject*)obj; std::ostringstream ss; - PyColor color = PyColor(self->data); - sf::Color c = color.get(); - ss << ""; + sf::Color c = self->data; + ss << ""; std::string repr_str = ss.str(); return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace"); @@ -171,6 +67,7 @@ PyObject* PyColor::repr(PyObject* obj) int PyColor::init(PyColorObject* self, PyObject* args, PyObject* kwds) { static const char* keywords[] = { "r", "g", "b", "a", nullptr }; + // TODO return 0; } diff --git a/src/PyColor.h b/src/PyColor.h index 6d0d35a..a111b89 100644 --- a/src/PyColor.h +++ b/src/PyColor.h @@ -5,41 +5,22 @@ class PyColor; class UIDrawable; // forward declare for pointer -typedef struct { - sf::Color* target; // color target to set/get - std::weak_ptr parent; // lifetime management: parent must still exist - int index; // specific to the parent class, which color is it? - sf::Color(*getter)(); - void(*setter)(sf::Color); -} _PyColorData; - typedef struct { PyObject_HEAD - _PyColorData data; + sf::Color data; } PyColorObject; class PyColor { private: - _PyColorData data; - static const int SELF_OWNED = -1; - static const int BORROWED = -2; - PyColor(_PyColorData); // private constructor / for operations transferring between C++ and Python - public: - PyColor(sf::Color* target, std::weak_ptr parent, int index); // linked constructor - PyColor(sf::Color target); // simple color container - PyColor(sf::Color (*)(), void (*)(sf::Color), std::weak_ptr, int); - ~PyColor(); - void set(sf::Color); // change target value, behavior determined by the mode - sf::Color get(); // retrieve target value, behavior determined by the mode - PyObject* pyParent(); // UIDrawable derived parent object or None - std::string field(); // interpret the index as a field's name on UIDrawable - std::string mode(); // "value" for SELF_OWNED, "linked" for pointer, and "passthrough" for callbacks - bool alive(); // true if SELF_OWNED or parent still exists + sf::Color data; + PyColor(sf::Color); + void set(sf::Color); + sf::Color get(); PyObject* pyObject(); - static PyColor fromPy(PyObject*); - static PyColor fromPy(PyColorObject*); + static sf::Color fromPy(PyObject*); + static sf::Color fromPy(PyColorObject*); static PyObject* repr(PyObject*); static Py_hash_t hash(PyObject*); static int init(PyColorObject*, PyObject*, PyObject*); @@ -48,47 +29,8 @@ public: static int set_member(PyObject*, PyObject*, void*); static PyGetSetDef getsetters[]; - /*static PyGetSetDef getsetters[] = { - {"r", (getter)PyColor::get_member, (setter)PyColor::set_member, "Red component", (void*)0}, - {"g", (getter)PyColor::get_member, (setter)PyColor::set_member, "Green component", (void*)1}, - {"b", (getter)PyColor::get_member, (setter)PyColor::set_member, "Blue component", (void*)2}, - {"a", (getter)PyColor::get_member, (setter)PyColor::set_member, "Alpha component", (void*)3}, - {NULL} - };*/ }; - - -// static PyTypeObject PyColorType = { -// //PyVarObject_HEAD_INIT(NULL, 0) -// .tp_name = "mcrfpy.Color", -// .tp_basicsize = sizeof(PyColorObject), -// .tp_itemsize = 0, -// .tp_dealloc = (destructor)[](PyObject* self) -// { -// PyColorObject* obj = (PyColorObject*)self; -// obj->data.reset(); -// Py_TYPE(self)->tp_free(self); -// }, -// //.tp_repr = (reprfunc)PyUIFrame_repr, -// //.tp_hash = NULL, -// //.tp_iter -// //.tp_iternext -// .tp_flags = Py_TPFLAGS_DEFAULT, -// .tp_doc = PyDoc_STR("SFML Color object (RGBA)"), -// //.tp_methods = PyUIFrame_methods, -// //.tp_members = PyColor_members, -// .tp_getset = PyColor_getsetters, -// //.tp_base = NULL, -// //.tp_init = (initproc)PyUIFrame_init, -// .tp_new = [](PyTypeObject* type, PyObject* args, PyObject* kwds) -> PyObject* -// { -// PyColorObject* self = (PyColorObject*)type->tp_alloc(type, 0); -// if (self) self->data = std::make_shared(); -// return (PyObject*)self; -// } -// }; - namespace mcrfpydef { static PyTypeObject PyColorType = { .tp_name = "mcrfpy.Color", diff --git a/src/PyLinkedColor.cpp b/src/PyLinkedColor.cpp index d509ab8..cc0b02d 100644 --- a/src/PyLinkedColor.cpp +++ b/src/PyLinkedColor.cpp @@ -1,10 +1,12 @@ #include "PyLinkedColor.h" +#include "PyColor.h" PyGetSetDef PyLinkedColor::getsetters[] = { {"r", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Red component", (void*)0}, {"g", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Green component", (void*)1}, {"b", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Blue component", (void*)2}, {"a", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Alpha component", (void*)3}, + {"color", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "RGBA as mcrfpy.Color", (void*)4}, {NULL} }; @@ -116,19 +118,34 @@ PyObject* PyLinkedColor::repr(PyObject* obj) std::ostringstream ss; PyLinkedColor color = PyLinkedColor(self->data); sf::Color c = color.get(); - ss << ""; + ss << "data.parent.lock(); + if (!ptr) + { + ss << " [dead link]"; + } + else + { + switch (ptr->derived_type()) + { + case PyObjectsEnum::UIFRAME: + break; + } + } + ss << ">"; std::string repr_str = ss.str(); return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace"); } - +/* int PyLinkedColor::init(PyLinkedColorObject* self, PyObject* args, PyObject* kwds) { // TODO static const char* keywords[] = { "r", "g", "b", "a", nullptr }; return 0; } +*/ PyObject* PyLinkedColor::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds) { @@ -137,10 +154,56 @@ PyObject* PyLinkedColor::pynew(PyTypeObject* type, PyObject* args, PyObject* kwd PyObject* PyLinkedColor::get_member(PyObject* obj, void* closure) { - return Py_None; // TODO + PyLinkedColorObject* self = (PyLinkedColorObject*)obj; + PyLinkedColor color = PyLinkedColor(self->data); + sf::Color c = color.get(); + auto var = reinterpret_cast(closure); + + if (var == 0) + return PyLong_FromLong(c.r); + else if (var == 1) + return PyLong_FromLong(c.g); + else if (var == 2) + return PyLong_FromLong(c.b); + else if (var == 3) + return PyLong_FromLong(c.a); + else if (var == 4) + return PyColor(c).pyObject(); + return Py_None; } int PyLinkedColor::set_member(PyObject* obj, PyObject* value, void* closure) { - return 0; // TODO + PyLinkedColorObject* self = (PyLinkedColorObject*)obj; + PyLinkedColor color = PyLinkedColor(self->data); + sf::Color c = color.get(); + auto var = reinterpret_cast(closure); + + if (var == 4) + { + // cheat - call mcrfpy.Color __init__ on the value (don't duplicate arg parsing code) + PyObject* newcolor = PyType_GenericAlloc(&mcrfpydef::PyColorType, 0); + mcrfpydef::PyColorType.tp_init(newcolor, value, NULL); + if (PyErr_Occurred()) return -1; + auto newc = PyColor::fromPy(newcolor); + color.set(newc); + Py_DECREF(newcolor); + } + + long val = PyLong_AsLong(value); + if (PyErr_Occurred()) return -1; + if (val > 255 || val < 0) + { + PyErr_SetString(PyExc_ValueError, "Color values must be between 0 and 255"); + return -1; + } + if (var == 0) + color.set(sf::Color(val, c.g, c.b, c.a)); + else if (var == 1) + color.set(sf::Color(c.r, val, c.b, c.a)); + else if (var == 2) + color.set(sf::Color(c.r, c.g, val, c.a)); + else if (var == 3) + color.set(sf::Color(c.r, c.g, c.b, val)); + return 0; } diff --git a/src/PyLinkedColor.h b/src/PyLinkedColor.h index f41331e..e629c27 100644 --- a/src/PyLinkedColor.h +++ b/src/PyLinkedColor.h @@ -4,7 +4,34 @@ #include class PyLinkedColor; -class UIDrawable; // forward declare for pointer +//class UIDrawable; // forward declare for pointer +class PyClickCallable; + +// TODO - after UI.h gets broken up, this can go into a separate base class, since only derived classes use PyLinkedColor +#ifndef ui_h +enum PyObjectsEnum : int +{ + UIFRAME = 1, + UICAPTION, + UISPRITE, + UIGRID +}; + +class UIDrawable +{ +public: + void render(); + virtual void render(sf::Vector2f) = 0; + virtual PyObjectsEnum derived_type() = 0; + + std::unique_ptr click_callable; + virtual UIDrawable* click_at(sf::Vector2f point) = 0; + void click_register(PyObject*); + void click_unregister(); + + UIDrawable(); +}; +#endif typedef struct { std::weak_ptr parent; // lifetime management: parent must still exist @@ -56,7 +83,7 @@ namespace mcrfpydef { .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = PyDoc_STR("SFML Color Object - Linked to UIDrawable Field"), .tp_getset = PyLinkedColor::getsetters, - .tp_init = (initproc)PyLinkedColor::init, + //.tp_init = (initproc)PyLinkedColor::init, .tp_new = PyLinkedColor::pynew, }; } diff --git a/src/UI.h b/src/UI.h index 82610f0..384cfda 100644 --- a/src/UI.h +++ b/src/UI.h @@ -5,6 +5,9 @@ #include "IndexTexture.h" #include "Resources.h" #include + +#define ui_h + #include "PyCallable.h" #include "PyTexture.h" #include "PyColor.h" @@ -929,9 +932,10 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c // initialize new mcrfpy.Color instance //pyColorObj->data = std::make_shared(color); - PyColor::fromPy(pyColorObj).set(color); + //PyColor::fromPy(pyColorObj).set(color); - return pyColor; + // TODO - supposed to return Linked + return PyColor(color).pyObject(); } static int PyUIFrame_set_color_member(PyUIFrameObject* self, PyObject* value, void* closure) @@ -950,7 +954,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c a = color->data->a; std::cout << "using color: " << r << " " << g << " " << b << " " << a << std::endl; */ - sf::Color c = PyColor::fromPy(value).get(); + sf::Color c = ((PyColorObject*)value)->data; r = c.r; g = c.g; b = c.b; a = c.a; } else if (!PyTuple_Check(value) || PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4) diff --git a/src/scripts/game.py b/src/scripts/game.py index c022aca..2975588 100644 --- a/src/scripts/game.py +++ b/src/scripts/game.py @@ -130,7 +130,7 @@ logo_sprite = mcrfpy.Sprite(50, 50, logo_texture, 0, 0.5) ui.append(logo_sprite) logo_sprite.click = lambda *args: mcrfpy.setScene("menu") logo_caption = mcrfpy.Caption(70, 600, "Click to Proceed", font, (255, 0, 0, 255), (0, 0, 0, 255)) -logo_caption.fill_color =(255, 0, 0, 255) +#logo_caption.fill_color =(255, 0, 0, 255) ui.append(logo_caption) @@ -186,7 +186,7 @@ mcrfpy.createScene("settings") window_scaling = 1.0 scale_caption = mcrfpy.Caption(180, 70, "1.0x", font, (255, 255, 255), (0, 0, 0)) -scale_caption.fill_color = (255, 255, 255) # TODO - mcrfpy.Caption.__init__ is not setting colors +#scale_caption.fill_color = (255, 255, 255) # TODO - mcrfpy.Caption.__init__ is not setting colors for e in [ mcrfpy.Caption(10, 10, "Settings", font, (255, 255, 255), (0, 0, 0)), mcrfpy.Frame(15, 70, 150, 60, fill_color=(64, 64, 128)), # + From 01706bd59d9b62fe1ea8f8dcce0929da738490dd Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 30 Mar 2024 21:13:31 -0400 Subject: [PATCH 10/11] Color wrapup... Cutting PyLinkedColor to simplify my cursedly mortal, finite existence --- src/McRFPy_API.cpp | 2 +- src/PyColor.cpp | 68 ++++++++++- src/UI.h | 35 +++--- src/scripts/game.py | 246 +++++++--------------------------------- src/scripts/game_old.py | 221 ++++++++++++++++++++++++++++++++++++ 5 files changed, 344 insertions(+), 228 deletions(-) create mode 100644 src/scripts/game_old.py diff --git a/src/McRFPy_API.cpp b/src/McRFPy_API.cpp index 019ab74..e5621f0 100644 --- a/src/McRFPy_API.cpp +++ b/src/McRFPy_API.cpp @@ -56,7 +56,7 @@ PyObject* PyInit_mcrfpy() using namespace mcrfpydef; PyTypeObject* pytypes[] = { /*SFML exposed types*/ - &PyColorType, &PyLinkedColorType, &PyFontType, &PyTextureType, + &PyColorType, /*&PyLinkedColorType,*/ &PyFontType, &PyTextureType, /*UI widgets*/ &PyUICaptionType, &PyUISpriteType, &PyUIFrameType, &PyUIEntityType, &PyUIGridType, diff --git a/src/PyColor.cpp b/src/PyColor.cpp index 434a963..50eae73 100644 --- a/src/PyColor.cpp +++ b/src/PyColor.cpp @@ -14,6 +14,7 @@ PyColor::PyColor(sf::Color target) PyObject* PyColor::pyObject() { PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyColorType, 0); + Py_INCREF(obj); PyColorObject* self = (PyColorObject*)obj; self->data = data; return obj; @@ -57,7 +58,7 @@ PyObject* PyColor::repr(PyObject* obj) PyColorObject* self = (PyColorObject*)obj; std::ostringstream ss; sf::Color c = self->data; - ss << ""; + ss << ""; std::string repr_str = ss.str(); return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace"); @@ -66,8 +67,69 @@ PyObject* PyColor::repr(PyObject* obj) int PyColor::init(PyColorObject* self, PyObject* args, PyObject* kwds) { + using namespace mcrfpydef; static const char* keywords[] = { "r", "g", "b", "a", nullptr }; - // TODO + PyObject* leader; + int r = -1, g = -1, b = -1, a = 255; + if (!PyArg_ParseTupleAndKeywords, args, kwds, "O|iii", leader, &g, &b, &a) + { + PyErr_SetString(PyExc_TypeError, "mcrfpy.Color requires a color object, 3-tuple, 4-tuple, color name, or integer values within 0-255 (r, g, b, optionally a)"); + return -1; + } + + // if the "r" arg is already a color, yoink that color value + if (PyObject_IsInstance(leader, (PyObject*)&PyColorType)) + { + self->data = ((PyColorObject*)leader)->data; + return 0; + } + // else if the "r" arg is a 3-tuple, initialize to (r, g, b, 255) + // (if the "r" arg is a 4-tuple, initialize to (r, g, b, a)) + else if (PyTuple_Check(leader)) + { + if (PyTuple_Size(leader) < 3 && PyTuple_Size(leader) > 4) + { + PyErr_SetString(PyExc_TypeError, "Invalid tuple length: mcrfpy.Color requires a color object, 3-tuple, 4-tuple, color name, or integer values within 0-255 (r, g, b, optionally a)"); + return -1; + } + r = PyLong_AsLong(PyTuple_GetItem(leader, 0)); + g = PyLong_AsLong(PyTuple_GetItem(leader, 1)); + b = PyLong_AsLong(PyTuple_GetItem(leader, 2)); + //a = 255; //default value + + if (PyTuple_Size(leader) == 4) + { + a = PyLong_AsLong(PyTuple_GetItem(leader, 3)); + } + + // value validation + if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 || a < 0 || a > 255) + { + PyErr_SetString(PyExc_ValueError, "Color values must be between 0 and 255."); + return -1; + } + self->data = sf::Color(r, g, b, a); + } + // else if the "r" arg is a string, initialize to {color lookup function value} + else if (PyUnicode_Check(leader)) + { + PyErr_SetString(Py_NotImplemented, "Color names aren't ready yet"); + return -1; + } + // else - + else if (!PyLong_Check(leader)) + { + PyErr_SetString(PyExc_TypeError, "mcrfpy.Color requires a color object, 3-tuple, 4-tuple, color name, or integer values within 0-255 (r, g, b, optionally a)"); + return -1; + } + r = PyLong_AsLong(leader); + // assert r, g, b are present and ints in range (0, 255) - if not enough ints were provided to the args/kwds parsed by init, g and/or b will still hold -1. + if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 || a < 0 || a > 255) + { + PyErr_SetString(PyExc_ValueError, "R, G, B values are required, A value is optional; Color values must be between 0 and 255."); + return -1; + } + self->data = sf::Color(r, g, b, a); return 0; } @@ -78,10 +140,12 @@ PyObject* PyColor::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds) PyObject* PyColor::get_member(PyObject* obj, void* closure) { + // TODO return Py_None; } int PyColor::set_member(PyObject* obj, PyObject* value, void* closure) { + // TODO return 0; } diff --git a/src/UI.h b/src/UI.h index 384cfda..f0f64db 100644 --- a/src/UI.h +++ b/src/UI.h @@ -11,7 +11,7 @@ #include "PyCallable.h" #include "PyTexture.h" #include "PyColor.h" -#include "PyLinkedColor.h" +//#include "PyLinkedColor.h" enum PyObjectsEnum : int { @@ -610,38 +610,38 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c */ // fetch correct member data - //sf::Color color; + sf::Color color; //sf::Color (*cgetter)(); //void (*csetter)(sf::Color); - std::function csetter; - std::function cgetter; + //std::function csetter; + //std::function cgetter; if (member_ptr == 0) { - //color = self->data->text.getFillColor(); + color = self->data->text.getFillColor(); //return Py_BuildValue("(iii)", color.r, color.g, color.b); //csetter = &self->data->text.setFillColor; //cgetter = &self->data->text.getFillColor; - csetter = [s = self->data](sf::Color c){s->text.setFillColor(c);}; - cgetter = [s = self->data](){return s->text.getFillColor();}; + //csetter = [s = self->data](sf::Color c){s->text.setFillColor(c);}; + //cgetter = [s = self->data](){return s->text.getFillColor();}; } else if (member_ptr == 1) { - //color = self->data->text.getOutlineColor(); + color = self->data->text.getOutlineColor(); //return Py_BuildValue("(iii)", color.r, color.g, color.b); //csetter = &self->data->text.setOutlineColor; //cgetter = &self->data->text.getOutlineColor; - csetter = [s = self->data](sf::Color c){s->text.setOutlineColor(c);}; - cgetter = [s = self->data](){return s->text.getOutlineColor();}; + //csetter = [s = self->data](sf::Color c){s->text.setOutlineColor(c);}; + //cgetter = [s = self->data](){return s->text.getOutlineColor();}; } // initialize new mcrfpy.Color instance //pyColorObj->data = std::make_shared(color); //PyLinkedColor::fromPy(pyColorObj).set(color); - auto linkedcolor = PyLinkedColor(csetter, cgetter, self->data, member_ptr); + //auto linkedcolor = PyLinkedColor(csetter, cgetter, self->data, member_ptr); //linkedcolor.set(color); // don't need to set a linked color! //return pyColor; - return linkedcolor.pyObject(); + return PyColor(color).pyObject(); } static int PyUICaption_set_color_member(PyUICaptionObject* self, PyObject* value, void* closure) @@ -649,7 +649,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c auto member_ptr = reinterpret_cast(closure); //TODO: this logic of (PyColor instance OR tuple -> sf::color) should be encapsulated for reuse int r, g, b, a; - if (PyObject_IsInstance(value, (PyObject*)&PyLinkedColorType)) + if (PyObject_IsInstance(value, (PyObject*)&PyColorType)) { // get value from mcrfpy.Color instance /* @@ -659,10 +659,11 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c b = color->data->b; a = color->data->a; */ - std::cout << "Build LinkedColor" << std::endl; - auto lc = PyLinkedColor::fromPy(value); - std::cout << "Fetch value" << std::endl; - auto c = lc.get(); + //std::cout << "Build LinkedColor" << std::endl; + //auto lc = PyLinkedColor::fromPy(value); + auto c = ((PyColorObject*)value)->data; + //std::cout << "Fetch value" << std::endl; + //auto c = lc.get(); r = c.r; g = c.g; b = c.b; a = c.a; std::cout << "got " << int(r) << ", " << int(g) << ", " << int(b) << ", " << int(a) << std::endl; } diff --git a/src/scripts/game.py b/src/scripts/game.py index 2975588..8e28bc3 100644 --- a/src/scripts/game.py +++ b/src/scripts/game.py @@ -1,221 +1,51 @@ -#print("Hello mcrogueface") import mcrfpy -import cos_play -# Universal stuff font = mcrfpy.Font("assets/JetbrainsMono.ttf") -texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16) #12, 11) -texture_cold = mcrfpy.Texture("assets/kenney_ice.png", 16, 16) #12, 11) -texture_hot = mcrfpy.Texture("assets/kenney_lava.png", 16, 16) #12, 11) +texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16) -# Test stuff -mcrfpy.createScene("boom") -mcrfpy.setScene("boom") -ui = mcrfpy.sceneUI("boom") -box = mcrfpy.Frame(40, 60, 200, 300, fill_color=(255,128,0), outline=4.0, outline_color=(64,64,255,96)) -ui.append(box) +# build test widgets -#caption = mcrfpy.Caption(10, 10, "Clicky", font, (255, 255, 255, 255), (0, 0, 0, 255)) -#box.click = lambda x, y, btn, type: print("Hello callback: ", x, y, btn, type) -#box.children.append(caption) +mcrfpy.createScene("pytest") +mcrfpy.setScene("pytest") +ui = mcrfpy.sceneUI("pytest") -test_sprite_number = 86 -sprite = mcrfpy.Sprite(20, 60, texture, test_sprite_number, 4.0) -spritecap = mcrfpy.Caption(5, 5, "60", font) -def click_sprite(x, y, btn, action): - global test_sprite_number - if action != "start": return - if btn in ("left", "wheel_up"): - test_sprite_number -= 1 - elif btn in ("right", "wheel_down"): - test_sprite_number += 1 - sprite.sprite_number = test_sprite_number # TODO - inconsistent naming for __init__, __repr__ and getsetter: sprite_number vs sprite_index - spritecap.text = test_sprite_number +# Frame +f = mcrfpy.Frame(25, 19, 462, 346, fill_color=(255, 92, 92)) +# fill (LinkedColor / Color): f.fill_color +# outline (LinkedColor / Color): f.outline_color +# pos (LinkedVector / Vector): f.pos +# size (LinkedVector / Vector): f.size -sprite.click = click_sprite # TODO - sprites don't seem to correct for screen position or scale when clicking -box.children.append(sprite) -box.children.append(spritecap) -box.click = click_sprite +# Caption +c = mcrfpy.Caption(512+25, 19, "Hi.", font) +# fill (LinkedColor / Color): c.fill_color +#color_val = c.fill_color +print(c.fill_color) +print("Set a fill color") +c.fill_color = (255, 255, 255) +print("Lol, did it segfault?") +# outline (LinkedColor / Color): c.outline_color +# font (Font): c.font +# pos (LinkedVector / Vector): c.pos -f_a = mcrfpy.Frame(250, 60, 80, 80, fill_color=(255, 92, 92)) -f_a_txt = mcrfpy.Caption(5, 5, "0", font) +# Sprite +s = mcrfpy.Sprite(25, 384+19, texture, 86, 9.0) +# pos (LinkedVector / Vector): s.pos +# texture (Texture): s.texture -f_b = mcrfpy.Frame(340, 60, 80, 80, fill_color=(92, 255, 92)) -f_b_txt = mcrfpy.Caption(5, 5, "0", font) +# Grid +g = mcrfpy.Grid(10, 10, texture, 512+25, 384+19, 462, 346) +# texture (Texture): g.texture +# pos (LinkedVector / Vector): g.pos +# size (LinkedVector / Vector): g.size -f_c = mcrfpy.Frame(430, 60, 80, 80, fill_color=(92, 92, 255)) -f_c_txt = mcrfpy.Caption(5, 5, "0", font) +for _x in range(10): + for _y in range(10): + g.at((_x, _y)).color = (255 - _x*25, 255 - _y*25, 255) +g.zoom = 2.0 +[ui.append(d) for d in (f, c, s, g)] -ui.append(f_a) -f_a.children.append(f_a_txt) -ui.append(f_b) -f_b.children.append(f_b_txt) -ui.append(f_c) -f_c.children.append(f_c_txt) +print("built!") -import sys -def ding(*args): - f_a_txt.text = str(sys.getrefcount(ding)) + " refs" - f_b_txt.text = sys.getrefcount(dong) - f_c_txt.text = sys.getrefcount(stress_test) +# tests -def dong(*args): - f_a_txt.text = str(sys.getrefcount(ding)) + " refs" - f_b_txt.text = sys.getrefcount(dong) - f_c_txt.text = sys.getrefcount(stress_test) - -running = False -timers = [] - -def add_ding(): - global timers - n = len(timers) - mcrfpy.setTimer(f"timer{n}", ding, 100) - print("+1 ding:", timers) - -def add_dong(): - global timers - n = len(timers) - mcrfpy.setTimer(f"timer{n}", dong, 100) - print("+1 dong:", timers) - -def remove_random(): - global timers - target = random.choice(timers) - print("-1 timer:", target) - print("remove from list") - timers.remove(target) - print("delTimer") - mcrfpy.delTimer(target) - print("done") - -import random -import time -def stress_test(*args): - global running - global timers - if not running: - print("stress test initial") - running = True - timers.append("recurse") - add_ding() - add_dong() - mcrfpy.setTimer("recurse", stress_test, 1000) - mcrfpy.setTimer("terminate", lambda *args: mcrfpy.delTimer("recurse"), 30000) - ding(); dong() - else: - #print("stress test random activity") - #random.choice([ - # add_ding, - # add_dong, - # remove_random - # ])() - #print(timers) - print("Segfaultin' time") - mcrfpy.delTimer("recurse") - print("Does this still work?") - time.sleep(0.5) - print("How about now?") - - -stress_test() - - -# Loading Screen -mcrfpy.createScene("loading") -ui = mcrfpy.sceneUI("loading") -#mcrfpy.setScene("loading") -logo_texture = mcrfpy.Texture("assets/temp_logo.png", 1024, 1024)#1, 1) -logo_sprite = mcrfpy.Sprite(50, 50, logo_texture, 0, 0.5) -ui.append(logo_sprite) -logo_sprite.click = lambda *args: mcrfpy.setScene("menu") -logo_caption = mcrfpy.Caption(70, 600, "Click to Proceed", font, (255, 0, 0, 255), (0, 0, 0, 255)) -#logo_caption.fill_color =(255, 0, 0, 255) -ui.append(logo_caption) - - -# menu screen -mcrfpy.createScene("menu") - -for e in [ - mcrfpy.Caption(10, 10, "Crypt of Sokoban", font, (255, 255, 255), (0, 0, 0)), - mcrfpy.Caption(20, 55, "a McRogueFace demo project", font, (192, 192, 192), (0, 0, 0)), - mcrfpy.Frame(15, 70, 150, 60, fill_color=(64, 64, 128)), - mcrfpy.Frame(15, 145, 150, 60, fill_color=(64, 64, 128)), - mcrfpy.Frame(15, 220, 150, 60, fill_color=(64, 64, 128)), - mcrfpy.Frame(15, 295, 150, 60, fill_color=(64, 64, 128)), - #mcrfpy.Frame(900, 10, 100, 100, fill_color=(255, 0, 0)), - ]: - mcrfpy.sceneUI("menu").append(e) - -def click_once(fn): - def wraps(*args, **kwargs): - #print(args) - action = args[3] - if action != "start": return - return fn(*args, **kwargs) - return wraps - -@click_once -def asdf(x, y, btn, action): - print(f"clicky @({x},{y}) {action}->{btn}") - -@click_once -def clicked_exit(*args): - mcrfpy.exit() - -menu_btns = [ - ("Boom", lambda *args: 1 / 0), - ("Exit", clicked_exit), - ("About", lambda *args: mcrfpy.setScene("about")), - ("Settings", lambda *args: mcrfpy.setScene("settings")), - ("Start", lambda *args: mcrfpy.setScene("play")) - ] -for i in range(len(mcrfpy.sceneUI("menu"))): - e = mcrfpy.sceneUI("menu")[i] # TODO - fix iterator - #print(e, type(e)) - if type(e) is not mcrfpy.Frame: continue - label, fn = menu_btns.pop() - #print(label) - e.children.append(mcrfpy.Caption(5, 5, label, font, (192, 192, 255), (0,0,0))) - e.click = fn - - -# settings screen -mcrfpy.createScene("settings") -window_scaling = 1.0 - -scale_caption = mcrfpy.Caption(180, 70, "1.0x", font, (255, 255, 255), (0, 0, 0)) -#scale_caption.fill_color = (255, 255, 255) # TODO - mcrfpy.Caption.__init__ is not setting colors -for e in [ - mcrfpy.Caption(10, 10, "Settings", font, (255, 255, 255), (0, 0, 0)), - mcrfpy.Frame(15, 70, 150, 60, fill_color=(64, 64, 128)), # + - mcrfpy.Frame(300, 70, 150, 60, fill_color=(64, 64, 128)), # - - mcrfpy.Frame(15, 295, 150, 60, fill_color=(64, 64, 128)), - scale_caption, - ]: - mcrfpy.sceneUI("settings").append(e) - -@click_once -def game_scale(x, y, btn, action, delta): - global window_scaling - print(f"WIP - scale the window from {window_scaling:.1f} to {window_scaling+delta:.1f}") - window_scaling += delta - scale_caption.text = f"{window_scaling:.1f}x" - mcrfpy.setScale(window_scaling) - #mcrfpy.setScale(2) - -settings_btns = [ - ("back", lambda *args: mcrfpy.setScene("menu")), - ("-", lambda x, y, btn, action: game_scale(x, y, btn, action, -0.1)), - ("+", lambda x, y, btn, action: game_scale(x, y, btn, action, +0.1)) - ] - -for i in range(len(mcrfpy.sceneUI("settings"))): - e = mcrfpy.sceneUI("settings")[i] # TODO - fix iterator - #print(e, type(e)) - if type(e) is not mcrfpy.Frame: continue - label, fn = settings_btns.pop() - #print(label, fn) - e.children.append(mcrfpy.Caption(5, 5, label, font, (192, 192, 255), (0,0,0))) - e.click = fn diff --git a/src/scripts/game_old.py b/src/scripts/game_old.py new file mode 100644 index 0000000..2975588 --- /dev/null +++ b/src/scripts/game_old.py @@ -0,0 +1,221 @@ +#print("Hello mcrogueface") +import mcrfpy +import cos_play +# Universal stuff +font = mcrfpy.Font("assets/JetbrainsMono.ttf") +texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16) #12, 11) +texture_cold = mcrfpy.Texture("assets/kenney_ice.png", 16, 16) #12, 11) +texture_hot = mcrfpy.Texture("assets/kenney_lava.png", 16, 16) #12, 11) + +# Test stuff +mcrfpy.createScene("boom") +mcrfpy.setScene("boom") +ui = mcrfpy.sceneUI("boom") +box = mcrfpy.Frame(40, 60, 200, 300, fill_color=(255,128,0), outline=4.0, outline_color=(64,64,255,96)) +ui.append(box) + +#caption = mcrfpy.Caption(10, 10, "Clicky", font, (255, 255, 255, 255), (0, 0, 0, 255)) +#box.click = lambda x, y, btn, type: print("Hello callback: ", x, y, btn, type) +#box.children.append(caption) + +test_sprite_number = 86 +sprite = mcrfpy.Sprite(20, 60, texture, test_sprite_number, 4.0) +spritecap = mcrfpy.Caption(5, 5, "60", font) +def click_sprite(x, y, btn, action): + global test_sprite_number + if action != "start": return + if btn in ("left", "wheel_up"): + test_sprite_number -= 1 + elif btn in ("right", "wheel_down"): + test_sprite_number += 1 + sprite.sprite_number = test_sprite_number # TODO - inconsistent naming for __init__, __repr__ and getsetter: sprite_number vs sprite_index + spritecap.text = test_sprite_number + +sprite.click = click_sprite # TODO - sprites don't seem to correct for screen position or scale when clicking +box.children.append(sprite) +box.children.append(spritecap) +box.click = click_sprite + +f_a = mcrfpy.Frame(250, 60, 80, 80, fill_color=(255, 92, 92)) +f_a_txt = mcrfpy.Caption(5, 5, "0", font) + +f_b = mcrfpy.Frame(340, 60, 80, 80, fill_color=(92, 255, 92)) +f_b_txt = mcrfpy.Caption(5, 5, "0", font) + +f_c = mcrfpy.Frame(430, 60, 80, 80, fill_color=(92, 92, 255)) +f_c_txt = mcrfpy.Caption(5, 5, "0", font) + + +ui.append(f_a) +f_a.children.append(f_a_txt) +ui.append(f_b) +f_b.children.append(f_b_txt) +ui.append(f_c) +f_c.children.append(f_c_txt) + +import sys +def ding(*args): + f_a_txt.text = str(sys.getrefcount(ding)) + " refs" + f_b_txt.text = sys.getrefcount(dong) + f_c_txt.text = sys.getrefcount(stress_test) + +def dong(*args): + f_a_txt.text = str(sys.getrefcount(ding)) + " refs" + f_b_txt.text = sys.getrefcount(dong) + f_c_txt.text = sys.getrefcount(stress_test) + +running = False +timers = [] + +def add_ding(): + global timers + n = len(timers) + mcrfpy.setTimer(f"timer{n}", ding, 100) + print("+1 ding:", timers) + +def add_dong(): + global timers + n = len(timers) + mcrfpy.setTimer(f"timer{n}", dong, 100) + print("+1 dong:", timers) + +def remove_random(): + global timers + target = random.choice(timers) + print("-1 timer:", target) + print("remove from list") + timers.remove(target) + print("delTimer") + mcrfpy.delTimer(target) + print("done") + +import random +import time +def stress_test(*args): + global running + global timers + if not running: + print("stress test initial") + running = True + timers.append("recurse") + add_ding() + add_dong() + mcrfpy.setTimer("recurse", stress_test, 1000) + mcrfpy.setTimer("terminate", lambda *args: mcrfpy.delTimer("recurse"), 30000) + ding(); dong() + else: + #print("stress test random activity") + #random.choice([ + # add_ding, + # add_dong, + # remove_random + # ])() + #print(timers) + print("Segfaultin' time") + mcrfpy.delTimer("recurse") + print("Does this still work?") + time.sleep(0.5) + print("How about now?") + + +stress_test() + + +# Loading Screen +mcrfpy.createScene("loading") +ui = mcrfpy.sceneUI("loading") +#mcrfpy.setScene("loading") +logo_texture = mcrfpy.Texture("assets/temp_logo.png", 1024, 1024)#1, 1) +logo_sprite = mcrfpy.Sprite(50, 50, logo_texture, 0, 0.5) +ui.append(logo_sprite) +logo_sprite.click = lambda *args: mcrfpy.setScene("menu") +logo_caption = mcrfpy.Caption(70, 600, "Click to Proceed", font, (255, 0, 0, 255), (0, 0, 0, 255)) +#logo_caption.fill_color =(255, 0, 0, 255) +ui.append(logo_caption) + + +# menu screen +mcrfpy.createScene("menu") + +for e in [ + mcrfpy.Caption(10, 10, "Crypt of Sokoban", font, (255, 255, 255), (0, 0, 0)), + mcrfpy.Caption(20, 55, "a McRogueFace demo project", font, (192, 192, 192), (0, 0, 0)), + mcrfpy.Frame(15, 70, 150, 60, fill_color=(64, 64, 128)), + mcrfpy.Frame(15, 145, 150, 60, fill_color=(64, 64, 128)), + mcrfpy.Frame(15, 220, 150, 60, fill_color=(64, 64, 128)), + mcrfpy.Frame(15, 295, 150, 60, fill_color=(64, 64, 128)), + #mcrfpy.Frame(900, 10, 100, 100, fill_color=(255, 0, 0)), + ]: + mcrfpy.sceneUI("menu").append(e) + +def click_once(fn): + def wraps(*args, **kwargs): + #print(args) + action = args[3] + if action != "start": return + return fn(*args, **kwargs) + return wraps + +@click_once +def asdf(x, y, btn, action): + print(f"clicky @({x},{y}) {action}->{btn}") + +@click_once +def clicked_exit(*args): + mcrfpy.exit() + +menu_btns = [ + ("Boom", lambda *args: 1 / 0), + ("Exit", clicked_exit), + ("About", lambda *args: mcrfpy.setScene("about")), + ("Settings", lambda *args: mcrfpy.setScene("settings")), + ("Start", lambda *args: mcrfpy.setScene("play")) + ] +for i in range(len(mcrfpy.sceneUI("menu"))): + e = mcrfpy.sceneUI("menu")[i] # TODO - fix iterator + #print(e, type(e)) + if type(e) is not mcrfpy.Frame: continue + label, fn = menu_btns.pop() + #print(label) + e.children.append(mcrfpy.Caption(5, 5, label, font, (192, 192, 255), (0,0,0))) + e.click = fn + + +# settings screen +mcrfpy.createScene("settings") +window_scaling = 1.0 + +scale_caption = mcrfpy.Caption(180, 70, "1.0x", font, (255, 255, 255), (0, 0, 0)) +#scale_caption.fill_color = (255, 255, 255) # TODO - mcrfpy.Caption.__init__ is not setting colors +for e in [ + mcrfpy.Caption(10, 10, "Settings", font, (255, 255, 255), (0, 0, 0)), + mcrfpy.Frame(15, 70, 150, 60, fill_color=(64, 64, 128)), # + + mcrfpy.Frame(300, 70, 150, 60, fill_color=(64, 64, 128)), # - + mcrfpy.Frame(15, 295, 150, 60, fill_color=(64, 64, 128)), + scale_caption, + ]: + mcrfpy.sceneUI("settings").append(e) + +@click_once +def game_scale(x, y, btn, action, delta): + global window_scaling + print(f"WIP - scale the window from {window_scaling:.1f} to {window_scaling+delta:.1f}") + window_scaling += delta + scale_caption.text = f"{window_scaling:.1f}x" + mcrfpy.setScale(window_scaling) + #mcrfpy.setScale(2) + +settings_btns = [ + ("back", lambda *args: mcrfpy.setScene("menu")), + ("-", lambda x, y, btn, action: game_scale(x, y, btn, action, -0.1)), + ("+", lambda x, y, btn, action: game_scale(x, y, btn, action, +0.1)) + ] + +for i in range(len(mcrfpy.sceneUI("settings"))): + e = mcrfpy.sceneUI("settings")[i] # TODO - fix iterator + #print(e, type(e)) + if type(e) is not mcrfpy.Frame: continue + label, fn = settings_btns.pop() + #print(label, fn) + e.children.append(mcrfpy.Caption(5, 5, label, font, (192, 192, 255), (0,0,0))) + e.click = fn From 572aa526058ae012f622393eae01c65cbc8dc05e Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 30 Mar 2024 21:18:26 -0400 Subject: [PATCH 11/11] More color table updates --- generate_color_table.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/generate_color_table.py b/generate_color_table.py index fb0d411..43fa4de 100644 --- a/generate_color_table.py +++ b/generate_color_table.py @@ -73,4 +73,39 @@ for p in palettes: print(f"{prefix}->{len(all_colors)}") for c in all_colors: - c.nn(all_colors) \ No newline at end of file + c.nn(all_colors) + +smallest_dist = 9999999999999 +largest_dist = 0 +for c in all_colors: + dist = rgbdist(c, c.nearest_neighbor) + if dist > largest_dist: largest_dist = dist + if dist < smallest_dist: smallest_dist = dist + #print(f"{c.prefix}:{c.name} -> {c.nearest_neighbor.prefix}:{c.nearest_neighbor.name}\t{rgbdist(c, c.nearest_neighbor):.2f}") +# questions - + +# are there any colors where their nearest neighbor's nearest neighbor isn't them? (There should be) +nonnear_pairs = 0 +for c in all_colors: + neighbor = c.nearest_neighbor + their_neighbor = neighbor.nearest_neighbor + if c is not their_neighbor: + #print(f"{c.prefix}:{c.name} -> {neighbor.prefix}:{neighbor.name} -> {their_neighbor.prefix}:{their_neighbor.name}") + nonnear_pairs += 1 +print("Non-near pairs:", nonnear_pairs) + #print(f"{c.prefix}:{c.name} -> {c.nearest_neighbor.prefix}:{c.nearest_neighbor.name}\t{rgbdist(c, c.nearest_neighbor):.2f}") + +# Are there duplicates? They should be removed from the palette that won't be used +dupes = 0 +for c in all_colors: + for c2 in all_colors: + if c is c2: continue + if c.r == c2.r and c.g == c2.g and c.b == c2.b: + dupes += 1 +print("dupes:", dupes, "this many will need to be removed:", dupes / 2) + +# What order to put them in? Do we want large radiuses first, or some sort of "common color" table? + +# does manhattan distance change any answers over the 16.7M RGB values? + +# What's the worst case lookup? (Checking all 1200 colors to find the name?) \ No newline at end of file