Move to settings dropdown instead of category buttons, add Buffalo Fractal, fix settings issue

This commit is contained in:
csd4ni3l
2025-06-25 20:05:33 +02:00
parent 81e60e5862
commit 333e5a23e8
6 changed files with 65 additions and 20 deletions

View File

@@ -1,3 +1,3 @@
Fractal viewer in Python using compute shaders and the Arcade and Pyglet modules.
Currently supports Julia, multi-Julia, Mandelbrot, Multibrot, Mandelbar, multi-Mandelbar, Phoenix Fractal, Lambda Fractal, Burning Ship, Newton Fractal and the Sierpinsky Carpet.
Currently supports Julia, multi-Julia, Mandelbrot, Multibrot, Mandelbar, multi-Mandelbar, Buffalo Fractal, Phoenix Fractal, Lambda Fractal, Burning Ship, Newton Fractal and the Sierpinsky Carpet.

View File

@@ -35,7 +35,7 @@ class IterFractalViewer(arcade.gui.UIView):
int(self.settings_dict.get(f"{self.fractal_name}_escape_radius", 2)),
self.settings_dict.get("julia_type", "Classic swirling")
)
self.fractal_sprite = pyglet.sprite.Sprite(img=self.fractal_image)
self.create_image()

View File

@@ -206,6 +206,39 @@ multi_mandelbar_calc = """int calculate_iters(vec2 c) {{
}}
"""
buffalo_fractal_calc = """int calculate_iters({vec2type} c) {{
int iters = 0;
{vec2type} z = {vec2type}(0.0, 0.0);
{floattype} R = {escape_radius};
while (dot(z, z) < R * R && iters < u_maxIter) {{
{floattype} z_squared_real = z.x * z.x - z.y * z.y;
{floattype} z_squared_imag = 2.0 * z.x * z.y;
z = {vec2type}(abs(z_squared_real) + c.x, abs(z_squared_imag) + c.y);
iters++;
}}
return iters;
}}
"""
multi_buffalo_fractal_calc = """int calculate_iters(vec2 c) {{
int iters = 0;
vec2 z = vec2(0.0);
float n = {multi_n};
float R = {escape_radius};
while (dot(z, z) < R * R && iters < u_maxIter) {{
float r = length(z);
float theta = atan(z.y, z.x);
float r_n = pow(r, n);
float theta_n = n * theta;
float zn_real = r_n * cos(theta_n);
float zn_imag = r_n * sin(theta_n);
z = vec2(abs(zn_real) + c.x, abs(zn_imag) + c.y);
iters++;
}}
return iters;
}}
"""
burning_ship_calc = """int calculate_iters({vec2type} c) {{
int iters = 0;
{vec2type} z = {vec2type}(0.0, 0.0);
@@ -375,6 +408,13 @@ def create_iter_calc_shader(fractal_type, width, height, precision="single", mul
else:
replacements["iter_calc_func"] = multi_julia_calc.format_map(replacements)
elif fractal_type == "buffalo_fractal":
replacements["coloring_func"] = fire_coloring.format_map(replacements)
if int(multi_n) == 2:
replacements["iter_calc_func"] = buffalo_fractal_calc.format_map(replacements)
else:
replacements["iter_calc_func"] = multi_buffalo_fractal_calc.format_map(replacements)
elif fractal_type == "burning_ship":
replacements["coloring_func"] = fire_coloring.format_map(replacements)
replacements["iter_calc_func"] = burning_ship_calc.format_map(replacements)

View File

@@ -16,7 +16,7 @@ class FractalChooser(arcade.gui.UIView):
self.grid = self.add_widget(arcade.gui.UIGridLayout(row_count=4, column_count=3, horizontal_spacing=10, vertical_spacing=10))
self.anchor.add(self.grid, anchor_x="center", anchor_y="center")
def on_show_view(self):
super().on_show_view()

View File

@@ -56,19 +56,16 @@ class Settings(arcade.gui.UIView):
self.display_category(settings_start_category)
def display_categories(self):
for category in settings:
category_button = arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text=category, style=button_style, width=self.window.width / 13, height=50)
if not category == "Credits":
category_button.on_click = lambda e, category=category: self.display_category(category)
else:
category_button.on_click = lambda e: self.credits()
self.top_box.add(category_button)
self.settings_dropdown = self.anchor.add(arcade.gui.UIDropdown(options=list(settings.keys()), default=settings_start_category, primary_style=dropdown_style, active_style=dropdown_style, dropdown_style=dropdown_style, width=self.window.width / 1.5, height=self.window.height / 20), anchor_x="center", anchor_y="top", align_y=-10)
self.settings_dropdown.on_change = lambda event: self.display_category(event.new_value)
self.anchor.detect_focusable_widgets()
def display_category(self, category):
if category == "Credits":
self.credits()
return
if hasattr(self, 'apply_button'):
self.anchor.remove(self.apply_button)
del self.apply_button
@@ -94,7 +91,7 @@ class Settings(arcade.gui.UIView):
self.value_layout.add(dropdown)
elif setting_dict['type'] == "bool":
button_layout = self.value_layout.add(arcade.gui.arcade.gui.UIBoxLayout(space_between=50, vertical=False))
button_layout = self.value_layout.add(arcade.gui.UIBoxLayout(space_between=50, vertical=False))
on_radiobutton = arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text="ON", style=button_style, width=150, height=50)
self.on_radiobuttons[setting] = on_radiobutton

View File

@@ -12,6 +12,7 @@ initial_real_imag = {
"mandelbar": (-2.0, 1.0, -1.0, 1.0),
"phoenix_fractal": (-2.0, 1.0, -1.0, 1.0),
"lambda_fractal": (-2.0, 1.0, -1.0, 1.0),
"buffalo_fractal": (-2.0, 1.5, -2.0, 1.0),
"burning_ship": (-2.0, 1.5, -2.0, 1.0),
"newton_fractal": (-2.0, 2.0, -2.0, 2.0)
}
@@ -23,7 +24,7 @@ c_for_julia_type = {
"Snowflake": (-0.8, 0.156)
}
iter_fractals = ["mandelbrot", "mandelbar", "phoenix_fractal", "lambda_fractal", "julia", "burning_ship", "newton_fractal"]
iter_fractals = ["mandelbrot", "mandelbar", "phoenix_fractal", "lambda_fractal", "julia", "burning_ship", "buffalo_fractal", "newton_fractal"]
button_style = {'normal': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), 'hover': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK),
'press': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), 'disabled': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK)}
@@ -53,6 +54,19 @@ settings = {
"Zoom Increase Per Click": {"type": "slider", "min": 2, "max": 100, "config_key": "mandelbar_zoom_increase", "default": 2},
"Max Iterations": {"type": "slider", "min": 100, "max": 10000, "config_key": "mandelbar_max_iter", "default": 200, "step": 100}
},
"Burning Ship": {
"Float Precision": {"type": "option", "options": ["Single", "Double"], "config_key": "burning_ship_precision", "default": "Single"},
"Escape Radius": {"type": "slider", "min": 1, "max": 10, "config_key": "burning_ship_escape_radius", "default": 2, "step": 0.1},
"Zoom Increase Per Click": {"type": "slider", "min": 2, "max": 100, "config_key": "burning_ship_zoom_increase", "default": 2},
"Max Iterations": {"type": "slider", "min": 100, "max": 10000, "config_key": "burning_ship_max_iter", "default": 200, "step": 100}
},
"Buffalo Fractal": {
"Float Precision": {"type": "option", "options": ["Single", "Double"], "config_key": "buffalo_fractal_precision", "default": "Single"},
"N": {"type": "slider", "min": 1, "max": 10, "config_key": "buffalo_fractal_n", "default": 2, "step": 1},
"Escape Radius": {"type": "slider", "min": 1, "max": 10, "config_key": "buffalo_fractal_escape_radius", "default": 2, "step": 0.1},
"Zoom Increase Per Click": {"type": "slider", "min": 2, "max": 100, "config_key": "buffalo_fractal_zoom_increase", "default": 2},
"Max Iterations": {"type": "slider", "min": 100, "max": 10000, "config_key": "buffalo_fractal_max_iter", "default": 200, "step": 100}
},
"Phoenix Fractal": {
"Float Precision": {"type": "option", "options": ["Single", "Double"], "config_key": "phoenix_fractal_precision", "default": "Single"},
"Escape Radius": {"type": "slider", "min": 1, "max": 10, "config_key": "phoenix_fractal_escape_radius", "default": 2, "step": 0.1},
@@ -65,12 +79,6 @@ settings = {
"Zoom Increase Per Click": {"type": "slider", "min": 2, "max": 100, "config_key": "phoenix_fractal_zoom_increase", "default": 2},
"Max Iterations": {"type": "slider", "min": 100, "max": 10000, "config_key": "phoenix_fractal_max_iter", "default": 200, "step": 100}
},
"Burning Ship": {
"Float Precision": {"type": "option", "options": ["Single", "Double"], "config_key": "burning_ship_precision", "default": "Single"},
"Escape Radius": {"type": "slider", "min": 1, "max": 10, "config_key": "burning_ship_escape_radius", "default": 2, "step": 0.1},
"Zoom Increase Per Click": {"type": "slider", "min": 2, "max": 100, "config_key": "burning_ship_zoom_increase", "default": 2},
"Max Iterations": {"type": "slider", "min": 100, "max": 10000, "config_key": "burning_ship_max_iter", "default": 200, "step": 100}
},
"Sierpinsky Carpet": {
"Float Precision": {"type": "option", "options": ["Single", "Double"], "config_key": "sierpinsky_precision", "default": "Single"},
"Zoom Increase Per Click": {"type": "slider", "min": 2, "max": 100, "config_key": "sierpinsky_zoom_increase", "default": 2},