Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions rct-graphics-helper/magick_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ def as_montage(self, inputs):
"\" \"".join(inputs) + \
"\" +append -background none"

# Writes rbg or rbga data to output
def pixel_data(self, image):
self.full_command = '"'+ image + '" -format %c -depth 8 histogram:info:-'

# Writes the current result to the MPR for reuse in the same command. The cached result can be referenced using mpr:{id}
def write_to_cache(self, id, delete_previous=False, next_file=""):
delete_addition = ""
Expand Down Expand Up @@ -100,10 +104,10 @@ def clone(self):

# Gets the cli command to perform the ImageMagick operation

def get_command_string(self, magick_path, output):
def get_command_string(self, magick_path, output = None):
if self.use_repage:
self.full_command = self.full_command + " +repage"
final_command = magick_path + " " + self.full_command + " \"" + output + "\""
final_command = magick_path + " " + self.full_command + (output and " \"" + output + "\"" or "")
if os.name == "posix":
final_command = final_command.replace("(", "\(").replace(")", "\)")
return final_command
Expand Down
46 changes: 46 additions & 0 deletions rct-graphics-helper/models/palette.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import subprocess
import os
import re

from ..magick_command import MagickCommand
from ..res.res import res_path
Expand Down Expand Up @@ -176,9 +177,37 @@
}
}

palettes_for_recolor = [
"black", "lavender_purple", "violet_purple","blue", "teal","yellow_green",
"sea_green","light_olive_green","dark_olive_green","lime_green","yellow",
"bright_yellow","orange","salmon","sandy_brown","bordeaux_red","bright_red",
"magenta","recolor_1","recolor_1_orct2"
]

def create_remap_tuple(paletteName):
if not paletteName in palette_colors_details:
return
palette = palette_colors_details[paletteName]
return tuple([paletteName, palette["title"], palette["Description"]])

def create_remap_enumlist(defaultSelection):
myPaletteColors = palettes_for_recolor.copy()
myPaletteColors.remove(defaultSelection)
options = [create_remap_tuple(i) for i in myPaletteColors]
options.insert(0,create_remap_tuple(defaultSelection))
return options

palette_base_path = os.path.join(res_path, "palettes")
palette_groups_path = os.path.join(palette_base_path, "groups")

class RGBA:
def __init__(self, hexString, red, green, blue, alpha = 255):
self.hex = hexString
self.red = int(red)
self.green = int(green)
self.blue = int(blue)
self.alpha = int(alpha)

# Collection of color groups to create a palette from


Expand All @@ -188,6 +217,7 @@ def __init__(self, path=None, colors=[]):
self.generated = False
self.invalidated = False
self.path = ""
self.shades = []

if path != None:
self.path = path
Expand Down Expand Up @@ -242,3 +272,19 @@ def generate_output(self, renderer, output_path):
self.path = output_path
self.generated = True
self.invalidated = False

# generates a list of hexadecimal colors usable in ImageMagick
def get_shades(self, renderer):
cmd = MagickCommand("")
cmd.pixel_data(self.path)
raw_output = subprocess.check_output(cmd.get_command_string(
renderer.magick_path), shell = True)
output = raw_output.decode("utf-8")
data_rgb = re.findall(" \(([\d,]+)\)", output)
data_hex = re.findall("#[\w]+", output)
if (len(data_rgb) != len(data_hex)):
print(len(data_rgb), data_rgb)
print(len(data_hex), data_hex)
assert(len(data_rgb) != len(data_hex))
colors_present = [RGBA(data_hex[i], *(data_rgb[i].split(","))) for i in range(len(data_rgb))]
self.shades = [shade.hex for shade in colors_present if shade.alpha == 255]
6 changes: 5 additions & 1 deletion rct-graphics-helper/operators/render_tiles_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ def create_task(self, context):
scene = context.scene
props = scene.rct_graphics_helper_static_properties
general_props = scene.rct_graphics_helper_general_properties


# Update the remap palettes with the ones we set. These colors will be recolored into OpenRCT2's remap 1, 2, 3
# colors on materials with the appropriate index set
self.palette_manager.set_recolor_palettes(general_props.primary_remap_input, general_props.secondary_remap_input,
general_props.tertiary_remap_input)
# Create the list of frames with our parameters
self.task_builder.clear()
self.task_builder.set_anti_aliasing_with_background(
Expand Down
5 changes: 5 additions & 0 deletions rct-graphics-helper/operators/vehicle_render_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ def create_task(self, context):
props = context.scene.rct_graphics_helper_vehicle_properties
general_props = context.scene.rct_graphics_helper_general_properties

# Update the remap palettes with the ones we set. These colors will be recolored into OpenRCT2's remap 1, 2, 3
# colors on materials with the appropriate index set
self.palette_manager.set_recolor_palettes(general_props.primary_remap_input, general_props.secondary_remap_input,
general_props.tertiary_remap_input)

self.task_builder.clear()
self.task_builder.set_anti_aliasing_with_background(
context.scene.render.use_antialiasing, general_props.anti_alias_with_background, general_props.maintain_aliased_silhouette)
Expand Down
5 changes: 5 additions & 0 deletions rct-graphics-helper/operators/walls_render_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ def create_task(self, context):
props = scene.rct_graphics_helper_walls_properties
general_props = scene.rct_graphics_helper_general_properties

# Update the remap palettes with the ones we set. These colors will be recolored into OpenRCT2's remap 1, 2, 3
# colors on materials with the appropriate index set
self.palette_manager.set_recolor_palettes(general_props.primary_remap_input, general_props.secondary_remap_input,
general_props.tertiary_remap_input)

# Create the list of frames with our parameters
self.task_builder.clear()
self.task_builder.set_anti_aliasing_with_background(
Expand Down
36 changes: 24 additions & 12 deletions rct-graphics-helper/palette_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import bpy
import math

from .models.palette import Palette, palette_base_path
from .models.palette import Palette, palette_base_path, palette_groups_path

default_full_palette = Palette(os.path.join(
palette_base_path, "default_full_palette.bmp"), [
Expand Down Expand Up @@ -52,12 +52,6 @@
"transparent"
])

recolor_1_palette = Palette(os.path.join(
palette_base_path, "recolor_1_palette.bmp"), [
"recolor_1",
"transparent"
])

recolor_1_orct2_palette = Palette(os.path.join(
palette_base_path, "recolor_1_orct2_palette.bmp"), [
"recolor_1_orct2",
Expand Down Expand Up @@ -86,18 +80,36 @@

class PaletteManager:
def __init__(self):
self.recolor_palettes = [
recolor_1_palette,
recolor_2_palette,
recolor_3_palette
]
self.recolor_palettes = []

self.orct2_recolor_palettes = [
recolor_1_orct2_palette,
recolor_2_palette,
recolor_3_palette
]

def set_recolor_palettes(self, recolor1, recolor2, recolor3):
self.recolor_palettes = [
Palette(
os.path.join(palette_groups_path, recolor1 + ".png"),
[ recolor1 ]
),
Palette(
os.path.join(palette_groups_path, recolor2 + ".png"),
[ recolor2 ]
),
Palette(
os.path.join(palette_groups_path, recolor3 + ".png"),
[ recolor3 ]
),
]

def get_recolor_shades(self, renderer):
for palette in self.recolor_palettes:
palette.get_shades(renderer)
for palette in self.orct2_recolor_palettes:
palette.get_shades(renderer)

# Gets a base palette for the selected palette mode for the selected number of recolorables
def get_base_palette(self, selected_palette_mode, recolors, preference="FULL"):
if selected_palette_mode == "AUTO":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ def process(self, frame, callback=None):
magick_command.quantize(self.renderer.get_palette_path(
frame.base_palette), self.renderer.floyd_steinberg_diffusion)

# this should be moved somewhere it can run once per palette change
self.renderer.get_recolor_shades()

# Force the recolorables to a palette that only contains the recolorable color
channels_to_exclude_for_mai = ["Green", "Blue"]

Expand All @@ -58,21 +61,10 @@ def process(self, frame, callback=None):
forced_color_render = MagickCommand("mpr:render")
forced_color_render.quantize(self.renderer.get_palette_path(
palette), self.renderer.floyd_steinberg_diffusion)

if i == 0:
# Replace our clover green recolor 1 with the OpenRCT2 orange recolor 1
forced_color_render.replace_color("#003F21", "#6F332F")
forced_color_render.replace_color("#00672F", "#83372F")
forced_color_render.replace_color("#0B7B41", "#973F33")
forced_color_render.replace_color("#178F51", "#AB4333")
forced_color_render.replace_color("#1FA35C", "#BF4B2F")
forced_color_render.replace_color("#27B768", "#D34F2B")
forced_color_render.replace_color("#3BDB7F", "#E75723")
forced_color_render.replace_color("#5BEF98", "#FF5F1F")
forced_color_render.replace_color("#77F3A9", "#FF7F27")
forced_color_render.replace_color("#97F7BE", "#FF9B33")
forced_color_render.replace_color("#B7FBD0", "#FFB73F")
forced_color_render.replace_color("#D7FFE5", "#FFCF4B")

# Replace our input color with the appropriate orct2 remap color
for i in range(min(len(palette.shades), len(orct2_palette.shades))):
forced_color_render.replace_color(palette.shades[i],orct2_palette.shades[i])

magick_command.mask_mix(forced_color_render, mask)

Expand Down
17 changes: 16 additions & 1 deletion rct-graphics-helper/properties/general_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import math
import os

from ..models.palette import palette_colors, palette_colors_details
from ..models.palette import palette_colors, palette_colors_details, create_remap_enumlist


class GeneralProperties(bpy.types.PropertyGroup):
Expand Down Expand Up @@ -94,6 +94,21 @@ class GeneralProperties(bpy.types.PropertyGroup):
description="Which color groups to dither to. Recolorables will be excluded from this palette when used to avoid conflicts.",
size=len(defaults))

primary_remap_input = bpy.props.EnumProperty(
name="Primary Color",
items= create_remap_enumlist("recolor_1")
)

secondary_remap_input = bpy.props.EnumProperty(
name="Secondary Color",
items= create_remap_enumlist("magenta")
)

tertiary_remap_input = bpy.props.EnumProperty(
name="Tertiary Color",
items= create_remap_enumlist("yellow")
)

render_mode = bpy.props.EnumProperty(
name="Render Mode",
items=(
Expand Down
12 changes: 12 additions & 0 deletions rct-graphics-helper/rct_graphics_helper_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@ def draw(self, context):
row = layout.row()
row.separator()

row = layout.row()
row.label("Remap Colors:")

row = layout.row()
row.prop(properties,"primary_remap_input")

row = layout.row()
row.prop(properties,"secondary_remap_input")

row = layout.row()
row.prop(properties,"tertiary_remap_input")

row = layout.row()
row.label("Dither Palette:")

Expand Down
3 changes: 3 additions & 0 deletions rct-graphics-helper/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ def _render_finished_safe(self):
if callback != None:
callback()

def get_recolor_shades(self):
self.palette_manager.get_recolor_shades(self)

def get_palette_path(self, palette):
palette.prepare(self)
return palette.path
Expand Down
Binary file not shown.