Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GamePlus-Editor as default level editor #753

Closed
wants to merge 4 commits into from
Closed
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: 8 additions & 0 deletions level_editor/data/level_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import json

class LevelLoader:

@staticmethod
def load_level(file_path):
with open(file_path, "r") as file:
return json.load(file)
8 changes: 8 additions & 0 deletions level_editor/data/level_saver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import json

class LevelSaver:

@staticmethod
def save_level(file_path, level_data):
with open(file_path, "w") as file:
json.dump(level_data, file, indent=4)
56 changes: 56 additions & 0 deletions level_editor/editor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import json

class LevelEditor:

def __init__(self):
self.level_data = []
self.current_level = None

def new_level(self):
self.level_data = []
self.current_level = None
print("New level created")

def load_level(self, file_path):
try:
with open(file_path, 'r') as file:
self.level_data = json.load(file)
self.current_level = file_path
print(f"Level loaded from {file_path}")
except Exception as e:
print(f"Failed to load level: {e}")

def save_level(self, file_path):
try:
with open(file_path, 'w') as file:
json.dump(self.level_data, file, indent=4)
self.current_level = file_path
print(f"Level saved to {file_path}")
except Exception as e:
print(f"Failed to save level: {e}")

def add_object(self, obj):
self.level_data.append(obj)
print(f"Object {obj} added to the level")

def remove_object(self, obj):
if obj in self.level_data:
self.level_data.remove(obj)
print(f"Object {obj} removed from the level")
else:
print(f"Object {obj} not found in the level")

def modify_object(self, obj, new_obj):
if obj in self.level_data:
index = self.level_data.index(obj)
self.level_data[index] = new_obj
print(f"Object {obj} modified to {new_obj}")
else:
print(f"Object {obj} not found in the level")

def run(self):
print("Running Level Editor...")

if __name__ == "__main__":
editor = LevelEditor()
editor.run()
13 changes: 13 additions & 0 deletions level_editor/file_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import json

class FileManager:

@staticmethod
def save_level(file_path, level_data):
with open(file_path, "w") as file:
json.dump(level_data, file, indent=4)

@staticmethod
def load_level(file_path):
with open(file_path, "r") as file:
return json.load(file)
15 changes: 15 additions & 0 deletions level_editor/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import os

def open_level_editor():
os.system("python level_editor/editor.py")

def start_level_editor():
print("Starting Level Editor...")
open_level_editor()

if __name__ == "__main__":
print("1. Start Game")
print("2. Open Level Editor")
choice = input("Choose an option: ")
if choice == "2":
start_level_editor()
13 changes: 13 additions & 0 deletions level_editor/tools/object_placer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class ObjectPlacer:

def __init__(self, canvas):
self.canvas = canvas
self.objects = []

def place_object(self, event):
obj = self.canvas.create_rectangle(event.x, event.y, event.x + 20, event.y + 20, fill="blue")
self.objects.append(obj)
print(f"Placed object at {event.x}, {event.y}")

def enable(self):
self.canvas.bind("<Button-1>", self.place_object)
41 changes: 41 additions & 0 deletions level_editor/tools/object_rotator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import math

class ObjectRotator:

def __init__(self, canvas):
self.canvas = canvas

def rotate_object(self, obj, angle):
coords = self.canvas.coords(obj)
center_x = (coords[0] + coords[2]) / 2
center_y = (coords[1] + coords[3]) / 2
new_coords = []

for i in range(0, len(coords), 2):
x, y = coords[i], coords[i+1]
new_x = center_x + (x - center_x) * math.cos(angle) - (y - center_y) * math.sin(angle)
new_y = center_y + (x - center_x) * math.sin(angle) + (y - center_y) * math.cos(angle)
new_coords.extend([new_x, new_y])

self.canvas.coords(obj, *new_coords)
print(f"Rotated object {obj} by {angle} degrees")

def enable(self):
self.canvas.bind("<Button-2>", self.start_rotating)
self.canvas.bind("<B2-Motion>", self.perform_rotating)
self.canvas.bind("<ButtonRelease-2>", self.stop_rotating)
self.rotating = False

def start_rotating(self, event):
self.rotating = True
self.start_x = event.x
self.start_y = event.y

def perform_rotating(self, event):
if self.rotating:
angle = math.atan2(event.y - self.start_y, event.x - self.start_x)
obj = self.canvas.find_closest(self.start_x, self.start_y)
self.rotate_object(obj, angle)

def stop_rotating(self, event):
self.rotating = False
30 changes: 30 additions & 0 deletions level_editor/tools/object_scaler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class ObjectScaler:

def __init__(self, canvas):
self.canvas = canvas

def scale_object(self, obj, scale_factor):
coords = self.canvas.coords(obj)
new_coords = [coords[0], coords[1], coords[2] * scale_factor, coords[3] * scale_factor]
self.canvas.coords(obj, *new_coords)
print(f"Scaled object {obj} by {scale_factor}")

def enable(self):
self.canvas.bind("<Button-3>", self.start_scaling)
self.canvas.bind("<B3-Motion>", self.perform_scaling)
self.canvas.bind("<ButtonRelease-3>", self.stop_scaling)
self.scaling = False

def start_scaling(self, event):
self.scaling = True
self.start_x = event.x
self.start_y = event.y

def perform_scaling(self, event):
if self.scaling:
scale_factor = (event.x - self.start_x) / 100
obj = self.canvas.find_closest(self.start_x, self.start_y)
self.scale_object(obj, scale_factor)

def stop_scaling(self, event):
self.scaling = False
38 changes: 38 additions & 0 deletions level_editor/ui/editor_window.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from tkinter import Tk, Menu, Frame, Button

class EditorWindow:

def __init__(self):
self.root = Tk()
self.root.title("Level Editor")
self.create_menu()
self.create_layout()

def create_menu(self):
menu_bar = Menu(self.root)
file_menu = Menu(menu_bar, tearoff=0)
file_menu.add_command(label="New Level")
file_menu.add_command(label="Load Level")
file_menu.add_command(label="Save Level")
menu_bar.add_cascade(label="File", menu=file_menu)
self.root.config(menu=menu_bar)

def create_layout(self):
self.frame = Frame(self.root)
self.frame.pack()

self.place_button = Button(self.frame, text="Place Object")
self.place_button.pack()

self.scale_button = Button(self.frame, text="Scale Object")
self.scale_button.pack()

self.rotate_button = Button(self.frame, text="Rotate Object")
self.rotate_button.pack()

def run(self):
self.root.mainloop()

if __name__ == "__main__":
window = EditorWindow()
window.run()
20 changes: 20 additions & 0 deletions level_editor/ui/tool_panel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from tkinter import Frame, Button

class ToolPanel:

def __init__(self, parent):
self.frame = Frame(parent)
self.create_tools()

def create_tools(self):
place_button = Button(self.frame, text="Place Object")
place_button.pack()

scale_button = Button(self.frame, text="Scale Object")
scale_button.pack()

rotate_button = Button(self.frame, text="Rotate Object")
rotate_button.pack()

def pack(self):
self.frame.pack()
62 changes: 62 additions & 0 deletions projectExporter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import os
import json
import re
# from ProjectSavingEncoder import ProjectSavingEncoder

def ProjectExporter(ProjectName,ProjectPath,ToSavePath,Demo = False):
#Loading the items
if not os.path.exists(f"{ToSavePath}/{ProjectName}"):
os.makedirs(f"{ToSavePath}/{ProjectName}")


with open(f"{ProjectPath}/{ProjectName}/World items.txt","r") as WorldItemsFile:
WorldItems = json.load(WorldItemsFile)

with open(f"{ProjectPath}/{ProjectName}/To import.txt","r") as ToImportFile:
ToImport = json.load(ToImportFile)

# with open(f"{ProjectPath}/{ProjectName}/User defined functions.txt","r") as UdFuncFile:
# UdFunc = json.load(UdFuncFile)

# with open(f"{ProjectPath}/{ProjectName}/User defined src.txt","r") as UdSrcFile:
# UdSrc = json.load(UdSrcFile)

# with open(f"{ProjectPath}/{ProjectName}/User defined vars.txt","r") as UdVarsFile:
# UdVars = json.load(UdVarsFile)

# with open(f"{ProjectPath}/{ProjectName}/Window config.txt","r") as WindowConfigFile:
# WindowConfig = json.load(WindowConfigFile)

#Making a .py file

FinalFile = ''''''
TabIndent = " "
Indent = " "
for i in range(len(ToImport)):
FinalFile += f"{ToImport[i]}\n"

FinalFile += "\n"

FinalFile += "class Game:\n"
FinalFile += f"{TabIndent}def __init__(self):\n"

# WorldItems = [{"cls": "Entity", "args": "(parent=scene, name=\'item_0\', enabled=True, eternal=False, position=Vec3(0, 0.6, 0), rotation=Vec3(0, 0, 0), scale=Vec3(1, 1, 1), model=\'cube\', origin=Vec3(0, 0, 0), shader=None, texture=\'white_cube\', color=color.white, collider=\'mesh\', )"}, {"cls": "Button", "args": "(parent=scene, name=\'item_1\', enabled=True, eternal=False, position=Vec3(-1.11, 0, 0), rotation=Vec3(0, 0, 0), scale=Vec3(1, 1, 1), model=\'cube\', origin=Vec3(0, 0, 0), shader=None, texture=\'white_cube\', color=color.green, )"}, {"cls": "InputField", "args": "(parent=scene, name=\'item_2\', enabled=True, eternal=False, position=Vec3(0, 1.73, 0), rotation=Vec3(0, 0, 0), scale=Vec3(1, 1, 1), model=\'cube\', origin=Vec3(0, 0, 0), shader=None, texture=\'white_cube\', color=color.green, )"}, {"cls": "Button", "args": "(parent=scene, name=\'item_3\', enabled=True, eternal=False, position=Vec3(0.06, -0.72, 0), rotation=Vec3(0, 0, 0), scale=Vec3(1, 1, 1), model=\'cube\', origin=Vec3(0, 0, 0), shader=None, texture=\'white_cube\', color=color.green, )"}, {"cls": "Entity", "args": "(parent=scene, name=\'item_4\', enabled=True, eternal=False, position=Vec3(1.09, 0, 0), rotation=Vec3(0, 0, 0), scale=Vec3(1, 1, 1), model=\'cube\', origin=Vec3(0, 0, 0), shader=None, texture=\'white_cube\', color=color.white, collider=\'mesh\', )"}]
# names = [re.search(r"name='([^']*)'", item).group(1) for item in ]

for item in WorldItems:
name = re.search(r"name='([^']*)'", item['args']).group(1)
FinalFile += f'{Indent}self.{name} = {item["cls"] + item["args"]}\n'
if not Demo:
FinalFile += "if __name__ == '__main__':\n app = Ursina()\n application.development_mode = False\n Sky()\n Game()\n render.setAntialias(AntialiasAttrib.MAuto)\n EditorCamera()\n app.run()"
else:
FinalFile += "if __name__ == '__main__':\n app = Ursina()\n window.center_on_screen()\n application.development_mode = False\n window.borderless = False\n window.size = (960,540)\n window.exit_button.disable()\n Sky()\n Game()\n render.setAntialias(AntialiasAttrib.MAuto)\n EditorCamera()\n app.run()"

with open(f"{ToSavePath}/{ProjectName}/Main.py","w") as File:
File.write(FinalFile)

return True

if __name__ == "__main__":
from GamePlusEditor.OtherStuff import CurrentFolderNameReturner

ProjectExporter("w",f"{CurrentFolderNameReturner()}/Current Games",ToSavePath=CurrentFolderNameReturner().replace("Editor","FInal"))
1 change: 1 addition & 0 deletions samples/main_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def __init__(self, text='', **kwargs):
main_menu.buttons = [
MenuButton('start', on_click=Func(setattr, state_handler, 'state', 'load_menu')),
MenuButton('options', on_click=Func(setattr, state_handler, 'state', 'options_menu')),
MenuButton('level editor', on_click=Func(os.system, "python level_editor/main.py")),
MenuButton('quit', on_click=Sequence(Wait(.01), Func(application.quit))),
]
for i, e in enumerate(main_menu.buttons):
Expand Down
Loading