diff --git a/clang b/clang index 320a739..0a0e2fe 100644 --- a/clang +++ b/clang @@ -1 +1 @@ -en_EN \ No newline at end of file +de_DE \ No newline at end of file diff --git a/hashengine.py b/hashengine.py index 6547d41..cf827cb 100644 --- a/hashengine.py +++ b/hashengine.py @@ -1,9 +1,10 @@ import tkinter as tk import string import random +import threading class stdrend: - def __init__(self, size): + def __init__(self, size, cam): self._size = size self._grid = {} self._win = tk.Tk() @@ -34,6 +35,7 @@ class color3: self.r = r self.g = g self.b = b + self._type = "color3" def __add__(self, v): temp = color3(self.r+v.r, self.g+v.g, self.b+v.b) @@ -81,6 +83,7 @@ class vector2: def __init__(self, x=0, y=0): self.x = x self.y = y + self._type = "vector2" def __add__(self, v): return vector2(self.x+v.x, self.y+v.y) @@ -115,6 +118,14 @@ class enum: cammode = enum({"editable": 0, "follow": 1}) +class event: + def __init__(self): + self._attached = [] + + def execute(self): + for i in self._attached: + threading.Thread(target=i).start() + class obj: def __init__(self): self.position = vector2() @@ -147,9 +158,9 @@ class game: def __init__(self, size=[10, 10], renderer=stdrend): if renderer == None: raise TypeError("Renderer class needed!") self._size = size - self._renderer = renderer(size) self._objects = {} self.camera = camera() + self._renderer = renderer(size, self.camera) def addobj(self, obj): id = "" @@ -173,6 +184,9 @@ class game: return self._objects[id] def render(self): + for x in range(self._size[0]): + for y in range(self._size[1]): + self._renderer.pix(x, y, " ", color3(255, 255, 255), color3(255, 255, 255)) for i in list(self._objects.values()): pos = i.position + self.camera.position if not self.between(-1, self._size[0], pos.x) or not self.between(-1, self._size[1], pos.y): continue diff --git a/langsys/lang/de_DE.LAN b/langsys/lang/de_DE.LAN index 98c5883..b35c945 100644 --- a/langsys/lang/de_DE.LAN +++ b/langsys/lang/de_DE.LAN @@ -15,8 +15,12 @@ "attribute-val": "Wert", "newval": "Neuen Wert eingeben", "error": "Fehler", -"SCE": "Länge des neuen Wertes muss 1 sein!", +"SCE": "Laenge des neuen Wertes muss 1 sein!", "true": "Wahr", "false": "Falsch", "objs": "Objekte", +"suc": "Erfolg!", +"save-suc": "Gespeichert!", +"xcam": "Kamera x Position:", +"ycam": "Kamera y Position:", } \ No newline at end of file diff --git a/langsys/lang/en_EN.LAN b/langsys/lang/en_EN.LAN index 2c41208..75296ad 100644 --- a/langsys/lang/en_EN.LAN +++ b/langsys/lang/en_EN.LAN @@ -18,5 +18,9 @@ "SCE": "Length of the new value must be 1!", "true": "True", "false": "False", -"objs": "Objects" +"objs": "Objects", +"suc": "Success!", +"save-suc": "Saved!", +"xcam": "Camera x position:", +"ycam": "Camera y position:", } \ No newline at end of file diff --git a/main.py b/main.py index 052f975..1f6404a 100644 --- a/main.py +++ b/main.py @@ -4,11 +4,13 @@ sys.dont_write_bytecode = True import mtTkinter as tk from tkinter import ttk as tkk from tkinter import messagebox +from tkinter import filedialog import PCPL import langsys -import time +import ast import subprocess import sys +import time import hashengine import os import random @@ -17,6 +19,8 @@ import easygui global LH global gamedata +global cooldown +cooldown = False gamedata = {} LH = langsys.langhandler() lang = open("clang", 'r') @@ -26,26 +30,61 @@ LH.setlang(lang) PCPL.interpreter.ENG = hashengine +def prepgamedata(): + out = [] + for i in gamedata: + i = gamedata[i] + temp = {"id": i["id"], "name": i["name"]} + tempargs = {} + tosearch = {} + for arg in i["args"]: + if not arg in extypes and not arg in ignoreat: + tosearch[arg] = i["args"][arg] + continue + if arg in ignoreat: continue + tempargs[arg] = i["args"][arg] + for argname in tosearch: + arg = tosearch[argname] + temp2 = getattributes(arg) + temp2.update({"ARGID": arg._type}) + tempargs[argname] = temp2 + temp["args"] = tempargs + out.append(temp) + return out + class script: def __init__(self): self.code = "" - def execute(self): + def execute(self, API): + #old code for PCPL code execution, replaced with python code execution + """ PCPL.resetvar() PCPL.LIS("HASHBASE") - PCPL.run(self.code) + PCPL.run(self.code)""" + prep = {"HASHAPI": API} + exec(self.code, prep) class previewrend: - def __init__(self, size, container, offset): + def __init__(self, size, cam, container, offset): self._size = size self._grid = {} self._win = container + self._frame = tk.Frame(container) + self._posframe = tk.Frame(self._frame) + self._cam = cam + self._xcam = tk.Label(self._posframe, text="-") + self._ycam = tk.Label(self._posframe, text="-") + self._xcam.grid(row=size[1], column=0) + self._ycam.grid(row=size[1]+1, column=0) for y in range(size[1]): for x in range(size[0]): - temp = tk.Label(text=" ") - temp.grid(row=y+offset[1], column=x+offset[0]) + temp = tk.Label(self._frame, text=" ", borderwidth=1, relief=tk.GROOVE, width=3) + temp.grid(row=y+offset[1], column=x+offset[0]+1) self._win.update() self._grid[f"{x}:{y}"] = temp + self._posframe.grid() + self._frame.grid() def coltohex(self, target): colors = [] @@ -58,6 +97,8 @@ class previewrend: return "#"+out def pix(self, x, y, text, bcolor, fcolor): + self._xcam.config(text=LH.string("xcam")+str(self._cam.position.x)) + self._ycam.config(text=LH.string("ycam")+str(self._cam.position.y)) if f"{x}:{y}" in self._grid: self._grid[f"{x}:{y}"].config(text=text, bg=self.coltohex(bcolor), fg=self.coltohex(fcolor)) self._win.update() @@ -71,7 +112,6 @@ def selectlang(new): def add(objtype): global objtree - crucial = ["obj"] obj = getattr(types, objtype)() args = {} for i in dir(obj): @@ -88,6 +128,7 @@ def add(objtype): preview.addobj(obj) gamedata[id]["args"]["ID"] = obj.ID preview.render() + return id def renameobj(): target = objtree.focus() @@ -102,7 +143,10 @@ def delobj(): if target == "": return atritree.delete(*atritree.get_children()) objtree.delete(target) - gamedata.pop(target) + temp = gamedata.pop(target) + if temp["id"] in crucial: + preview.removeobjbyid(temp["args"]["ID"]) + preview.render() def rpopup(event): try: @@ -153,6 +197,66 @@ def halatribute(event): atritree.item(target, values=(new)) preview.render() +def updatepreviewcam(char): + global cooldown + if cooldown == True: return + cooldown = True + char = char.char + if char == "w": preview.camera.position += hashengine.vector2(y=1) + if char == "a": preview.camera.position += hashengine.vector2(x=1) + if char == "s": preview.camera.position -= hashengine.vector2(y=1) + if char == "d": preview.camera.position -= hashengine.vector2(x=1) + preview.render() + time.sleep(0) + cooldown = False + +def save(): + target = filedialog.asksaveasfile() + target.write(str(prepgamedata())) + target.close() + messagebox.showinfo(LH.string("suc"), LH.string("save-suc")) + +def clear(): + global gamedata + objtree.delete(*objtree.get_children()) + atritree.delete(*atritree.get_children()) + gamedata = {} + preview._objects = {} + preview.camera.position = hashengine.vector2() + preview.render() + +def importobj(target): + oid = add(target["id"]) + id = gamedata[oid] + id["name"] = target["name"] + objtree.item(oid, text=target["name"]) + #create arguments + outargs = {} + for argname in target["args"]: + arg = target["args"][argname] + if isinstance(arg, dict): + ID = arg.pop("ARGID") + obj = attypes[ID]() + for i in arg: + setattr(obj, i, arg[i]) + arg = obj + outargs[argname] = arg + #apply arguments to obj + if target["id"] in crucial: + for i in outargs: + setattr(preview.getobjbyid(gamedata[oid]["args"]["ID"]), i, outargs[i]) + id["args"].update(outargs) + +def load(): + file = filedialog.askopenfile() + target = file.read() + file.close() + target = ast.literal_eval(target) + clear() + for i in target: + importobj(i) + preview.render() + def GUIinit(): global container global objtree @@ -161,6 +265,7 @@ def GUIinit(): global currentat global preview container = tk.Tk() + container.bind("", updatepreviewcam) global icons icons = {} @@ -169,13 +274,13 @@ def GUIinit(): icons[i.split(".")[0]] = tk.PhotoImage(file=f"icons/{i}") #preview init - preview = hashengine.game(renderer=lambda size: previewrend(size, container=container, offset=[0, 0])) + preview = hashengine.game(renderer=lambda size, cam: previewrend(size, cam, container=container, offset=[0, 0])) #tree init - objtree = tkk.Treeview(container, selectmode="browse") + objtree = tkk.Treeview(container, selectmode="browse", columns=("-")) objtree.heading("#0", text=LH.string("objs")) objtree.tag_bind("objsel", "<>", updatribute) - objtree.grid(row=10, column=11) + objtree.grid(row=1, column=0) #attribute tree init currentat = "temp" @@ -183,7 +288,7 @@ def GUIinit(): atritree.heading("#0", text=LH.string("attribute")) atritree.heading("#1", text=LH.string("attribute-val")) atritree.bind("", halatribute) - atritree.grid(row=11, column=11) + atritree.grid(row=2, column=0) #right click menu rmenu = tk.Menu(container, tearoff=0) @@ -197,9 +302,9 @@ def GUIinit(): container.config(menu=menu) filemenu = tk.Menu(menu) menu.add_cascade(label=LH.string("file"), menu=filemenu) - filemenu.add_command(label=LH.string("new")) - filemenu.add_command(label=LH.string("open")) - filemenu.add_command(label=LH.string("save")) + filemenu.add_command(label=LH.string("new"), command=clear) + filemenu.add_command(label=LH.string("open"), command=load) + filemenu.add_command(label=LH.string("save"), command=save) filemenu.add_separator() filemenu.add_command(label=LH.string("exit"), command=container.quit) @@ -249,8 +354,12 @@ global types global icon global ignoreat global valtypes +global extypes +global attypes +global crucial +crucial = ["obj"] types = hashengine.enum({"obj": hashengine.obj, "script": script}) -icon = hashengine.enum({"obj": "icons/object.png", "script": "icons/script.pngg"}) +icon = hashengine.enum({"obj": "icons/object.png", "script": "icons/script.png"}) ignoreat = ["ID", "execute"] """self.position = vector2() self.char = " " @@ -279,5 +388,9 @@ valtypes = { "anchored": abool, "code": acode, } - +extypes = list(valtypes.keys()) +attypes = { +"vector2": hashengine.vector2, +"color3": hashengine.color3, +} GUIinit() \ No newline at end of file diff --git a/tests/BASEobjtest b/tests/BASEobjtest new file mode 100644 index 0000000..f7675bd --- /dev/null +++ b/tests/BASEobjtest @@ -0,0 +1 @@ +[{'id': 'obj', 'name': 'Objekt', 'args': {'anchored': False, 'char': '#', 'collide': True, 'friction': 0, 'gravity': 0, 'touch': True, 'acceleration': {'x': 0, 'y': 0, 'ARGID': 'vector2'}, 'bcolor': {'b': 0, 'g': 255, 'r': 255, 'ARGID': 'color3'}, 'fcolor': {'b': 0, 'g': 0, 'r': 255, 'ARGID': 'color3'}, 'position': {'x': 0, 'y': 0, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}] \ No newline at end of file diff --git a/tests/EXTobjtest b/tests/EXTobjtest new file mode 100644 index 0000000..f6f0b1e --- /dev/null +++ b/tests/EXTobjtest @@ -0,0 +1 @@ +[{'id': 'obj', 'name': 'objtest1', 'args': {'anchored': False, 'char': '#', 'collide': True, 'friction': 0, 'gravity': 0, 'touch': True, 'acceleration': {'x': 0, 'y': 0, 'ARGID': 'vector2'}, 'bcolor': {'b': 0, 'g': 255, 'r': 255, 'ARGID': 'color3'}, 'fcolor': {'b': 0, 'g': 0, 'r': 255, 'ARGID': 'color3'}, 'position': {'x': 0, 'y': 0, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'obj', 'name': 'objtest2', 'args': {'anchored': False, 'char': '#', 'collide': True, 'friction': 0, 'gravity': 0, 'touch': True, 'acceleration': {'x': 0, 'y': 0, 'ARGID': 'vector2'}, 'bcolor': {'b': 255, 'g': 0, 'r': 255, 'ARGID': 'color3'}, 'fcolor': {'b': 255, 'g': 0, 'r': 0, 'ARGID': 'color3'}, 'position': {'x': 5, 'y': 5, 'ARGID': 'vector2'}, 'velocity': {'x': 0, 'y': 0, 'ARGID': 'vector2'}}}, {'id': 'script', 'name': 'scriptsavetest', 'args': {'code': ''}}] \ No newline at end of file