16.09.2024, 12:54
(Dieser Beitrag wurde zuletzt bearbeitet: 16.09.2024, 13:12 von Manfred Aabye.)
Jetzt gibt es 14 Spirale-Typen.
Einige Fehler behoben.
Erste Windows Version verfügbar: DOWNLOAD
Einige Fehler behoben.
Erste Windows Version verfügbar: DOWNLOAD
PHP-Code:
import tkinter as tk
from tkinter import messagebox, filedialog
import configparser
import uuid
import math
import random
# Erweiterte Listen mit Vorsilben und Nachsilben
VORSILBE = [
"Alt", "Augs", "Ber", "Biele", "Dort", "Dres", "Duel", "Er", "Frank", "Gos",
"Gör", "Heil", "Hild", "Jena", "Kass", "Kiel", "Köln", "Linz", "Magde", "Mann",
"Mar", "Mittel", "Neu", "Nord", "Ober", "Osna", "Ost", "Reut", "Rost", "Sieger",
"Stutt", "Sued", "Unter", "West", "Neub", "Stein", "Zell", "Trier", "Hagen", "Wert"
]
NACHSILBE = [
"markt", "burg", "lin", "feld", "mund", "den", "len", "men", "furt", "lar",
"litz", "bronn", "heim", "er", "el", "ken", "Rhein", "Delhi", "Hessen", "Bayern",
"Pfalz", "brück", "land", "Harz", "lingen", "ock", "land", "gart", "Baden",
"Tirol", "Franken", "Sachsen", "Falen", "ner", "stein", "stadt", "bach", "tal",
"hof", "en", "ring"
]
def generate_random_name():
# Wählt zufällig eine Vorsilbe und eine Nachsilbe aus
vorsilbe = random.choice(VORSILBE)
nachsilbe = random.choice(NACHSILBE)
# Generiert den Namen durch Verknüpfung der Vorsilbe und Nachsilbe
name = vorsilbe + nachsilbe
return name
# Custom ConfigParser class to preserve key case sensitivity
class CaseConfigParser(configparser.ConfigParser):
def optionxform(self, optionstr):
return optionstr # Keep original case
class RegionConfigApp:
def __init__(self, root):
self.root = root
self.index = 0
# Set window icon
#self.root.iconbitmap("icon.ico")
# Set window title
self.root.title("Region Configurations")
# Set window size
self.root.geometry("450x700")
# Initialize variables with default values
self.region_name = tk.StringVar(value=generate_random_name())
self.region_uuid = tk.StringVar(value=str(uuid.uuid4()))
self.maptile_uuid = tk.StringVar(value=self.region_uuid.get())
# Location variable for grid position
self.location = tk.StringVar(value="1000,1000")
self.size = tk.IntVar(value=256)
self.internal_port = tk.IntVar(value=9050)
self.external_host = tk.StringVar(value="SYSTEMIP")
self.max_prims = tk.IntVar(value=100000)
self.max_agents = tk.IntVar(value=99)
self.internal_address = tk.StringVar(value="0.0.0.0")
self.allow_alt_ports = tk.BooleanVar(value=False)
self.non_physical_prim_max = tk.IntVar(value=256)
self.physical_prim_max = tk.IntVar(value=64)
# New variables for additional settings
self.clamp_prim_size = tk.BooleanVar(value=False)
self.max_prims_per_user = tk.IntVar(value=-1)
self.scope_id = tk.StringVar(value=self.region_uuid.get())
self.region_type = tk.StringVar(value="")
self.render_min_height = tk.IntVar(value=-1)
self.render_max_height = tk.IntVar(value=100)
self.maptile_static_file = tk.StringVar(value="SomeFile.png")
self.master_avatar_first_name = tk.StringVar(value="John")
self.master_avatar_last_name = tk.StringVar(value="Doe")
self.master_avatar_sandbox_password = tk.StringVar(value="passwd")
self.region_count = 0 # Start at 0
self.angle = 0
self.radius = 1 # Initial radius for spirals
self.locations = [] # List to store locations of all regions
# Variable for selecting spiral type
self.spiral_type = tk.StringVar(value="flower") # Default to "flower"
# Trace changes to region_uuid to update maptile_uuid accordingly
self.region_uuid.trace_add('write', self.update_maptile_uuid)
# Build the UI
self.build_ui()
def update_maptile_uuid(self, *args):
self.maptile_uuid.set(self.region_uuid.get())
def build_ui(self):
canvas = tk.Canvas(self.root)
scrollbar = tk.Scrollbar(self.root, orient="vertical", command=canvas.yview)
scrollable_frame = tk.Frame(canvas)
scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")
)
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
fields = [
("Region Name:", self.region_name),
("Region UUID:", self.region_uuid),
("Location:", self.location),
("Size:", self.size),
("Internal Port:", self.internal_port),
("External Host:", self.external_host),
("Max Prims:", self.max_prims),
("Max Agents:", self.max_agents),
("Maptile UUID:", self.maptile_uuid),
("Internal Address:", self.internal_address),
("Allow Alternate Ports:", self.allow_alt_ports),
("Non-Physical Prim Max:", self.non_physical_prim_max),
("Physical Prim Max:", self.physical_prim_max),
("Clamp Prim Size:", self.clamp_prim_size),
("Max Prims Per User:", self.max_prims_per_user),
("Scope ID:", self.scope_id),
("Region Type:", self.region_type),
("Render Min Height:", self.render_min_height),
("Render Max Height:", self.render_max_height),
("Maptile Static File:", self.maptile_static_file),
("Master Avatar First Name:", self.master_avatar_first_name),
("Master Avatar Last Name:", self.master_avatar_last_name),
("Master Avatar Sandbox Password:", self.master_avatar_sandbox_password),
]
for idx, (label_text, var) in enumerate(fields):
if isinstance(var, tk.BooleanVar):
tk.Checkbutton(scrollable_frame, text=label_text, variable=var).grid(row=idx, column=0, columnspan=2, sticky=tk.W, pady=2, padx=5)
else:
tk.Label(scrollable_frame, text=label_text).grid(row=idx, column=0, sticky=tk.W, pady=2, padx=5)
entry = tk.Entry(scrollable_frame, textvariable=var, width=40)
entry.grid(row=idx, column=1, sticky=tk.W, pady=2, padx=5)
# Dropdown for spiral selection
self.spiral_type = tk.StringVar(value="flower") # Fix: Make sure the initial value of self.spiral_type is set correctly, which is already done with the line
tk.Label(scrollable_frame, text="Spiral Type:").grid(row=len(fields), column=0, sticky=tk.W, pady=2, padx=5)
spiral_menu = tk.OptionMenu(scrollable_frame, self.spiral_type, "archimedean_spiral1", "archimedean_spiral2", "circle1", "circle2", "fibonacci_spiral", "flower", "grid1", "grid2", "logarithmic_spiral", "logistic", "random1", "random2", "star")
spiral_menu.grid(row=len(fields), column=1, sticky=tk.W, pady=2, padx=5)
button_frame = tk.Frame(scrollable_frame)
button_frame.grid(row=len(fields) + 1, column=0, columnspan=2, pady=10)
tk.Button(button_frame, text="Add Region", command=self.add_region).pack(side="left", padx=10)
tk.Button(button_frame, text="Save Config", command=self.save_config).pack(side="left", padx=10)
def next_flower_spiral_location1(self):
# Calculate the next position using a flower-like spiral
self.angle += 137.5 # Golden angle in degrees
radians = math.radians(self.angle)
location_x = 1000 + int(self.radius * math.cos(radians))
location_y = 1000 + int(self.radius * math.sin(radians))
self.radius += 1 # Increment the radius gradually for the next point
return location_x, location_y
def next_fibonacci_spiral_location(self):
# Calculate the next position using the Fibonacci spiral
self.angle += 137.5 # Golden angle in degrees
radians = math.radians(self.angle)
self.radius *= 1.618 # Fibonacci increment
location_x = 1000 + int(self.radius * math.cos(radians))
location_y = 1000 + int(self.radius * math.sin(radians))
return location_x, location_y
def next_archimedean_spiral_location2(self):
self.angle += 10 # Increment angle by a fixed value
radians = math.radians(self.angle)
location_x = 1000 + int(self.radius * math.cos(radians))
location_y = 1000 + int(self.radius * math.sin(radians))
self.radius += 10 # Increment the radius linearly for a smooth spiral
return location_x, location_y
def next_logarithmic_spiral_location(self):
self.angle += 10 # Increase angle gradually
radians = math.radians(self.angle)
self.radius *= 1.1 # Exponentially increase the radius
location_x = 1000 + int(self.radius * math.cos(radians))
location_y = 1000 + int(self.radius * math.sin(radians))
return location_x, location_y
def next_random_location1(self):
location_x = random.randint(0, 2000)
location_y = random.randint(0, 2000)
return location_x, location_y
def next_grid_location1(self):
location_x = 1000 + (self.index % 10) * 100 # Move horizontally
location_y = 1000 + (self.index // 10) * 100 # Move vertically
self.index += 1
return location_x, location_y
def next_circle_location1(self):
self.angle += 36 # Divide 360 degrees by 10 points
radians = math.radians(self.angle)
radius = 500 # Constant radius
location_x = 1000 + int(radius * math.cos(radians))
location_y = 1000 + int(radius * math.sin(radians))
return location_x, location_y
def next_star_location(self):
self.angle += 144 # Star angle (5 points)
radians = math.radians(self.angle)
location_x = 1000 + int(self.radius * math.cos(radians))
location_y = 1000 + int(self.radius * math.sin(radians))
return location_x, location_y
def next_logistic_function_location(self):
self.angle += 10
radians = math.radians(self.angle)
K = 2000 # Carrying capacity (limit of growth)
location_x = 1000 + int(self.radius * (K / (1 + math.exp(-0.1 * self.angle))) * math.cos(radians))
location_y = 1000 + int(self.radius * (K / (1 + math.exp(-0.1 * self.angle))) * math.sin(radians))
return location_x, location_y
def next_grid_location2(self):
# Define grid parameters
grid_size = 100 # Distance between grid points
num_columns = 10 # Number of columns in the grid
# Calculate row and column based on the current index
row = self.index // num_columns
column = self.index % num_columns
# Calculate the x, y position
location_x = 1000 + column * grid_size
location_y = 1000 + row * grid_size
# Increment the index for the next call
self.index += 1
return location_x, location_y
def next_circle_location2(self):
num_points = 20 # Total number of points on the circle
radius = 200 # Fixed radius of the circle
# Calculate the angle for the current point
angle = (2 * math.pi / num_points) * self.index
location_x = 1000 + int(radius * math.cos(angle))
location_y = 1000 + int(radius * math.sin(angle))
# Increment the index for the next call
self.index += 1
return location_x, location_y
def next_archimedean_spiral_location1(self):
# Increase the angle
self.angle += 10 # Change the step size for tighter or looser spirals
radians = math.radians(self.angle)
# Archimedean spiral equation: r = a + b * theta
a = 5 # Adjust this value for initial distance from the center
b = 5 # Adjust for spacing between spiral arms
self.radius = a + b * self.angle
location_x = 1000 + int(self.radius * math.cos(radians))
location_y = 1000 + int(self.radius * math.sin(radians))
return location_x, location_y
def next_random_location2(self):
# Define the bounds for random placement
location_x = random.randint(800, 1200)
location_y = random.randint(800, 1200)
return location_x, location_y
def add_region(self):
# Determine which spiral to use
location = None
if self.spiral_type.get() == "flower":
location = self.next_flower_spiral_location1()
elif self.spiral_type.get() == "fibonacci_spiral":
location = self.next_fibonacci_spiral_location()
elif self.spiral_type.get() == "archimedean_spiral1":
location = self.next_archimedean_spiral_location1()
elif self.spiral_type.get() == "logarithmic_spiral":
location = self.next_logarithmic_spiral_location()
elif self.spiral_type.get() == "random1":
location = self.next_random_location1()
elif self.spiral_type.get() == "grid1":
location = self.next_grid_location1()
elif self.spiral_type.get() == "circle1":
location = self.next_circle_location1()
elif self.spiral_type.get() == "logistic":
location = self.next_logistic_function_location()
elif self.spiral_type.get() == "star":
location = self.next_star_location()
elif self.spiral_type.get() == "grid2":
location = self.next_grid_location2()
elif self.spiral_type.get() == "circle2":
location = self.next_circle_location2()
elif self.spiral_type.get() == "archimedean_spiral2":
location = self.next_archimedean_spiral_location2()
elif self.spiral_type.get() == "random2":
location = self.next_random_location2()
if location is None:
messagebox.showerror("Error", "No spiral selected")
return
self.locations.append(location)
new_uuid = str(uuid.uuid4())
self.region_count += 1
self.region_name.set(generate_random_name())
self.region_uuid.set(new_uuid)
self.internal_port.set(self.internal_port.get() + 1)
self.location.set(f"{location[0]},{location[1]}") # Update the location
messagebox.showinfo("Region Added", f"Region {self.region_name.get()} added. Location: ({location[0]},{location[1]})")
def save_config(self):
filename = filedialog.asksaveasfilename(defaultextension=".ini", filetypes=[("INI files", "*.ini")])
if not filename:return
if filename:
config = CaseConfigParser() # Use the custom parser to preserve case
for i in range(1, self.region_count + 1):
if i == 1:
region_name = self.region_name.get()
region_uuid = self.region_uuid.get()
location_x, location_y = map(int, self.location.get().split(',')) # First region
else:
region_name = generate_random_name()
region_uuid = str(uuid.uuid4())
location_x, location_y = self.locations[i-1] # Specific location for each region
config[region_name] = {
"RegionUUID": region_uuid,
"Location": f"{location_x},{location_y}",
"SizeX": self.size.get(),
"SizeY": self.size.get(),
"SizeZ": self.size.get(),
"InternalPort": self.internal_port.get() + (i - 1),
"InternalAddress": self.internal_address.get(),
"AllowAlternatePorts": str(self.allow_alt_ports.get()),
"ExternalHostName": self.external_host.get(),
"MaxPrims": self.max_prims.get(),
"MaxAgents": self.max_agents.get(),
"MaxPrimsPerUser": self.max_prims_per_user.get(),
";MaptileStaticUUID": self.maptile_uuid.get(),
";NonPhysicalPrimMax": self.non_physical_prim_max.get(),
";PhysicalPrimMax": self.physical_prim_max.get(),
";ClampPrimSize": str(self.clamp_prim_size.get()),
";ScopeID": self.scope_id.get(),
";RegionType": self.region_type.get(),
";RenderMinHeight": self.render_min_height.get(),
";RenderMaxHeight": self.render_max_height.get(),
";MaptileStaticFile": self.maptile_static_file.get(),
";MasterAvatarFirstName": self.master_avatar_first_name.get(),
";MasterAvatarLastName": self.master_avatar_last_name.get(),
";MasterAvatarSandboxPassword": self.master_avatar_sandbox_password.get(),
}
with open(filename, 'w') as configfile:
config.write(configfile)
messagebox.showinfo("Saved", "Configuration saved successfully.")
if __name__ == "__main__":
root = tk.Tk()
app = RegionConfigApp(root)
root.mainloop()
Ein Metaversum sind viele kleine Räume, die nahtlos aneinander passen,
sowie direkt sichtbar und begehbar sind, als wäre es aus einem Guss.
sowie direkt sichtbar und begehbar sind, als wäre es aus einem Guss.