def apply_animated_material_forcefield(self) -> None: """Renders a GIF loosely based on the behavior of the AnimatedMaterialForcefield part.""" # tile rotates every 500 ms (_1 to _4), color rotates every 250 ms obj, tile = self.qud_object, self.qud_tile tile_prefix = tile.filename.rsplit('_', 1)[0][:-1] tile_postfix = '_' + tile.filename.rsplit('_', 1)[1] tile_numerals = ['1', '1', '2', '2', '3', '3', '4', '4'] tile_colors = ['&C', '&c', '&C', '&c'] tile_details = [None, 'K', 'c', 'C'] forcefield_palette = obj.part_AnimatedMaterialForcefield_Color if forcefield_palette is not None: if forcefield_palette == 'Red': tile_colors = ['&R', '&r', '&R', '&r'] tile_details = [None, 'r', 'r', 'r'] elif forcefield_palette == 'Blue': tile_colors = ['&B', '&b', '&B', '&b'] tile_details = [None, 'K', 'b', 'B'] tile_colors = tile_colors + tile_colors tile_details = tile_details + tile_details frames = [] durations = [] for numeral, color, detail in zip(tile_numerals, tile_colors, tile_details): f = tile_prefix + numeral + tile_postfix # construct filename frames.append( QudTile(f, color, color, detail, tile.qudname, tile.raw_transparent)) durations.append(250) self._make_gif(frames, durations)
def apply_phase_sticky(self) -> None: """Renders a GIF loosely based on the behavior of the PhaseSticky part.""" tile = self.qud_tile frame1 = QudTile(tile.filename, '&k', '&k', tile.raw_detailcolor, tile.qudname, tile.raw_transparent) frame2 = QudTile(tile.filename, '&K', '&K', tile.raw_detailcolor, tile.qudname, tile.raw_transparent) frame3 = QudTile(tile.filename, '&c', '&c', tile.raw_detailcolor, tile.qudname, tile.raw_transparent) frame4 = tile frame5 = QudTile(tile.filename, '&y', '&y', tile.raw_detailcolor, tile.qudname, tile.raw_transparent) frame6 = tile frames = [frame1, frame2, frame3, frame4, frame5, frame6] durations = [40, 40, 40, 40, 40, 40] self._make_gif(frames, durations)
def apply_animated_material_mainframe_tape_drive(self) -> None: """Renders a GIF loosely based on the behavior of the AnimatedMaterialMainframeTapeDrive.""" t = self.qud_tile pre = t.filename.split('-')[0][:-1] post = '-' + t.filename.split('-')[1] file1, file2, file3, file4 = f'{pre}1{post}', f'{pre}2{post}',\ f'{pre}3{post}', f'{pre}4{post}' frames: List[QudTile] = [ QudTile(file1, t.colorstring, t.raw_tilecolor, t.raw_detailcolor, t.qudname, t.raw_transparent), QudTile(file2, t.colorstring, t.raw_tilecolor, t.raw_detailcolor, t.qudname, t.raw_transparent), QudTile(file3, t.colorstring, t.raw_tilecolor, t.raw_detailcolor, t.qudname, t.raw_transparent), QudTile(file4, t.colorstring, t.raw_tilecolor, t.raw_detailcolor, t.qudname, t.raw_transparent) ] # tape drive rotates forward once every 500ms. But it also has a 1/64 chance (each) to enter # RushingForward or RushingBackward mode for a random duration between 15-120 frames. We # have to restrain ourselves a bit to keep the GIF at a manageable size. The GIF generated # below is 80 frames and 926KB. sequence = [] durations = [] for cycle in range(2): # Normal forward for rotation in range(4): sequence.append(frames[rotation]) durations.append(500) for cycle in range(12): # RushingBackward for rotation in [2, 1, 0, 3]: sequence.append(frames[rotation]) durations.append(20) for cycle in range(1): # Normal forward for rotation in range(4): sequence.append(frames[rotation]) durations.append(500) for cycle in range(4): # RushingForward for rotation in range(4): sequence.append(frames[rotation]) durations.append(20) for cycle in range(1): # Normal forward for rotation in range(4): sequence.append(frames[rotation]) durations.append(500) self._make_gif(sequence, durations)
def apply_gas_animation(self) -> None: """Renders a GIF that replicates the behavior of the Gas part.""" t = self.qud_tile glyph1 = TileProvider(StandInTiles.gas_glyph1) glyph2 = TileProvider(StandInTiles.gas_glyph2) glyph3 = TileProvider(StandInTiles.gas_glyph3) glyph4 = TileProvider(StandInTiles.gas_glyph4) frame1 = QudTile(None, t.colorstring, t.raw_tilecolor, t.raw_detailcolor, t.qudname, t.raw_transparent, glyph1) frame2 = QudTile(None, t.colorstring, t.raw_tilecolor, t.raw_detailcolor, t.qudname, t.raw_transparent, glyph2) frame3 = QudTile(None, t.colorstring, t.raw_tilecolor, t.raw_detailcolor, t.qudname, t.raw_transparent, glyph3) frame4 = QudTile(None, t.colorstring, t.raw_tilecolor, t.raw_detailcolor, t.qudname, t.raw_transparent, glyph4) self._make_gif([frame1, frame2, frame3, frame4], [250, 250, 250, 250])
def apply_animated_material_techlight(self) -> None: obj, tile = self.qud_object, self.qud_tile base_color = obj.part_AnimatedMaterialTechlight_baseColor base_color = '&c' if base_color is None else base_color frame1 = QudTile(tile.filename, None, base_color, 'Y', tile.qudname, tile.raw_transparent) frame2 = QudTile(tile.filename, None, base_color, 'C', tile.qudname, tile.raw_transparent) frame3 = QudTile(tile.filename, None, base_color, 'B', tile.qudname, tile.raw_transparent) frame4 = QudTile(tile.filename, None, base_color, 'b', tile.qudname, tile.raw_transparent) frame5 = QudTile(tile.filename, None, base_color, 'c', tile.qudname, tile.raw_transparent) frames = [ (frame1, 650), (frame2, 20), (frame1, 900), (frame4, 20), (frame1, 750), (frame3, 20), (frame1, 800), (frame2, 20), (frame1, 40), (frame4, 20), (frame1, 1150), (frame2, 20), (frame1, 350), (frame5, 20), (frame1, 1000), (frame2, 20), (frame1, 20), (frame3, 20), (frame1, 200), (frame2, 20), (frame1, 2500), (frame5, 20), ] self._make_gif([f[0] for f in frames], [d[1] for d in frames])
def tile(self, tile_index: int = 0) -> QudTile | None: """Retrieves the painted QudTile for this object. If an index is supplied for an object that has multiple tiles, returns the alternate tile at the specified index.""" if tile_index >= len(self._tiles): return None if self._tiles[tile_index] is not None: return self._tiles[tile_index] if self.file is None or self.file == '': if not self.standin: return None self._stylize_tile_variant(tile_index) self._tiles[tile_index] = QudTile(None, self.color, self.tilecolor, self.detail, self.obj.name, self.trans, self.standin, self.prefab_imitator) else: self._stylize_tile_variant(tile_index) self._tiles[tile_index] = QudTile(self.file, self.color, self.tilecolor, self.detail, self.obj.name, self.trans, None, self.prefab_imitator) return self._tiles[tile_index]
def apply_power_transmission(self) -> None: """Renders a GIF loosely based on the behavior of IPowerTransmission parts that have TileEffects enabled. To simplify things, we assume that the object is powered and unbroken, ignoring other potential variations.""" obj, t = self.qud_object, self.qud_tile part, tile_path_start = None, None for partname in POWER_TRANSMISSION_PARTS: part = getattr(obj, f'part_{partname}') if part is not None and 'TileBaseFromTag' in part: if 'TileEffects' in part and part['TileEffects'].lower( ) == 'true': tile_path_start = getattr( obj, f"tag_{part['TileBaseFromTag']}_Value") break if tile_path_start is None or part is None: logging.error(f'Unexpectedly failed to generate .gif for ' f'"{obj.name}" - missing Tile rendering tag?') return directory = t.filename.split(tile_path_start)[0] # calculate tile path postfixes first_postfix = '' numeral_postfixes = [] if 'TileAppendWhenUnbrokenAndPowered' in part: first_postfix += part['TileAppendWhenUnbrokenAndPowered'] else: if 'TileAppendWhenPowered' in part: first_postfix += part['TileAppendWhenPowered'] if 'TileAppendWhenUnbroken' in part: first_postfix += part['TileAppendWhenUnbroken'] if 'TileAnimatePoweredFrames' in part: for num in range(1, int(part['TileAnimatePoweredFrames']) + 1): numeral_postfixes.append(f'_{num}') final_postfix = '_nsew' if TilePainter.is_painted_fence(obj) else '' ext = obj.tag_PaintedFenceExtension_Value ext = ext if ext else '.bmp' # divide frames evenly across 1000 milliseconds frame_duration = (100 // len(numeral_postfixes)) * 10 frame_duration = 20 if frame_duration < 20 else frame_duration # minimum render duration frames = [] durations = [] for numeral_postfix in numeral_postfixes: f = directory + tile_path_start + first_postfix + numeral_postfix + final_postfix + ext frames.append( QudTile(f, t.colorstring, t.raw_tilecolor, t.raw_detailcolor, t.qudname, t.raw_transparent)) durations.append(frame_duration) self._make_gif(frames, durations)
def apply_vortex_animation(self) -> None: """Renders a GIF loosely based on the behavior of the SpaceTimeVortex part.""" frame_count = 50 random.seed(self.qud_object.name) glyphs = ['§', 'φ', '☼', '○'] # '•' colors = ['B', 'R', 'C', 'W', 'K'] frames: List[QudTile] = [] for _ in range(frame_count): color = random.choice(colors) glyph = random.choice(glyphs) if random.randint(0, 20) != 0 else '•' generator = TileProvider( lambda: (StandInTiles.make_font_glyph(glyph, color), False)) frames.append( QudTile.from_image_provider(generator, self.qud_object.name)) self._make_gif(frames, [50] * frame_count)
def apply_walltrap_animation(self) -> None: """Renders a GIF loosely based on the behavior of the Walltrap part.""" tile = self.qud_tile frame1 = tile # WarmColor readycolor = self.qud_object.part_Walltrap_ReadyColor turninterval = self.qud_object.part_Walltrap_TurnInterval turninterval = 3 if turninterval is None else int(turninterval) fore = extract_foreground_char(readycolor, 'R') back = extract_background_char(readycolor, 'g') color_string = '&' + fore + '^' + back tile_color = color_string trans_color = back detail_color = 'transparent' frame2 = QudTile(tile.filename, color_string, tile_color, detail_color, tile.qudname, trans_color) # ReadyColor final_frame_duration = turninterval * 1200 - 1600 final_frame_duration = 20 if final_frame_duration < 20 else final_frame_duration self._make_gif([frame1, frame2, frame1], [1600, 1200, final_frame_duration])
def apply_animated_material_reality_stabilization_field(self) -> None: tile = self.qud_tile t_pre = tile.filename.rsplit('_', 1)[0][:-1] t_post = '_' + tile.filename.rsplit('_', 1)[1] tile_paths = [ f'{t_pre}1{t_post}', f'{t_pre}2{t_post}', f'{t_pre}3{t_post}', f'{t_pre}4{t_post}' ] # tile_colors = ['&y^k', '&K^k', '&Y^y', '&Y^K', '&y^k'] # tile_details = ['k', 'k', 'y', 'K', 'k'] tile_colors = ['&y', '&K', '&Y^y', '&Y^K', '&y'] tile_details = [None, None, 'y', 'K', None] color_tick_idxs = [0, 2000, 7000, 12000, 16000] frames = [] durations = [] path_idx = 0 color_idx = 0 prev_tick = None for tick in range(0, 36000, 100): update_frame = False if tick % 2400 == 0: path_idx = (tick // 2400) % 4 update_frame = True if (tick % 18000) in color_tick_idxs: color_idx = color_tick_idxs.index((tick % 18000)) update_frame = True if update_frame is True: path = tile_paths[path_idx] color = tile_colors[color_idx] detail = tile_details[color_idx] frames.append( QudTile(path, color, color, detail, tile.qudname, tile.raw_transparent)) if prev_tick is not None: duration = tick - prev_tick duration = 20 if duration < 20 else duration # minimum render duration durations[-1] = duration durations.append(0) prev_tick = tick durations[-1] = 36000 - prev_tick durations[-1] = 20 if durations[-1] < 20 else durations[ -1] # minimum render duration self._make_gif(frames, durations)
def apply_astral(self, random_sequence: bool = False) -> None: """Renders a GIF loosely based on the behavior of the Astral tag combined with a phasing effect (like the Astral mutation). The only object this currently affects is Astral Tabby. This is very similar to the holographic animiation but it uses different colors and is designed to animate at half the speed, more or less.""" tile = self.qud_tile glyph1 = TileProvider(StandInTiles.hologram_material_glyph1) glyph2 = TileProvider(StandInTiles.hologram_material_glyph2) glyph3 = TileProvider(StandInTiles.hologram_material_glyph3) # base most of the time base = QudTile(tile.filename, '&K', '&K', 'y', tile.qudname, tile.raw_transparent) # 2-4 somewhat common frame2 = QudTile(tile.filename, '&Y', '&Y', 'k', tile.qudname, tile.raw_transparent) frame3 = QudTile(tile.filename, '&y', '&y', 'K', tile.qudname, tile.raw_transparent) frame4 = QudTile(tile.filename, '&k', '&k', 'y', tile.qudname, tile.raw_transparent) # 5-9 less common frame5 = QudTile(None, '&K', '&K', 'y', tile.qudname, tile.raw_transparent, glyph1) frame6 = QudTile(None, '&K', '&K', 'y', tile.qudname, tile.raw_transparent, glyph2) frame7 = QudTile(None, '&K', '&K', 'y', tile.qudname, tile.raw_transparent, glyph3) frame8 = QudTile(tile.filename, '&K', '&K', 'k', tile.qudname, tile.raw_transparent) frame9 = QudTile(tile.filename, '&K', '&K', 'y', tile.qudname, tile.raw_transparent) frames = [] durations = [] if random_sequence: altframes_common = [frame2, frame3, frame4] altframes_rare = [frame8, frame9] baseframe = True fullflicker_chance = 12 for i in range(40): # frame limit if baseframe: frames.append(base) durations.append( random.randint(600, 1400) + random.randint(-200, 600)) baseframe = not baseframe else: if random.randint(1, fullflicker_chance) == 1: fullflicker_chance = 200 # significantly reduce chance frames.extend([frame6, frame5, frame7]) durations.extend([20, 20, 20]) else: if random.randint(1, 18) > 1: frames.append(random.choice(altframes_common)) else: frames.append(random.choice(altframes_rare)) if random.randint(1, 8) > 1: durations.append(40) else: durations.append( 50 if random.randint(1, 10) > 7 else 30) if random.randint(1, 5) > 1: baseframe = not baseframe else: frames.extend([ base, frame2, base, frame3, base, frame9, frame6, frame5, frame7, base, frame4, base ]) durations.extend( [1100, 40, 400, 40, 2200, 30, 20, 20, 20, 1560, 40, 960]) frames.extend([ frame2, frame3, base, frame4, base, frame4, base, frame2, base, frame3, base, frame8, base ]) durations.extend([ 30, 40, 1800, 50, 2200, 40, 1700, 40, 1000, 50, 2600, 40, 1400 ]) frames.extend([ frame4, base, frame3, base, frame2, base, frame3, base, frame4, base ]) durations.extend([40, 2500, 40, 1300, 40, 1000, 30, 1800, 40, 700]) self._make_gif(frames, durations)
def apply_hologram_material(self, is_concealed: bool = False, random_sequence: bool = False) -> None: """Renders a GIF loosely based on the behavior of the HologramMaterial part. This particular method uses a preset algorithm for the default case, which (1) ensures we'll know when the existing wiki image matches, because it'll always be the same (2) is predictable and we know it'll look halfway decent. Cryptogull invokes this with the random_sequence parameter, which instead creates a random holographic animation sequence.""" tile = self.qud_tile glyph1 = TileProvider(StandInTiles.hologram_material_glyph1) glyph2 = TileProvider(StandInTiles.hologram_material_glyph2) glyph3 = TileProvider(StandInTiles.hologram_material_glyph3) # base most of the time if is_concealed: base = tile else: base = QudTile(tile.filename, '&B', '&B', 'b', tile.qudname, tile.raw_transparent) # 2-4 somewhat common frame2 = QudTile(tile.filename, '&C', '&C', 'c', tile.qudname, tile.raw_transparent) frame3 = QudTile(tile.filename, '&c', '&c', 'b', tile.qudname, tile.raw_transparent) frame4 = QudTile(tile.filename, '&b', '&b', 'C', tile.qudname, tile.raw_transparent) # 5-9 less common frame5 = QudTile(None, '&c', '&c', 'b', tile.qudname, tile.raw_transparent, glyph1) frame6 = QudTile(None, '&C', '&C', 'b', tile.qudname, tile.raw_transparent, glyph2) frame7 = QudTile(None, '&Y', '&Y', 'b', tile.qudname, tile.raw_transparent, glyph3) frame8 = QudTile(tile.filename, '&Y', '&Y', 'b', tile.qudname, tile.raw_transparent) frame9 = QudTile(tile.filename, '&Y', '&Y', 'c', tile.qudname, tile.raw_transparent) frames = [] durations = [] if random_sequence: altframes_common = [frame2, frame3, frame4] altframes_rare = [frame8, frame9] baseframe = True fullflicker_chance = 12 for i in range(40): # frame limit if baseframe: frames.append(base) durations.append( random.randint(300, 700) + random.randint(-100, 300)) baseframe = not baseframe else: if random.randint(1, fullflicker_chance) == 1: fullflicker_chance = 200 # significantly reduce chance frames.extend([frame6, frame5, frame7]) durations.extend([20, 20, 20]) else: if random.randint(1, 18) > 1: frames.append(random.choice(altframes_common)) else: frames.append(random.choice(altframes_rare)) if random.randint(1, 8) > 1: durations.append(40) else: durations.append( 50 if random.randint(1, 10) > 7 else 30) if random.randint(1, 5) > 1: baseframe = not baseframe else: frames.extend([ base, frame2, base, frame3, base, frame9, frame6, frame5, frame7, base, frame4, base ]) durations.extend( [550, 40, 200, 40, 1100, 30, 20, 20, 20, 780, 40, 480]) frames.extend([ frame2, frame3, base, frame4, base, frame4, base, frame2, base, frame3, base, frame8, base ]) durations.extend( [30, 40, 900, 50, 1100, 40, 850, 40, 500, 50, 1300, 40, 700]) frames.extend([ frame4, base, frame3, base, frame2, base, frame3, base, frame4, base ]) durations.extend([40, 1250, 40, 650, 40, 500, 30, 900, 40, 350]) self._make_gif(frames, durations)
def apply_animated_material_generic(self) -> None: """Renders a GIF loosely based on the behavior of the AnimatedMaterialGeneric and AnimatedMaterialGenericAlternate parts.""" source_tile = self.qud_tile max_frames = 40 # set an upper limit to animation length to limit .gif size anim_parts = [] if self.qud_object.part_AnimatedMaterialGeneric is not None: anim_parts.append(self.qud_object.part_AnimatedMaterialGeneric) if self.qud_object.part_AnimatedMaterialGenericAlternate is not None: anim_parts.append( self.qud_object.part_AnimatedMaterialGenericAlternate) # adjustments for particular objects # AnimatedMaterialGenericAlternate is often inherited from HighTechInstallation and used as # the 'unpowered' animation, so we don't always want to show it if we're animating an object # that also has a 'powered' animation remove_alternate = [ 'Force Projector', 'GritGateChromeBeacon', 'Rodanis Y', 'Industrial Fan', 'Hydraulic Press', 'Fusion Pumping Station', 'Solar Power Station', 'Solar Pumping Station' ] if self.qud_object.name in remove_alternate: anim_parts.pop() # ignore AnimatedMaterialGenericAlternate # get greatest animation length and move that animation to front of array max_animation_length = 60 len1, len2 = 60, 60 if 'AnimationLength' in anim_parts[0]: len1 = max_animation_length = int(anim_parts[0]['AnimationLength']) if len(anim_parts) == 2 and 'AnimationLength' in anim_parts[1]: len2 = int(anim_parts[1]['AnimationLength']) if len2 > max_animation_length: max_animation_length = int(anim_parts[1]['AnimationLength']) anim_parts[0], anim_parts[1] = anim_parts[1], anim_parts[0] len1, len2 = len2, len1 # if necessary, calculate lowest common multiple of out-of-sync animation lengths total_duration = max_animation_length if len(anim_parts) > 1: total_duration = lowest_common_multiple(len1, len2) # extract frames from each animation tileframes: List[dict] = [{}, {}] colorframes: List[dict] = [{}, {}] detailframes: List[dict] = [{}, {}] for part, tframes, cframes, dframes in \ zip(anim_parts, tileframes, colorframes, detailframes): # set first frame to 'default' to absorb object's base render properties # using special logic below tframes[0] = 'default' cframes[0] = 'default' dframes[0] = 'default' # add additional frames based on AnimatedMaterial* part if 'TileAnimationFrames' in part: parse_comma_equals_str_into_dict(part['TileAnimationFrames'], tframes) if 'ColorStringAnimationFrames' in part: parse_comma_equals_str_into_dict( part['ColorStringAnimationFrames'], cframes) if 'DetailColorAnimationFrames' in part: parse_comma_equals_str_into_dict( part['DetailColorAnimationFrames'], dframes) # merge animation frames until we reach total_duration or we hit the max_frames limit sequenced_animation = [] tick, max_tick = -1, max_frames * 300 frame_index, last_frame_tick, idx1, idx2 = 0, 0, 0, 0 while tick < max_tick and tick < (total_duration - 1) and frame_index <= max_frames: tick += 1 tile, color, detail = None, None, None idx1 = tick % len1 idx2 = tick % len2 if idx1 in tileframes[0]: tile = tileframes[0][idx1] if idx1 in colorframes[0]: color = colorframes[0][idx1] if idx1 in detailframes[0]: detail = detailframes[0][idx1] if idx2 in tileframes[1]: tile = tileframes[1][idx2] if idx2 in colorframes[1]: color = colorframes[1][idx2] if idx2 in detailframes[1]: detail = detailframes[1][idx2] if tile is None and color is None and detail is None: continue sequenced_animation.append((-1, tile, color, detail)) if frame_index > 0: # insert duration into previous frame duration = tick - last_frame_tick prev_frame = sequenced_animation[frame_index - 1] sequenced_animation[frame_index - 1] = \ (duration, prev_frame[1], prev_frame[2], prev_frame[3]) frame_index += 1 last_frame_tick = tick # insert duration into final frame (or remove it) if tick == (total_duration - 1) or tick == max_tick: duration = tick - last_frame_tick last_frame = sequenced_animation[-1] sequenced_animation[-1] = (duration, last_frame[1], last_frame[2], last_frame[3]) elif frame_index > max_frames: sequenced_animation.pop() finalized_tiles = [] finalized_durations = [] for frame in sequenced_animation: duration, tile, color, detail = frame # calculate GIF duration duration = ( duration * (100 / 60)) // 1 # convert game's 60fps to gif format's 100fps duration = duration * 10 # convert to 1000ms rate used by PIL Image if duration < 20: duration = 20 # minimum render duration finalized_durations.append(duration) # determine tile and colors for this animation frame tile = source_tile.filename if (tile is None or tile == 'default') else tile detail = source_tile.raw_detailcolor if (detail is None or detail == 'default') \ else detail # Some complexity follows: if ColorStringAnimationFrames is not specified or is # 'default', the game uses the Render part ColorString and does NOT touch TileColor. # However, if ColorStringAnimationFrames IS specified, the game will (effectively) set # the specified color to BOTH ColorString and TileColor: animation_color_is_unspecified = (color is None or color == 'default') color = source_tile.colorstring if animation_color_is_unspecified else color tile_color = source_tile.raw_tilecolor if animation_color_is_unspecified else color # create tile qud_tile = QudTile(tile, color, tile_color, detail, source_tile.qudname, source_tile.raw_transparent) finalized_tiles.append(qud_tile) # generate GIF self._make_gif(finalized_tiles, finalized_durations)
def tile(self) -> QudTile: """Return a QudTile colored to match the in-game representation. Created on-demand to speed load times; cached in self._tile after first call.""" if self._tile is not None: return self._tile tile = None # not all objects have tiles if self.part_Render_Tile and not self.tag_BaseObject: holo_parts = [ 'part_HologramMaterial', 'part_HologramWallMaterial', 'part_HologramMaterialPrimary' ] if (any(self.is_specified(part) for part in holo_parts) or self.name == "Wraith-Knight Templar"): # special handling for holograms color = '&B' tilecolor = '&B^b' detail = 'b' trans = 'transparent' elif self.is_specified('part_AnimatedMaterialStasisfield'): color = '&C^M' tilecolor = '&C^M' detail = 'M' trans = 'M' else: color = self.part_Render_ColorString tilecolor = self.part_Render_TileColor # default detail color when unspecified is black (0, 0, 0) # which matches the overlay UI inventory rendering # ------------------------------------ detail = self.part_Render_DetailColor # below uses logic similar to non-overlay UI where default ('k') is # essentially invisible/transparent against the default background color ('k') # ------------------------------------ # _ = self.part_Render_DetailColor # detail = _ if _ else 'transparent' trans = 'transparent' if self.is_specified('tag_PaintedWall' ) and self.tag_PaintedWall_Value != "*delete": # special handling for painted walls if detail is None and '^' in color: trans = color.split('^', 1)[1] _ = self.tag_PaintedWallAtlas_Value tileloc = _ if _ else 'Tiles/' _ = self.tag_PaintedWallExtension_Value tileext = _ if _ and self.name != 'Dirt' else '.bmp' tile = QudTile(tileloc + self.tag_PaintedWall_Value + '-00000000' + tileext, color, tilecolor, detail, self.name, raw_transparent=trans) elif self.is_specified( 'tag_PaintedFence' ) and self.tag_PaintedFence_Value != "*delete": # special handling for painted fences if detail is None and '^' in color: trans = color.split('^', 1)[1] _ = self.tag_PaintedFenceAtlas_Value tileloc = _ if _ else 'Tiles/' _ = self.tag_PaintedFenceExtension_Value tileext = _ if _ else '.bmp' tile = QudTile(tileloc + self.tag_PaintedFence_Value + "_" + tileext, color, tilecolor, detail, self.name, raw_transparent=trans) else: # normal rendering tile = QudTile(self.part_Render_Tile, color, tilecolor, detail, self.name) self._tile = tile return tile