Created
October 31, 2024 16:28
-
-
Save TheNextGuy32/8869694263ca12209f687c8ad19d087a to your computer and use it in GitHub Desktop.
Can you help me write idiomatic Godot code?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extends Node3D | |
var base_url: String = "http://127.0.0.1:5000" | |
var roblox_user_id: String = "427590401" | |
func _ready(): | |
var http_request = HTTPRequest.new() | |
add_child(http_request) | |
http_request.request_completed.connect(_on_get_owned_items_completed) | |
var url = base_url + "/items/moderation_status?moderationStatus=APPROVED&pageSize=16" | |
# http_request.request(url) | |
func _on_get_owned_items_completed(result, response_code, headers, body): | |
if result != HTTPRequest.RESULT_SUCCESS: | |
emit_signal("load_error", "Request failed with code: " + str(result)) | |
return | |
if response_code != 200: | |
emit_signal("load_error", "Server returned error code: " + str(response_code)) | |
return | |
var json = JSON.parse_string(body.get_string_from_utf8()) | |
var items = json["items"] # Assuming the response has an "items" key | |
var num_items = items.size() | |
var grid_size = ceil(sqrt(num_items)) | |
var spacing = 18 | |
var total_width = grid_size * spacing | |
var total_height = grid_size * spacing | |
var offset_x = -total_width / 2 | |
var offset_y = -total_height / 2 | |
for i in range(num_items): | |
var row = floor(i / grid_size) | |
var col = i % int(grid_size) | |
var x_pos = col * spacing + offset_x | |
var y_pos = row * spacing + offset_y | |
var item = items[i] | |
var components = JSON.parse_string(item["components"]) | |
if components.has("ImageGuid") && components.has("RenderExtrusion"): | |
var renderExtrusion = components["RenderExtrusion"] | |
create_mesh_extrusion(Vector3(x_pos, y_pos, 0), components["ImageGuid"]["Image Guid"], renderExtrusion) | |
func create_mesh_extrusion(pos: Vector3, guid: String, render_extrusion: Dictionary) -> MeshInstance3D: | |
var mesh_instance = MeshInstance3D.new() | |
add_child(mesh_instance) | |
var transform = Transform3D.IDENTITY | |
transform.origin = pos | |
mesh_instance.transform = transform | |
# Set up the script | |
var script = load("res://MeshExtrusion.gd") | |
mesh_instance.set_script(script) | |
mesh_instance.image_guid = guid | |
mesh_instance.render_extrusion = render_extrusion | |
mesh_instance._ready() | |
return mesh_instance |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extends MeshInstance3D | |
signal mesh_loaded(mesh_instance) | |
signal load_error(error_message) | |
var base_url: String = "http://127.0.0.1:5000" | |
@export var image_guid: String = "" | |
@export var render_extrusion: Dictionary = {} | |
func _ready(): | |
if image_guid.is_empty(): | |
push_error("[MeshInstance3D] No image_guid provided") | |
return | |
request_mesh() | |
func request_mesh(): | |
var http_request = HTTPRequest.new() | |
add_child(http_request) | |
http_request.request_completed.connect(_on_request_completed) | |
http_request.request(base_url + "/image?imageGuid=" + image_guid) | |
func _on_request_completed(result, response_code, headers, body): | |
if result != HTTPRequest.RESULT_SUCCESS: | |
emit_signal("load_error", "Request failed with code: " + str(result)) | |
return | |
if response_code != 200: | |
emit_signal("load_error", "Server returned error code: " + str(response_code)) | |
return | |
var json = JSON.parse_string(body.get_string_from_utf8()) | |
var imageObject = json["image"] | |
var colorString = imageObject["image"] | |
mesh = VoxelMeshGenerator.generate_mesh(colorString, render_extrusion) | |
emit_signal("mesh_loaded", self) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class_name VoxelMeshGenerator | |
extends RefCounted | |
const VOXEL_SIZE = 1 | |
static func parse_color_data(input_string: String) -> Array: | |
var colors = [] | |
var color_strings = input_string.split(";") | |
# First convert all strings to Color objects | |
for color_str in color_strings: | |
var components = color_str.split(",") | |
if components.size() == 4: | |
var r = float(components[0]) | |
var g = float(components[1]) | |
var b = float(components[2]) | |
var a = 1 - float(components[3]) # Invert alpha | |
colors.append(Color(r, g, b, a)) | |
# Then convert to 2D array | |
var image_colors = [] | |
var index = 0 | |
for i in range(16): | |
var row = [] | |
for j in range(16): | |
row.append(colors[index]) | |
index += 1 | |
image_colors.append(row) | |
return image_colors | |
static func generate_mesh(color_data_string: String, render_extrusion: Dictionary) -> Mesh: | |
# Parse size and position from render_extrusion | |
var size_str = render_extrusion.get("Size", "16,16,16").split(",") | |
var size = Vector3(float(size_str[0]), float(size_str[1]), float(size_str[2])) | |
size *= VOXEL_SIZE | |
var pos_str = render_extrusion.get("Position", "0,0,0").split(",") | |
var rel_pos = Vector3(float(pos_str[0]), float(pos_str[1]), float(pos_str[2])) | |
rel_pos *= VOXEL_SIZE | |
# Create material | |
var mat = StandardMaterial3D.new() | |
mat.vertex_color_use_as_albedo = true | |
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED | |
var image_colors = parse_color_data(color_data_string) | |
var surface_tool = SurfaceTool.new() | |
surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES) | |
surface_tool.set_material(mat) | |
# Create a 3D array to easily check neighbors | |
var voxels = [] | |
for y in range(16): | |
var plane = [] | |
for x in range(16): | |
plane.append(image_colors[15-y][x]) | |
voxels.append(plane) | |
# Calculate offset to center the mesh | |
var offset_x = 0 #-8.0 # Half of 16 | |
var offset_y = 0 #-8.0 # Half of 16 | |
for y in range(16): | |
for x in range(16): | |
var color = voxels[y][x] | |
if color.a == 0: | |
continue | |
var transform = Transform3D(Basis(), Vector3(x + offset_x, y + offset_y, 0) + rel_pos) | |
add_optimized_box(surface_tool, transform, Vector2(size.x/16, size.y/16), size.z, color, voxels, x, y) | |
surface_tool.generate_normals() | |
return surface_tool.commit() | |
static func has_neighbor(voxels: Array, x: int, y: int, dx: int, dy: int) -> bool: | |
var nx = x + dx | |
var ny = y + dy | |
if nx < 0 or nx >= 16 or ny < 0 or ny >= 16: | |
return false | |
return voxels[ny][nx].a > 0 | |
static func add_optimized_box(surface_tool: SurfaceTool, transform: Transform3D, size: Vector2, depth: float, color: Color, voxels: Array, x: int, y: int): | |
# Scale the transform's origin by the voxel size to position voxels correctly | |
var scalingSize = Vector3(size.x, size.y, depth) | |
var scaled_transform = transform | |
scaled_transform.origin = transform.origin * scalingSize | |
var vertices = [ | |
Vector3(-0.5, -0.5, -0.5), | |
Vector3( 0.5, -0.5, -0.5), | |
Vector3( 0.5, 0.5, -0.5), | |
Vector3(-0.5, 0.5, -0.5), | |
Vector3(-0.5, -0.5, 0.5), | |
Vector3( 0.5, -0.5, 0.5), | |
Vector3( 0.5, 0.5, 0.5), | |
Vector3(-0.5, 0.5, 0.5) | |
] | |
# Use scaled_transform instead of transform | |
for i in range(vertices.size()): | |
vertices[i] = scaled_transform * (vertices[i] * scalingSize) | |
# Only add faces if there's no neighbor in that direction | |
var faces = [] | |
# Back face (facing negative Z) | |
faces.append([vertices[0], vertices[1], vertices[2], vertices[3]]) # Reversed winding order | |
# Front face (facing positive Z) | |
faces.append([vertices[5], vertices[4], vertices[7], vertices[6]]) # Reversed winding order | |
# Bottom face (facing negative Y) | |
if not has_neighbor(voxels, x, y, 0, -1): | |
faces.append([vertices[1], vertices[0], vertices[4], vertices[5]]) | |
# Top face (facing positive Y) | |
if not has_neighbor(voxels, x, y, 0, 1): | |
faces.append([vertices[3], vertices[2], vertices[6], vertices[7]]) | |
# Right face (facing positive X) | |
if not has_neighbor(voxels, x, y, 1, 0): | |
faces.append([vertices[2], vertices[1], vertices[5], vertices[6]]) | |
# Left face (facing negative X) | |
if not has_neighbor(voxels, x, y, -1, 0): | |
faces.append([vertices[0], vertices[3], vertices[7], vertices[4]]) | |
# Add only the necessary faces to the mesh | |
for face in faces: | |
surface_tool.set_color(color) | |
surface_tool.add_vertex(face[0]) | |
surface_tool.add_vertex(face[1]) | |
surface_tool.add_vertex(face[2]) | |
surface_tool.add_vertex(face[2]) | |
surface_tool.add_vertex(face[3]) | |
surface_tool.add_vertex(face[0]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment