Better number positioning, better mask combining and generation

conquest_develop
bobloy 4 years ago
parent 8abeca3d1e
commit e2e5477661

@ -23,17 +23,7 @@ class Conquest(commands.Cog):
default_zoom_json = {"enabled": False, "x": -1, "y": -1, "zoom": 1.0} default_zoom_json = {"enabled": False, "x": -1, "y": -1, "zoom": 1.0}
default_custom_map = { default_maps_json = {"maps": []}
"name": "",
"regions": {},
"region_max": 0,
"extension": "png",
"custom": True,
}
default_maps_json = {
"maps": []
}
def __init__(self, bot: Red): def __init__(self, bot: Red):
super().__init__() super().__init__()
@ -64,8 +54,9 @@ class Conquest(commands.Cog):
self.is_custom = False self.is_custom = False
self.current_map = None self.current_map = None
self.map_data = None self.map_data = None
self.ext = None
self.ext_format = None self.ext = "PNG"
self.ext_format = "PNG"
self.mm: Union[ConquestMap, None] = None self.mm: Union[ConquestMap, None] = None
@ -100,8 +91,6 @@ class Conquest(commands.Cog):
print(e) print(e)
await self.config.current_map.set(None) await self.config.current_map.set(None)
return return
self.ext = self.map_data["extension"]
self.ext_format = "JPEG" if self.ext.upper() == "JPG" else self.ext.upper()
async def _get_current_map_path(self): async def _get_current_map_path(self):
return self.current_map_folder / self.current_map return self.current_map_folder / self.current_map
@ -136,7 +125,7 @@ class Conquest(commands.Cog):
im = Image.open(current_img_path) im = Image.open(current_img_path)
async with ctx.typing(): async with ctx.typing():
out: Image.Image = await composite_regions( out: Image.Image = await composite_regions(
im, regions, color, self._path_if_custom() / self.current_map im, regions, color, self._path_if_custom() / self.current_map / "masks"
) )
out.save(current_img_path, self.ext_format) out.save(current_img_path, self.ext_format)
await self._send_maybe_zoomed_map(ctx, current_img_path, f"map.{self.ext}") await self._send_maybe_zoomed_map(ctx, current_img_path, f"map.{self.ext}")
@ -152,6 +141,19 @@ class Conquest(commands.Cog):
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
pass pass
@mapmaker.command(name="numbers")
async def _mapmaker_numbers(self, ctx: commands.Context):
"""Regenerates the number mask and puts it in the channel"""
if not self.mm:
await ctx.maybe_send_embed("No map currently being worked on")
return
async with ctx.typing():
await self.mm.create_number_mask()
im = await self.mm.get_blank_numbered_file()
await ctx.send(file=discord.File(im, filename="map.png"))
@mapmaker.command(name="close") @mapmaker.command(name="close")
async def _mapmaker_close(self, ctx: commands.Context): async def _mapmaker_close(self, ctx: commands.Context):
"""Close the currently open map.""" """Close the currently open map."""
@ -255,7 +257,7 @@ class Conquest(commands.Cog):
files = await self.mm.get_sample() files = await self.mm.get_sample()
for f in files: for f in files:
await ctx.send(file=discord.File(f)) await ctx.send(file=discord.File(f, filename="map.png"))
@mapmaker.command(name="load") @mapmaker.command(name="load")
async def _mapmaker_load(self, ctx: commands.Context, map_name: str): async def _mapmaker_load(self, ctx: commands.Context, map_name: str):
@ -311,9 +313,13 @@ class Conquest(commands.Cog):
@_mapmaker_masks.command(name="combine") @_mapmaker_masks.command(name="combine")
async def _mapmaker_masks_combine( async def _mapmaker_masks_combine(
self, ctx: commands.Context, mask_list: Greedy[int], recommended=False self, ctx: commands.Context, mask_list: Greedy[int], recommended=False
): ):
"""Generate masks for the map""" """Generate masks for the map"""
if not mask_list and not recommended:
await ctx.send_help()
return
if not self.mm: if not self.mm:
await ctx.maybe_send_embed("No map currently being worked on") await ctx.maybe_send_embed("No map currently being worked on")
return return
@ -339,13 +345,14 @@ class Conquest(commands.Cog):
await ctx.send("Not Implemented") await ctx.send("Not Implemented")
return return
result = await self.mm.combine_masks(mask_list) async with ctx.typing():
if not result: result = await self.mm.combine_masks(mask_list)
await ctx.maybe_send_embed( if not result:
"Failed to combine masks, try the command again or check log for errors" await ctx.maybe_send_embed(
) "Failed to combine masks, try the command again or check log for errors"
return )
await ctx.tick() return
await ctx.tick()
@commands.group() @commands.group()
async def conquest(self, ctx: commands.Context): async def conquest(self, ctx: commands.Context):
@ -491,7 +498,7 @@ class Conquest(commands.Cog):
@conquest_set.command(name="map") @conquest_set.command(name="map")
async def _conquest_set_map( async def _conquest_set_map(
self, ctx: commands.Context, mapname: str, is_custom: bool = False, reset: bool = False self, ctx: commands.Context, mapname: str, is_custom: bool = False, reset: bool = False
): ):
""" """
Select a map from current available maps Select a map from current available maps
@ -563,35 +570,35 @@ class Conquest(commands.Cog):
if self.current_map is None: if self.current_map is None:
await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`") await ctx.maybe_send_embed("No map is currently set. See `[p]conquest set map`")
return return
async with ctx.typing():
numbers_path = self._path_if_custom() / self.current_map / f"numbers.{self.ext}" numbers_path = self._path_if_custom() / self.current_map / f"numbers.{self.ext}"
if not numbers_path.exists(): if not numbers_path.exists():
await ctx.send( await ctx.send(
file=discord.File( file=discord.File(
fp=self._path_if_custom() / self.current_map / f"numbered.{self.ext}", fp=self._path_if_custom() / self.current_map / f"numbered.{self.ext}",
filename=f"numbered.{self.ext}", filename=f"numbered.{self.ext}",
)
) )
) return
return
current_map_path = await self._get_current_map_path() current_map_path = await self._get_current_map_path()
current_map = Image.open(current_map_path / f"current.{self.ext}") current_map = Image.open(current_map_path / f"current.{self.ext}")
numbers = Image.open(numbers_path).convert("L") numbers = Image.open(numbers_path).convert("L")
inverted_map = ImageOps.invert(current_map) inverted_map = ImageOps.invert(current_map)
loop = asyncio.get_running_loop() loop = asyncio.get_running_loop()
current_numbered_img = await loop.run_in_executor( current_numbered_img = await loop.run_in_executor(
None, Image.composite, current_map, inverted_map, numbers None, Image.composite, current_map, inverted_map, numbers
) )
current_numbered_img.save( current_numbered_img.save(
current_map_path / f"current_numbered.{self.ext}", self.ext_format current_map_path / f"current_numbered.{self.ext}", self.ext_format
) )
await self._send_maybe_zoomed_map( await self._send_maybe_zoomed_map(
ctx, current_map_path / f"current_numbered.{self.ext}", f"current_numbered.{self.ext}", ctx, current_map_path / f"current_numbered.{self.ext}", f"current_numbered.{self.ext}",
) )
@conquest.command(name="multitake") @conquest.command(name="multitake")
async def _conquest_multitake( async def _conquest_multitake(

@ -28,7 +28,7 @@ async def composite_regions(im, regions, color, masks_path) -> Union[Image.Image
if combined_mask is None: # No regions usually if combined_mask is None: # No regions usually
return None return None
out = await loop.run_in_executor(None, Image.composite, im, im2, combined_mask.convert("L")) out = await loop.run_in_executor(None, Image.composite, im, im2, combined_mask)
return out return out
@ -172,8 +172,12 @@ class ConquestMap:
return True return True
async def save_data(self): async def save_data(self):
to_save = self.__dict__.copy() to_save = {
to_save.pop("path") "name": self.name,
"custom": self.custom,
"region_max": self.region_max,
"regions": {num: r.get_json() for num, r in self.regions.items()}
}
with self.data_path().open("w+") as dp: with self.data_path().open("w+") as dp:
json.dump(to_save, dp, sort_keys=True, indent=4) json.dump(to_save, dp, sort_keys=True, indent=4)
@ -181,11 +185,13 @@ class ConquestMap:
with self.data_path().open() as dp: with self.data_path().open() as dp:
data = json.load(dp) data = json.load(dp)
self.name = data["name"] self.name = data.get("name")
self.custom = data["custom"] self.custom = data.get("custom")
self.region_max = data["region_max"] self.region_max = data.get("region_max")
if "regions" in data:
self.regions = {key: Region(**data) for key, data in data["regions"].items()} self.regions = {int(key): Region(**data) for key, data in data["regions"].items()}
else:
self.regions = {}
async def save_region(self, region): async def save_region(self, region):
if not self.custom: if not self.custom:
@ -239,6 +245,8 @@ class ConquestMap:
await self.save_data() await self.save_data()
return True
def _img_combine_masks(self, mask_list: List[int]): def _img_combine_masks(self, mask_list: List[int]):
if not mask_list: if not mask_list:
return False, None return False, None
@ -297,11 +305,7 @@ class ConquestMap:
current_map, regions[fourth * 3:], ImageColor.getrgb("yellow"), self.masks_path() current_map, regions[fourth * 3:], ImageColor.getrgb("yellow"), self.masks_path()
) )
numbers = Image.open(self.numbers_path()).convert("L") current_numbered_img = await self.get_numbered(current_map)
inverted_map = ImageOps.invert(current_map)
current_numbered_img = await loop.run_in_executor(
None, Image.composite, current_map, inverted_map, numbers
)
buffer1 = BytesIO() buffer1 = BytesIO()
buffer2 = BytesIO() buffer2 = BytesIO()
@ -316,6 +320,23 @@ class ConquestMap:
return files return files
async def get_blank_numbered_file(self):
im = await self.get_numbered(Image.open(self.blank_path()))
buffer1 = BytesIO()
im.save(buffer1, "png")
buffer1.seek(0)
return buffer1
async def get_numbered(self, current_map):
loop = asyncio.get_running_loop()
numbers = Image.open(self.numbers_path()).convert("L")
inverted_map = ImageOps.invert(current_map)
current_numbered_img = await loop.run_in_executor(
None, Image.composite, current_map, inverted_map, numbers
)
return current_numbered_img
class Region: class Region:
def __init__(self, center, weight, **kwargs): def __init__(self, center, weight, **kwargs):
@ -323,6 +344,13 @@ class Region:
self.weight = weight self.weight = weight
self.data = kwargs self.data = kwargs
def get_json(self):
return {
"center": self.center,
"weight": self.weight,
"data": self.data.copy()
}
class Regioner: class Regioner:
def __init__( def __init__(
@ -398,8 +426,11 @@ class Regioner:
fnt = ImageFont.load_default() fnt = ImageFont.load_default()
d = ImageDraw.Draw(number_img) d = ImageDraw.Draw(number_img)
for region_num, region in regions.items(): for region_num, region in regions.items():
center = region.center text = getattr(region, "name", str(region_num))
text = getattr(region, "center", str(region_num))
d.text(center, text, font=fnt, fill=0) w1, h1 = region.center
w2, h2 = fnt.getsize(text)
d.text((w1-(w2/2), h1-(h2/2)), text, font=fnt, fill=0)
number_img.save(self.filepath / f"numbers.png", "PNG") number_img.save(self.filepath / f"numbers.png", "PNG")
return True return True

Loading…
Cancel
Save