1162 lines
36 KiB
Python
1162 lines
36 KiB
Python
import sys
|
|
# Justus Jan Nico Wolff
|
|
sys.dont_write_bytecode = True
|
|
import mtTkinter as tk
|
|
from tkinter import ttk as tkk
|
|
from tkinter import messagebox
|
|
from tkinter import filedialog
|
|
import copy
|
|
import hashengine
|
|
def norms():
|
|
global LH
|
|
import PCPL
|
|
import langsys
|
|
PCPL.interpreter.ENG = hashengine
|
|
LH = langsys.langhandler()
|
|
lang = open("clang", 'r')
|
|
lang = lang.read()
|
|
LH.setlang(lang)
|
|
# LH.string("")
|
|
def replacelh():
|
|
global LH
|
|
class rLH:
|
|
def __init__(self):
|
|
pass
|
|
def string(self, target):
|
|
return target
|
|
def getlangs(self):
|
|
return ()
|
|
LH = rLH()
|
|
if __name__ == "__main__":
|
|
norms()
|
|
else:
|
|
replacelh()
|
|
if len(sys.argv) == 2:
|
|
if sys.argv[1] == "NOLANG":
|
|
replacelh()
|
|
import ast
|
|
import subprocess
|
|
import time
|
|
import shutil
|
|
import os
|
|
import random
|
|
import string
|
|
import easygui
|
|
import base64
|
|
import simpleaudio as sa
|
|
import multiprocessing
|
|
|
|
global gamedata
|
|
global cooldown
|
|
global version
|
|
version = "HE2.2-Hashengine V2.2"
|
|
cooldown = False
|
|
gamedata = {}
|
|
|
|
def prepspecified(target):
|
|
out = []
|
|
tempwin = tk.Tk()
|
|
bar = tkk.Progressbar(tempwin)
|
|
bar.place(width=200)
|
|
ptext = tk.Label(tempwin, text="NONE")
|
|
ptext.place()
|
|
count = 1
|
|
modellist = {}
|
|
for i in target:
|
|
id = i
|
|
i = gamedata[i]
|
|
ptext.config(text=i["name"])
|
|
bar.step(count/len(gamedata))
|
|
count += 1
|
|
tempwin.update()
|
|
temp = {"id": i["id"], "name": i["name"], "SID": i["SID"],}
|
|
tempargs = {}
|
|
tosearch = {}
|
|
for arg in i["args"]:
|
|
if not arg in extypes and not arg in ignoreat and arg != "sdata":
|
|
tosearch[arg] = i["args"][arg]
|
|
continue
|
|
if arg in ignoreat and arg != "sdata": continue
|
|
if arg != "sdata":
|
|
tempargs[arg] = i["args"][arg]
|
|
else:
|
|
tempargs[arg] = str(base64.b64encode(i["args"][arg]), "ascii", "ignore")
|
|
for argname in tosearch:
|
|
arg = tosearch[argname]
|
|
temp2 = getattributes(arg)
|
|
temp2.update({"ARGID": arg._type})
|
|
tempargs[argname] = temp2
|
|
if objtree.parent(id) != "":
|
|
modelname = objtree.item(objtree.parent(id), "text")
|
|
if not modelname in list(modellist.keys()):
|
|
modellist[modelname] = []
|
|
modellist[modelname].append(count-2)
|
|
temp["args"] = tempargs
|
|
out.append(temp)
|
|
tempwin.destroy()
|
|
return [out, modellist, gamexsize, gameysize]
|
|
|
|
class script:
|
|
def __init__(self):
|
|
self.code = ""
|
|
|
|
def execute(self, API, log):
|
|
#old code for PCPL code execution, replaced with python code execution
|
|
"""
|
|
PCPL.resetvar()
|
|
PCPL.LIS("HASHBASE")
|
|
PCPL.run(self.code)"""
|
|
try:
|
|
exec(self.code, API)
|
|
except Exception as e:
|
|
log(f"[GAME] Exception occured in script: {e}")
|
|
|
|
class previewrend:
|
|
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)
|
|
|
|
tkeys = list(string.ascii_letters)
|
|
self._keys = {}
|
|
for i in tkeys:
|
|
self._keys[i] = False
|
|
self._win.bind("<KeyPress>", self.keypupd, add="+")
|
|
self._win.bind("<KeyRelease>", self.keydupd, add="+")
|
|
|
|
for y in range(size[1]):
|
|
for x in range(size[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 destroy(self):
|
|
self._posframe.destroy()
|
|
self._frame.destroy()
|
|
|
|
def keypupd(self, event):
|
|
event = event.char
|
|
if event in self._keys:
|
|
self._keys[event] = True
|
|
|
|
def keydupd(self, event):
|
|
event = event.char
|
|
if event in self._keys:
|
|
self._keys[event] = False
|
|
|
|
def getkeys(self):
|
|
return self._keys
|
|
|
|
def coltohex(self, target):
|
|
colors = []
|
|
target = [target.r, target.g, target.b]
|
|
for i in target:
|
|
colors.append(("0"*(2-len(hex(int(i))[2:])))+hex(i)[2:])
|
|
out = ""
|
|
for i in colors:
|
|
out = out + i
|
|
return "#"+out
|
|
|
|
def update(self):
|
|
self._win.update()
|
|
|
|
def select(self, x, y):
|
|
if f"{x}:{y}" in self._grid:
|
|
self._grid[f"{x}:{y}"].config(background="cyan")
|
|
|
|
def deselect(self, x, y):
|
|
if f"{x}:{y}" in self._grid:
|
|
self._grid[f"{x}:{y}"].config(background="white")
|
|
|
|
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))
|
|
|
|
class render:
|
|
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)
|
|
|
|
tkeys = list(string.ascii_letters)
|
|
self._keys = {}
|
|
for i in tkeys:
|
|
self._keys[i] = False
|
|
self._win.bind("<KeyPress>", self.keypupd)
|
|
self._win.bind("<KeyRelease>", self.keydupd)
|
|
|
|
for y in range(size[1]):
|
|
for x in range(size[0]):
|
|
temp = tk.Label(self._frame, text=" ", 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 keypupd(self, event):
|
|
event = event.char
|
|
if event in self._keys:
|
|
self._keys[event] = True
|
|
|
|
def keydupd(self, event):
|
|
event = event.char
|
|
if event in self._keys:
|
|
self._keys[event] = False
|
|
|
|
def getkeys(self):
|
|
return self._keys
|
|
|
|
def coltohex(self, target):
|
|
colors = []
|
|
target = [target.r, target.g, target.b]
|
|
for i in target:
|
|
colors.append(("0"*(2-len(hex(int(i))[2:])))+hex(i)[2:])
|
|
out = ""
|
|
for i in colors:
|
|
out = out + i
|
|
return "#"+out
|
|
|
|
def update(self):
|
|
self._win.update()
|
|
|
|
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))
|
|
|
|
class nullrend:
|
|
def __init__(self, size, cam):
|
|
pass
|
|
|
|
def getkeys(self):
|
|
pass
|
|
|
|
def update(self):
|
|
pass
|
|
|
|
def pix(self, x, y, text, bcolor, fcolor):
|
|
pass
|
|
|
|
def selectlang(new):
|
|
lang = open("clang", 'w')
|
|
lang.write(new)
|
|
lang.close()
|
|
container.quit()
|
|
subprocess.Popen([sys.executable, __file__])
|
|
|
|
def add(objtype, parent="", render=True):
|
|
global objtree
|
|
obj = getattr(types, objtype)()
|
|
args = {}
|
|
for i in dir(obj):
|
|
if i.startswith("_"): continue
|
|
args[i] = getattr(obj, i)
|
|
temp = {"id": objtype, "args": args, "name": LH.string(objtype), "SID": genid()}
|
|
id = genid()
|
|
if GUIe == True: objtree.insert(parent, tk.END, text=LH.string(objtype), image=icons[objtype], iid=id, tags=("objsel"))
|
|
gamedata[id] = temp
|
|
if objtype in crucial:
|
|
preview.addobj(obj)
|
|
gamedata[id]["args"]["ID"] = obj.ID
|
|
if GUIe == True and render == True: preview.render()
|
|
return id
|
|
|
|
def renameobj():
|
|
target = objtree.focus()
|
|
if target == "": return
|
|
new = easygui.enterbox(LH.string("NN"), LH.string("rename"))
|
|
if new:
|
|
objtree.item(target, text=new)
|
|
if not "HASHMODEL" in objtree.item(target, "tags"):
|
|
gamedata[target]["name"] = new
|
|
|
|
def delobjg(target):
|
|
objtree.delete(target)
|
|
temp = gamedata.pop(target)
|
|
if temp["id"] in crucial:
|
|
preview.removeobjbyid(temp["args"]["ID"])
|
|
#preview.render()
|
|
|
|
def delobj():
|
|
target = objtree.selection()
|
|
if target == (): return
|
|
atritree.delete(*atritree.get_children())
|
|
for i in target:
|
|
if "HASHMODEL" in objtree.item(i, "tags"):
|
|
tempwin = tk.Tk()
|
|
stat = tk.Label(tempwin, text="NONE")
|
|
stat.grid()
|
|
speed = tk.Label(tempwin, text="NONE")
|
|
speed.grid()
|
|
tempwin.update()
|
|
count = 0
|
|
length = len(objtree.get_children(i))
|
|
fpscount = 0
|
|
timestamp = time.time()
|
|
fps = 0
|
|
for f in objtree.get_children(i):
|
|
delobjg(f)
|
|
stat.config(text=f"{count}/{length}")
|
|
speed.config(text=f"{fps}/s")
|
|
tempwin.update()
|
|
count += 1
|
|
fpscount += 1
|
|
if time.time()-timestamp > 0.1:
|
|
fps = fpscount*10
|
|
fpscount = 0
|
|
timestamp = time.time()
|
|
objtree.delete(i)
|
|
tempwin.destroy()
|
|
else:
|
|
delobjg(i)
|
|
preview.render()
|
|
|
|
def HMPC(event):
|
|
currentat = objtree.focus()
|
|
target = atritree.focus()
|
|
name = atritree.item(target, "text")
|
|
back = 0
|
|
if name == "x":
|
|
back = aposx(0)
|
|
elif name == "y":
|
|
back = aposy(0)
|
|
for i in objtree.get_children(currentat):
|
|
if not "ID" in gamedata[i]["args"]: continue
|
|
setattr(gamedata[i]["args"]["position"], name, getattr(gamedata[i]["args"]["position"], name)+back)
|
|
setattr(preview.getobjbyid(gamedata[i]["args"]["ID"]).position, name, getattr(preview.getobjbyid(gamedata[i]["args"]["ID"]).position, name)+back)
|
|
updselect(None)
|
|
|
|
def changemodelpos(event):
|
|
atritree.delete(*atritree.get_children())
|
|
atritree.insert("", index=tk.END, text="x", tags=("OA",))
|
|
atritree.insert("", index=tk.END, text="y", tags=("OA",))
|
|
atritree.insert("", index=tk.END, text="SEQSID", values=(calcseqsid(objtree.focus())), tags=("SID",))
|
|
|
|
def calcseqsid(target):
|
|
out = ""
|
|
for f in objtree.get_children(target):
|
|
out = out + gamedata[f]["SID"][:5]
|
|
return out
|
|
|
|
def rpopup(event):
|
|
try:
|
|
rmenu.tk_popup(event.x_root, event.y_root)
|
|
finally:
|
|
rmenu.grab_release()
|
|
|
|
def getattributes(target):
|
|
out = {}
|
|
for i in dir(target):
|
|
if i.startswith("_"): continue
|
|
out[i] = getattr(target, i)
|
|
return out
|
|
|
|
def copySID(event):
|
|
target = atritree.focus()
|
|
text = atritree.item(target, "values")[0]
|
|
container.clipboard_clear()
|
|
container.clipboard_append(text)
|
|
messagebox.showinfo(LH.string("done"), LH.string("copied"))
|
|
|
|
def updatribute(event):
|
|
global currentat
|
|
target = objtree.focus()
|
|
currentat = target
|
|
atritree.delete(*atritree.get_children())
|
|
for i in gamedata[target]["args"]:
|
|
if i in ignoreat: continue
|
|
if i in valtypes and not i in DCTE:
|
|
val = gamedata[target]["args"][i]
|
|
atritree.insert("", tk.END, text=i, values=(val), tags=("FA", ))
|
|
elif i in valtypes and i in DCTE:
|
|
atritree.insert("", tk.END, text=i, values=("<DCTE>"), tags=("FA", ))
|
|
else:
|
|
root = atritree.insert("", tk.END, text=i, tags=("FA", ))
|
|
temp = getattributes(gamedata[target]["args"][i])
|
|
for f in temp:
|
|
atritree.insert(root, tk.END, text=f, values=(temp[f]), tags=("FA", ))
|
|
atritree.insert("", tk.END, text="SID", values=(gamedata[target]["SID"]), tags=("SID", ))
|
|
|
|
def halatribute(event):
|
|
target = atritree.focus()
|
|
name = atritree.item(target, "text")
|
|
parent = atritree.parent(target)
|
|
currentobj = currentat
|
|
if name in valtypes:
|
|
if parent == "":
|
|
new = valtypes[name](gamedata[currentobj]["args"][name])
|
|
gamedata[currentobj]["args"][name] = new
|
|
if "ID" in gamedata[currentobj]["args"]:
|
|
temp = preview.getobjbyid(gamedata[currentobj]["args"]["ID"])
|
|
setattr(temp, name, new)
|
|
atritree.delete(*atritree.get_children())
|
|
objtree.focus("")
|
|
else:
|
|
parent = atritree.item(parent, "text")
|
|
new = valtypes[name](getattr(gamedata[currentobj]["args"][parent], name))
|
|
setattr(gamedata[currentobj]["args"][parent], name, new)
|
|
if "ID" in gamedata[currentobj]["args"]:
|
|
temp = preview.getobjbyid(gamedata[currentobj]["args"]["ID"])
|
|
setattr(temp, name, new)
|
|
atritree.delete(*atritree.get_children())
|
|
objtree.focus("")
|
|
updselect(None)
|
|
|
|
def updatepreviewcam(char):
|
|
global cooldown
|
|
if cooldown == True: return
|
|
cooldown = True
|
|
char = char.char
|
|
allowed = ["w", "a", "s", "d"]
|
|
if not char in allowed: return
|
|
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)
|
|
updselect(None)
|
|
time.sleep(.0)
|
|
cooldown = False
|
|
|
|
def save():
|
|
target = filedialog.asksaveasfile()
|
|
target.write(str(prepspecified(gamedata)))
|
|
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 importsound(target):
|
|
oid = add("rawsound")
|
|
gamedata[oid]["name"] = target["name"]
|
|
gamedata[oid]["args"]["sdata"] = base64.b64decode(target["args"]["sdata"])
|
|
gamedata[oid]["args"]["spath"] = target["args"]["spath"]
|
|
if "SID" in target:
|
|
gamedata[oid]["SID"] = target["SID"]
|
|
if GUIe == True: objtree.item(oid, text=target["name"])
|
|
|
|
def importobj(target):
|
|
if target["id"] == "sound" or target["id"] == "rawsound":
|
|
importsound(target)
|
|
return
|
|
oid = add(target["id"])
|
|
id = gamedata[oid]
|
|
id["name"] = target["name"]
|
|
if "SID" in target:
|
|
id["SID"] = target["SID"]
|
|
if GUIe == True: 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)
|
|
return oid
|
|
|
|
def load(cleargame=True, GUI=True, path="", override=False):
|
|
if GUI == True:
|
|
file = filedialog.askopenfile()
|
|
elif override == False:
|
|
file = open(path, 'r')
|
|
tempwin = tk.Tk()
|
|
ptext = tk.Label(tempwin, text="NONE")
|
|
ptext.place(y=30)
|
|
stat = tk.Label(tempwin, text="NONE")
|
|
stat.place(y=50)
|
|
if override == False:
|
|
target = file.read()
|
|
file.close()
|
|
else:
|
|
target = override
|
|
target = ast.literal_eval(target)
|
|
if cleargame:
|
|
global models
|
|
models = []
|
|
clear()
|
|
if len(target) == 0: return
|
|
if not isinstance(target[0], list):
|
|
#very old save file
|
|
count = 1
|
|
bar = tkk.Progressbar(tempwin, maximum=len(target))
|
|
bar.place(width=200)
|
|
for i in target:
|
|
ptext.config(text="Current: "+i["name"])
|
|
bar.step()
|
|
stat.config(text=f"Object {count}/{len(target)}")
|
|
tempwin.update()
|
|
importobj(i)
|
|
count += 1
|
|
tempwin.destroy()
|
|
preview.render()
|
|
elif len(target) < 3:
|
|
#old save file
|
|
count = 1
|
|
bar = tkk.Progressbar(tempwin, maximum=len(target))
|
|
bar.place(width=200)
|
|
ids = {}
|
|
for i in target[0]:
|
|
ptext.config(text="Current: "+i["name"])
|
|
bar.step()
|
|
stat.config(text=f"Object {count}/{len(target)}")
|
|
tempwin.update()
|
|
id = importobj(i)
|
|
if id:
|
|
ids[count-1] = id
|
|
count += 1
|
|
for i in target[1]:
|
|
tempid = genid()
|
|
if GUIe == True: objtree.insert("", tk.END, text=i, image=icons["model"], iid=tempid, tags=("HASHMODEL",))
|
|
temp = []
|
|
for f in target[1][i]:
|
|
if GUIe == True:
|
|
objtree.detach(ids[f])
|
|
objtree.move(ids[f], tempid, "end")
|
|
temp.append(ids[f])
|
|
models.append(temp)
|
|
tempwin.destroy()
|
|
preview.render()
|
|
else:
|
|
#new save file
|
|
global gamexsize
|
|
global gameysize
|
|
count = 1
|
|
bar = tkk.Progressbar(tempwin, maximum=len(target))
|
|
bar.place(width=200)
|
|
ids = {}
|
|
for i in target[0]:
|
|
ptext.config(text="Current: "+i["name"])
|
|
bar.step()
|
|
stat.config(text=f"Object {count}/{len(target)}")
|
|
tempwin.update()
|
|
id = importobj(i)
|
|
if id:
|
|
ids[count-1] = id
|
|
count += 1
|
|
for i in target[1]:
|
|
tempid = genid()
|
|
if GUIe == True: objtree.insert("", tk.END, text=i, image=icons["model"], iid=tempid, tags=("HASHMODEL",))
|
|
temp = []
|
|
for f in target[1][i]:
|
|
if GUIe == True:
|
|
objtree.detach(ids[f])
|
|
objtree.move(ids[f], tempid, "end")
|
|
temp.append(ids[f])
|
|
models.append(temp)
|
|
tempwin.destroy()
|
|
gamexsize = target[2]
|
|
gameysize = target[3]
|
|
if GUIe == True: initpreview()
|
|
preview.render()
|
|
|
|
def export():
|
|
temp = objtree.selection()
|
|
if temp == (): return
|
|
target = []
|
|
for i in temp:
|
|
if "HASHMODEL" in objtree.item(i, "tags"):
|
|
target.extend(objtree.get_children(i))
|
|
else: target.append(i)
|
|
back = prepspecified(target)
|
|
targetpath = filedialog.asksaveasfile()
|
|
if not targetpath: return
|
|
targetpath.write(str(back))
|
|
targetpath.close()
|
|
messagebox.showinfo(LH.string("suc"), LH.string("save-suc"))
|
|
|
|
def log(text, end="\n", flush=False):
|
|
global logfile
|
|
global clog
|
|
if clog:
|
|
if not os.path.exists("logs"):
|
|
os.mkdir("logs")
|
|
file = open("logs/"+logfile+".txt", 'a')
|
|
file.write(str(text)+end)
|
|
file.close()
|
|
|
|
def NULL():
|
|
pass
|
|
|
|
class gsound:
|
|
def __init__(self, data, game):
|
|
self._playing = False
|
|
self._data = data
|
|
game.currentsounds.append(self)
|
|
|
|
def play(self):
|
|
if self._playing == True: return
|
|
self._sound = sa.play_buffer(self._data, 2, 2, 44100)
|
|
self._playing = True
|
|
|
|
def stop(self):
|
|
if self._playing == False: return
|
|
self._sound.stop()
|
|
self._playing = False
|
|
|
|
def wait(self):
|
|
if self._playing == False: return
|
|
self._sound.wait_done()
|
|
|
|
def testing():
|
|
global testproc
|
|
global running
|
|
global clog
|
|
try:
|
|
if running == True: return
|
|
except:
|
|
pass
|
|
running = True
|
|
testproc = multiprocessing.Process(target=execgame, args=(prepspecified(gamedata), clog.get()))
|
|
testproc.start()
|
|
|
|
def APIGEN():
|
|
API = {"print": log, "HASHBASE": hashengine}
|
|
API["HASHGAME"] = maingame
|
|
API["SOUND"] = lambda data: gsound(data, maingame)
|
|
return API
|
|
|
|
def run():
|
|
global logfile
|
|
global maingame
|
|
global window
|
|
temp = time.gmtime(time.time())
|
|
logfile = ""
|
|
for i in temp:
|
|
logfile = logfile + "S" + str(i)
|
|
log("Log file start!")
|
|
log(f"date: year: {temp[0]} month: {temp[1]} day: {temp[2]} hour: {temp[3]} min.: {temp[4]}, sec.: {temp[5]}")
|
|
log(f"Version: {version}")
|
|
log("Preparing API...")
|
|
log("Done!")
|
|
window = tk.Tk()
|
|
window.protocol("WM_DELETE_WINDOW", NULL)
|
|
maingame = hashengine.game(renderer=lambda size, cam: render(size, cam, window, [0, 0]), sounddir="/", size=[gamexsize, gameysize])
|
|
log("main game initalised!")
|
|
log("copying sounds...")
|
|
for i in gamedata:
|
|
i = gamedata[i]
|
|
if i["id"] != "sound" and i["id"] != "rawsound": continue
|
|
maingame.sounds[i["args"]["spath"]] = i["args"]["sdata"]
|
|
#skip = []
|
|
for i in gamedata:
|
|
GID = i
|
|
i = gamedata[i]
|
|
if i["id"] != "obj": continue
|
|
objid = i["args"]["ID"]
|
|
maingame._SIDS[i["SID"]] = objid
|
|
"""if objtree.parent(GID) != "" and not objtree.parent(GID) in skip:
|
|
skip.append(objtree.parent(GID))
|
|
out = ""
|
|
out2 = []
|
|
for f in objtree.get_children(objtree.parent(GID)):
|
|
out = out + gamedata[f]["SID"][:5]
|
|
out2.append(f)
|
|
maingame._SEQSIDS[out] = out2"""
|
|
for i in models:
|
|
out = []
|
|
SEQSID = ""
|
|
for f in i:
|
|
SEQSID = SEQSID + gamedata[f]["SID"][:5]
|
|
out.append(gamedata[f]["args"]["ID"])
|
|
maingame._SEQSIDS[SEQSID] = out
|
|
|
|
maingame._objects = copy.deepcopy(preview._objects)
|
|
"""
|
|
objects = copy.deepcopy(preview._objects)
|
|
maingame._objects = objects"""
|
|
scripts = []
|
|
for i in gamedata:
|
|
i = gamedata[i]
|
|
if i["id"] != "script": continue
|
|
i = i["args"]["code"]
|
|
obj = script()
|
|
obj.code = i
|
|
scripts.append(obj)
|
|
log("objects transferred!")
|
|
#gamescript = """
|
|
#global HASHGAME
|
|
#import time
|
|
#while True:
|
|
# for i in HASHGAME._objects:
|
|
# i = HASHGAME._objects[i]
|
|
# HASHGAME.calcphysobj(i)
|
|
# HASHGAME.render()
|
|
#"""
|
|
#gameloopsc = script()
|
|
#gameloopsc.code = gamescript
|
|
#maingame.startscript(lambda: gameloopsc.execute(APIGEN(), log))
|
|
log("game test started!!!")
|
|
log("---------------------")
|
|
for i in scripts:
|
|
maingame.startscript(lambda: i.execute(APIGEN(), log))
|
|
#window.mainloop()
|
|
while True:
|
|
for i in maingame._objects:
|
|
i = maingame._objects[i]
|
|
maingame.calcphysobj(i)
|
|
maingame.render()
|
|
window.update()
|
|
|
|
def muladd(target):
|
|
for i in range(10):
|
|
add(target)
|
|
|
|
def stoptest():
|
|
global testproc
|
|
global running
|
|
try:
|
|
if running == False: return
|
|
except:
|
|
return
|
|
testproc.terminate()
|
|
running = False
|
|
|
|
def build():
|
|
print("asking user for output directory...")
|
|
target = filedialog.askdirectory()
|
|
os.mkdir(target+"/out")
|
|
target = target+"/out"
|
|
print("building started")
|
|
print("generating HEGF file...")
|
|
hegf = str(prepspecified(gamedata))
|
|
file = open(target+"/game.HEGF", 'w')
|
|
file.write(hegf)
|
|
file.close()
|
|
print("done.")
|
|
print("copying files...")
|
|
tocopy = ["mtTkinter.py", "hashengine.py"]
|
|
for i in tocopy:
|
|
print(f"copying {i}...")
|
|
shutil.copyfile(i, target+"/"+i)
|
|
shutil.copyfile(__file__, target+"/"+"player.py")
|
|
file = open(target+"/main.py", 'w')
|
|
file.write("""
|
|
import player
|
|
import ast
|
|
file = open("game.HEGF", 'r')
|
|
file = file.read()
|
|
file = ast.literal_eval(file)
|
|
player.execgame(file)
|
|
""")
|
|
print("done.")
|
|
print("building finished!")
|
|
|
|
def importPS():
|
|
target = filedialog.askopenfile()
|
|
if target:
|
|
temp = add("script")
|
|
gamedata[temp]["args"]["code"] = str(target.read())
|
|
target.close()
|
|
|
|
def genid():
|
|
id = ""
|
|
chars = list(string.ascii_letters)
|
|
for i in range(255):
|
|
id = id + random.choice(chars)
|
|
return id
|
|
|
|
def COBS(target: str, offset=hashengine.vector2(), ignore=[" ",]):
|
|
origin = target
|
|
target = target.split("\n")
|
|
tempid = genid()
|
|
tempwin = tk.Tk()
|
|
stat = tk.Label(tempwin, text="NONE")
|
|
stat.grid()
|
|
speed = tk.Label(tempwin, text="NONE")
|
|
speed.grid()
|
|
tempwin.update()
|
|
if GUIe == True: objtree.insert("", tk.END, text=LH.string("IOM"), image=icons["model"], iid=tempid, tags=("HASHMODEL",))
|
|
count = 1
|
|
fpscount = 0
|
|
timestamp = time.time()
|
|
fps = 0
|
|
for i in range(len(target)):
|
|
y = i
|
|
i = target[i]
|
|
for f in range(len(i)):
|
|
x = f
|
|
f = i[x]
|
|
stat.config(text=f"{count}/{len(origin)}")
|
|
speed.config(text=f"{fps}/s")
|
|
tempwin.update()
|
|
count += 1
|
|
fpscount += 1
|
|
if time.time()-timestamp > 0.1:
|
|
fps = fpscount*10
|
|
fpscount = 0
|
|
timestamp = time.time()
|
|
if f in ignore:
|
|
continue
|
|
temp = add("obj", tempid, False)
|
|
#gamedata[temp]["args"]["ID"]
|
|
gamedata[temp]["args"]["char"] = f
|
|
setattr(preview.getobjbyid(gamedata[temp]["args"]["ID"]), "char", f)
|
|
gamedata[temp]["args"]["position"] = hashengine.vector2(x, y)+offset
|
|
setattr(preview.getobjbyid(gamedata[temp]["args"]["ID"]), "position", hashengine.vector2(x, y)+offset)
|
|
gamedata[temp]["args"]["anchored"] = True
|
|
setattr(preview.getobjbyid(gamedata[temp]["args"]["ID"]), "anchored", True)
|
|
gamedata[temp]["args"]["collide"] = True
|
|
setattr(preview.getobjbyid(gamedata[temp]["args"]["ID"]), "collide", True)
|
|
#preview.render()
|
|
updselect(None)
|
|
tempwin.destroy()
|
|
|
|
def updselect(event):
|
|
preview.render()
|
|
selection = objtree.selection()
|
|
for selected in selection:
|
|
if "objsel" in objtree.item(selected, "tags"):
|
|
if gamedata[selected]["id"] == "obj":
|
|
preview._renderer.select(gamedata[selected]["args"]["position"].x+preview.camera.position.x, gamedata[selected]["args"]["position"].y+preview.camera.position.y)
|
|
if "HASHMODEL" in objtree.item(selected, "tags"):
|
|
for i in objtree.get_children(selected):
|
|
if "objsel" in objtree.item(i, "tags"):
|
|
if gamedata[i]["id"] == "obj":
|
|
preview._renderer.select(gamedata[i]["args"]["position"].x+preview.camera.position.x, gamedata[i]["args"]["position"].y+preview.camera.position.y)
|
|
|
|
def changegamex():
|
|
global gamexsize
|
|
gamexsize = int(aposx(gamexsize))
|
|
initpreview()
|
|
|
|
def changegamey():
|
|
global gameysize
|
|
gameysize = int(aposy(gameysize))
|
|
initpreview()
|
|
|
|
def initpreview():
|
|
global preview
|
|
objs = {}
|
|
try:
|
|
objs = preview._objects
|
|
preview._renderer.destroy()
|
|
ungridobjtrees()
|
|
except:
|
|
pass
|
|
preview = hashengine.game(renderer=lambda size, cam: previewrend(size, cam, container=container, offset=[0, 0]), sounddir="/", size=[gamexsize, gameysize])
|
|
preview._objects = objs
|
|
try:
|
|
gridobjtrees()
|
|
except NameError:
|
|
pass
|
|
|
|
def gridobjtrees():
|
|
objtree.grid(row=1, column=0)
|
|
atritree.grid(row=2, column=0)
|
|
|
|
def ungridobjtrees():
|
|
objtree.grid_remove()
|
|
atritree.grid_remove()
|
|
|
|
def GUIinit():
|
|
global container
|
|
global objtree
|
|
global rmenu
|
|
global atritree
|
|
global currentat
|
|
global GUIe
|
|
global clog
|
|
global models
|
|
models = []
|
|
GUIe = True
|
|
container = tk.Tk()
|
|
container.bind("<KeyPress>", updatepreviewcam, add="+")
|
|
|
|
global icons
|
|
icons = {}
|
|
|
|
for i in os.listdir("icons"):
|
|
icons[i.split(".")[0]] = tk.PhotoImage(file=f"icons/{i}")
|
|
|
|
#preview init
|
|
initpreview()
|
|
|
|
#tree init
|
|
objtree = tkk.Treeview(container, columns=("-"))
|
|
objtree.heading("#0", text=LH.string("objs"))
|
|
objtree.tag_bind("objsel", "<<TreeviewSelect>>", updatribute)
|
|
objtree.tag_bind("HASHMODEL", "<<TreeviewSelect>>", changemodelpos)
|
|
objtree.bind("<<TreeviewSelect>>", updselect, add="+")
|
|
objtree.grid(row=1, column=0)
|
|
|
|
#attribute tree init
|
|
currentat = "temp"
|
|
atritree = tkk.Treeview(container, columns=("#1"), selectmode="browse")
|
|
atritree.heading("#0", text=LH.string("attribute"))
|
|
atritree.heading("#1", text=LH.string("attribute-val"))
|
|
atritree.tag_bind("FA", "<Double-1>", halatribute)
|
|
atritree.tag_bind("OA", "<Double-1>", HMPC)
|
|
atritree.tag_bind("SID", "<Double-1>", copySID)
|
|
atritree.grid(row=2, column=0)
|
|
|
|
#right click menu
|
|
rmenu = tk.Menu(container, tearoff=0)
|
|
rmenu.add_command(label=LH.string("rename"), command=renameobj)
|
|
rmenu.add_command(label=LH.string("delete"), command=delobj)
|
|
|
|
objtree.bind("<Button-3>", rpopup)
|
|
|
|
#menu init
|
|
menu = tk.Menu(container)
|
|
container.config(menu=menu)
|
|
filemenu = tk.Menu(menu)
|
|
menu.add_cascade(label=LH.string("file"), menu=filemenu)
|
|
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()
|
|
#create logs var
|
|
clog = tk.BooleanVar()
|
|
filemenu.add_checkbutton(label=LH.string("clog"), onvalue=1, offvalue=0, variable=clog)
|
|
filemenu.add_separator()
|
|
filemenu.add_command(label=LH.string("export"), command=export)
|
|
filemenu.add_command(label=LH.string("import"), command=lambda: load(False))
|
|
filemenu.add_separator()
|
|
filemenu.add_command(label=LH.string("exit"), command=container.quit)
|
|
|
|
addmenu = tk.Menu(menu)
|
|
menu.add_cascade(label=LH.string("add"), menu=addmenu)
|
|
addmenu.add_command(label=LH.string("obj"), command=lambda: add("obj"))
|
|
addmenu.add_command(label=LH.string("script"), command=lambda: add("script"))
|
|
addmenu.add_command(label=LH.string("sound"), command=lambda: add("sound"))
|
|
addmenu.add_separator()
|
|
addmenu.add_command(label=LH.string("IPS"), command=importPS)
|
|
addmenu.add_command(label=LH.string("COBS"), command=lambda: COBS(acode(" ")))
|
|
#addmenu.add_command(label=LH.string("obj"), command=lambda: muladd("obj"))
|
|
|
|
testmenu = tk.Menu(menu)
|
|
menu.add_cascade(label=LH.string("testing"), menu=testmenu)
|
|
testmenu.add_command(label=LH.string("test"), command=testing, image=icons["test"], compound="left")
|
|
testmenu.add_command(label=LH.string("stest"), command=stoptest, image=icons["stop-test"], compound="left")
|
|
|
|
buildmenu = tk.Menu(menu)
|
|
menu.add_cascade(label=LH.string("building"), menu=buildmenu)
|
|
buildmenu.add_command(label=LH.string("build"), command=build, image=icons["build"], compound="left")
|
|
|
|
settings = tk.Menu(menu)
|
|
menu.add_cascade(label=LH.string("settings"), menu=settings)
|
|
settings.add_command(label=LH.string("gamex"), command=changegamex)
|
|
settings.add_command(label=LH.string("gamey"), command=changegamey)
|
|
|
|
langmenu = tk.Menu(menu)
|
|
menu.add_cascade(label=LH.string("langs"), menu=langmenu)
|
|
for i in LH.getlangs():
|
|
langmenu.add_command(label=i, command=lambda i=i: selectlang(i))
|
|
|
|
container.mainloop()
|
|
|
|
# attribute changers
|
|
def ats(mode, old):
|
|
#mode 0 = string
|
|
#mode 1 = single character
|
|
out = easygui.enterbox(LH.string("newval"), LH.string("newval"))
|
|
if out:
|
|
if mode == 1 and len(out) != 1:
|
|
messagebox.showerror(LH.string("error"), LH.string("SCE"))
|
|
return "N"
|
|
return out
|
|
else:
|
|
return old
|
|
|
|
def anum(old):
|
|
out = easygui.enterbox(LH.string("newval"), LH.string("newval"))
|
|
if out:
|
|
if "." in out:
|
|
try:
|
|
out = float(out)
|
|
return out
|
|
except ValueError:
|
|
return old
|
|
else:
|
|
return int(out)
|
|
else:
|
|
return old
|
|
|
|
def abool(old):
|
|
out = easygui.boolbox(LH.string("newval"), LH.string("newval"), (LH.string("true"), LH.string("false")))
|
|
return out
|
|
|
|
def acode(old):
|
|
out = easygui.textbox(LH.string("newval"), LH.string("newval"), old)
|
|
if out:
|
|
return out
|
|
else:
|
|
return old
|
|
|
|
def apath(old, ext):
|
|
new = filedialog.askopenfilename(defaultextension=ext, filetypes=(ext))
|
|
if new:
|
|
return new
|
|
else:
|
|
return old
|
|
|
|
def aNULL(old):
|
|
return old
|
|
|
|
def aposdone():
|
|
global wait
|
|
wait = False
|
|
|
|
def aposx(old):
|
|
global wait
|
|
wait = True
|
|
temp = tk.Toplevel()
|
|
butframe = tk.Frame(temp)
|
|
currentvar = tk.DoubleVar(temp, value=old)
|
|
current = tk.Entry(temp, textvariable=currentvar)
|
|
current.grid(row=0)
|
|
b1 = tk.Button(butframe, image=icons["ar-left"], command=lambda: currentvar.set(currentvar.get()-1))
|
|
b2 = tk.Button(butframe, image=icons["ar-right"], command=lambda: currentvar.set(currentvar.get()+1))
|
|
b1.grid(row=0, column=0)
|
|
b2.grid(row=0, column=1)
|
|
butframe.grid(row=1)
|
|
b3 = tk.Button(temp, text=LH.string("done"), command=aposdone)
|
|
b3.grid(row=3)
|
|
while wait == True:
|
|
temp.update()
|
|
tempvar = currentvar.get()
|
|
temp.destroy()
|
|
numbers = list(string.digits)
|
|
numbers.append("-")
|
|
numbers.append(".")
|
|
for i in str(tempvar):
|
|
if not i in numbers:
|
|
return old
|
|
return tempvar
|
|
|
|
def aposy(old):
|
|
global wait
|
|
wait = True
|
|
temp = tk.Toplevel()
|
|
butframe = tk.Frame(temp)
|
|
currentvar = tk.DoubleVar(temp, value=old)
|
|
current = tk.Entry(temp, textvariable=currentvar)
|
|
current.grid(row=0)
|
|
b1 = tk.Button(butframe, image=icons["ar-up"], command=lambda: currentvar.set(currentvar.get()-1))
|
|
b2 = tk.Button(butframe, image=icons["ar-down"], command=lambda: currentvar.set(currentvar.get()+1))
|
|
b1.grid(row=0, column=0)
|
|
b2.grid(row=1, column=0)
|
|
butframe.grid(row=1)
|
|
b3 = tk.Button(temp, text=LH.string("done"), command=aposdone)
|
|
b3.grid(row=3)
|
|
while wait == True:
|
|
temp.update()
|
|
tempvar = currentvar.get()
|
|
temp.destroy()
|
|
numbers = list(string.digits)
|
|
numbers.append("-")
|
|
numbers.append(".")
|
|
for i in str(tempvar):
|
|
if not i in numbers:
|
|
return old
|
|
return tempvar
|
|
|
|
def execgame(gametree, shouldlog=True):
|
|
global GUIe
|
|
global preview
|
|
global clog
|
|
global models
|
|
preview = hashengine.game(renderer=nullrend, sounddir="/")
|
|
GUIe = False
|
|
models = []
|
|
load(False, False, "", str(gametree))
|
|
clog = shouldlog
|
|
run()
|
|
|
|
class rsound:
|
|
def __init__(self):
|
|
self.spath = ""
|
|
self.sdata = b""
|
|
|
|
class sound():
|
|
def __init__(self, new):
|
|
self.spath = os.path.basename(new).split(".")[0]
|
|
self.sdata = hashengine.loadsound(new)
|
|
|
|
global types
|
|
global ignoreat
|
|
global valtypes
|
|
global extypes
|
|
global attypes
|
|
global crucial
|
|
global DCTE
|
|
global gamexsize
|
|
global gameysize
|
|
gamexsize = 10
|
|
gameysize = 10
|
|
crucial = ["obj"]
|
|
types = hashengine.enum({"obj": hashengine.obj, "script": script, "rawsound": rsound, "sound": lambda: sound(apath("", [("Wave files", ".wave .wav")]))})
|
|
ignoreat = ["ID", "execute", "sdata"]
|
|
DCTE = ["code"]
|
|
"""self.position = vector2()
|
|
self.char = " "
|
|
self.ID = 0
|
|
self.gravity = 0
|
|
self.acceleration = vector2()
|
|
self.velocity = vector2()
|
|
self.friction = 0
|
|
self.collide = True
|
|
self.touch = True
|
|
self.anchored = False
|
|
self.bcolor = color3(255, 255, 255)
|
|
self.fcolor = color3()"""
|
|
valtypes = {
|
|
"char": lambda old: ats(1, old),
|
|
"gravity": anum,
|
|
"x": aposx, #anum
|
|
"y": aposy, #anum
|
|
"z": anum,
|
|
"r": anum,
|
|
"g": anum,
|
|
"b": anum,
|
|
"friction": anum,
|
|
"collide": abool,
|
|
"touch": abool,
|
|
"anchored": abool,
|
|
"code": acode,
|
|
"spath": aNULL,
|
|
}
|
|
#lambda old: apath(old, [("Wave files", ".wave .wav")])
|
|
extypes = list(valtypes.keys())
|
|
attypes = {
|
|
"vector2": hashengine.vector2,
|
|
"color3": hashengine.color3,
|
|
}
|
|
if __name__ == "__main__":
|
|
GUIinit() |