This commit is contained in:
恍兮惚兮 2024-04-24 01:20:14 +08:00
parent 8aa1920bab
commit 635046fe6c
11 changed files with 316 additions and 318 deletions

View File

@ -798,15 +798,7 @@ def setTabThree_lazy(self):
("缩放方式", 4), ("缩放方式", 4),
( (
getsimplecombobox( getsimplecombobox(
_TRL( static_data["scalemethods_vis"],
[
"Magpie",
"ALT+ENTER",
"SW_SHOWMAXIMIZED",
"LosslessScaling",
"Magpie_External",
]
),
globalconfig, globalconfig,
"fullscreenmethod_3", "fullscreenmethod_3",
), ),

View File

@ -3,7 +3,7 @@ import functools
import threading import threading
import os, sys import os, sys
from PyQt5.QtCore import QT_VERSION_STR from PyQt5.QtCore import QT_VERSION_STR
import windows import windows, importlib
from traceback import print_exc from traceback import print_exc
from PyQt5.QtCore import Qt, pyqtSignal from PyQt5.QtCore import Qt, pyqtSignal
import qtawesome import qtawesome
@ -20,7 +20,6 @@ from myutils.hwnd import mouseselectwindow, grabwindow, getExeIcon
from gui.dialog_savedgame import dialog_savedgame_new from gui.dialog_savedgame import dialog_savedgame_new
from gui.dialog_memory import dialog_memory from gui.dialog_memory import dialog_memory
from gui.textbrowser import Textbrowser from gui.textbrowser import Textbrowser
from myutils.fullscreen import fullscreen
from gui.rangeselect import moveresizegame, rangeselct_function from gui.rangeselect import moveresizegame, rangeselct_function
from gui.usefulwidget import resizableframeless, isinrect from gui.usefulwidget import resizableframeless, isinrect
from gui.dialog_savedgame import browserdialog from gui.dialog_savedgame import browserdialog
@ -659,7 +658,8 @@ class QUnFrameWindow(resizableframeless):
static_data["allhira"], static_data["allkata"] static_data["allhira"], static_data["allkata"]
) )
self.isletgamefullscreened = False self.isletgamefullscreened = False
self.fullscreenmanager = fullscreen(self._externalfsend) self.fullscreenmanager = None
self.fullscreenmethod = None
self._isTracking = False self._isTracking = False
self.isontop = True self.isontop = True
self._TitleLabel = QLabel(self) self._TitleLabel = QLabel(self)
@ -721,11 +721,12 @@ class QUnFrameWindow(resizableframeless):
for pid in gobject.baseobject.textsource.pids: for pid in gobject.baseobject.textsource.pids:
winsharedutils.SetProcessMute(pid, self.processismuteed) winsharedutils.SetProcessMute(pid, self.processismuteed)
def _externalfsend(self): def _externalfsend(self, current):
self.isletgamefullscreened = False self.isletgamefullscreened = current
self.refreshtooliconsignal.emit() self.refreshtooliconsignal.emit()
def _fullsgame(self): def _fullsgame(self):
try:
if gobject.baseobject.textsource and gobject.baseobject.textsource.hwnd: if gobject.baseobject.textsource and gobject.baseobject.textsource.hwnd:
_hwnd = gobject.baseobject.textsource.hwnd _hwnd = gobject.baseobject.textsource.hwnd
else: else:
@ -733,9 +734,28 @@ class QUnFrameWindow(resizableframeless):
_pid = windows.GetWindowThreadProcessId(_hwnd) _pid = windows.GetWindowThreadProcessId(_hwnd)
if _pid == os.getpid(): if _pid == os.getpid():
return return
self.isletgamefullscreened = not self.isletgamefullscreened # self.isletgamefullscreened = not self.isletgamefullscreened
self.refreshtoolicon() # self.refreshtoolicon()
self.fullscreenmanager(_hwnd, self.isletgamefullscreened) skip = False
if (self.fullscreenmanager is None) or (
self.fullscreenmethod != globalconfig["fullscreenmethod_3"]
):
self.fullscreenmethod = globalconfig["fullscreenmethod_3"]
if self.fullscreenmanager:
skip = self.fullscreenmanager.endX()
self.fullscreenmanager = importlib.import_module(
"scalemethod."
+ static_data["scalemethods"][globalconfig["fullscreenmethod_3"]]
).Method(self._externalfsend)
if skip:
return
self.fullscreenmanager.callstatuschange(
_hwnd
) # , self.isletgamefullscreened)
except:
print_exc()
def changemousetransparentstate(self, idx): def changemousetransparentstate(self, idx):
if idx == 0: if idx == 0:
@ -988,7 +1008,8 @@ class QUnFrameWindow(resizableframeless):
self.buttons.append(button) self.buttons.append(button)
def closeEvent(self, a0) -> None: def closeEvent(self, a0) -> None:
self.fullscreenmanager.end() if self.fullscreenmanager:
self.fullscreenmanager.endX()
gobject.baseobject.isrunning = False gobject.baseobject.isrunning = False
self.tray.hide() self.tray.hide()
self.tray = None self.tray = None

View File

@ -1,291 +0,0 @@
import os, json
import windows, winsharedutils
from winsharedutils import letfullscreen, recoverwindow
from myutils.config import globalconfig, magpie_config
from myutils.hwnd import ListProcess, injectdll
from traceback import print_exc
from myutils.subproc import subproc_w
import time
from myutils.wrapper import threader
import re
class fullscreen:
def __init__(self, _externalfsend) -> None:
self.savewindowstatus = None
self._externalfsend = _externalfsend
self.status = False
self.lasthwnd = None
self.injectedpids = set()
def end(self):
if self.status and self.lasthwnd:
self.__call__(self.lasthwnd, not self.status)
@property
def fsmethod(self):
return globalconfig["fullscreenmethod_3"]
def internal_stopped(self):
self._externalfsend()
self.status = False
@threader
def _wait_lossless_stop_external(self):
while windows.FindWindow("LosslessScaling", None) == 0:
time.sleep(0.5)
while windows.FindWindow("LosslessScaling", None):
time.sleep(0.5)
self.internal_stopped()
def runlossless(self):
exes = [_[1] for _ in ListProcess()]
path = globalconfig["lossless"]["path"]
pexe = os.path.join(path, "LosslessScaling.exe")
if pexe.replace("/", "\\") not in exes:
subproc_w(pexe, cwd=path, name="LosslessScaling")
time.sleep(1)
if globalconfig["hooklossless"]:
for pid, exe in ListProcess():
if exe == pexe.replace("/", "\\"):
if pid in self.injectedpids:
continue
dll = os.path.abspath("./files/plugins/hookmagpie.dll")
injecter = os.path.abspath(
"./files/plugins/shareddllproxy{}.exe".format("64")
)
injectdll(pid, injecter, dll)
self.injectedpids.add(pid)
break
def _external_lossless(self, hwnd, full):
if full:
self.runlossless()
# self._wait_lossless_stop_external()
windows.SetForegroundWindow(hwnd)
time.sleep(0.1)
configpath = os.path.join(
os.environ["LOCALAPPDATA"], "Lossless Scaling/Settings.xml"
)
if os.path.exists(configpath) == False:
return
with open(configpath, "r", encoding="utf8") as ff:
config = ff.read()
Hotkey = re.findall("<Hotkey>(.*?)</Hotkey>", config)[0]
hotkHotkeyModifierKeysey = re.findall(
"<HotkeyModifierKeys>(.*?)</HotkeyModifierKeys>", config
)[0]
mods = hotkHotkeyModifierKeysey.split(" ")
vkcode = windows.MapVirtualKey(Hotkey)
mp1 = {"Shift": 16, "Windows": 91, "Control": 17, "Alt": 18}
for k in mods:
windows.keybd_event(mp1[k], 0, 0, 0)
windows.keybd_event(vkcode, 0, 0, 0)
windows.keybd_event(vkcode, 0, windows.KEYEVENTF_KEYUP, 0)
for k in mods:
windows.keybd_event(mp1[k], 0, windows.KEYEVENTF_KEYUP, 0)
def runmagpie(self):
if windows.FindWindow("Magpie_Hotkey", None) == 0:
subproc_w(
os.path.join(globalconfig["magpiepath"], "Magpie.exe"),
cwd=globalconfig["magpiepath"],
name="magpie",
)
while windows.FindWindow("Magpie_Hotkey", None) == 0:
time.sleep(0.5)
if globalconfig["hookmagpie"]:
pid = windows.GetWindowThreadProcessId(
windows.FindWindow("Magpie_Hotkey", None)
)
if pid in self.injectedpids:
return
dll = os.path.abspath("./files/plugins/hookmagpie.dll")
injecter = os.path.abspath(
"./files/plugins/shareddllproxy{}.exe".format("64")
)
injectdll([pid], injecter, dll)
self.injectedpids.add(pid)
@threader
def _wait_magpie_stop_external(self):
while (
windows.FindWindow(
"Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22", None
)
== 0
):
time.sleep(0.5)
while windows.FindWindow(
"Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22", None
):
time.sleep(0.5)
self.internal_stopped()
def _external_magpie(self, hwnd, full):
configpath = os.path.join(globalconfig["magpiepath"], "config/config.json")
if os.path.exists(configpath) == False:
version = winsharedutils.queryversion(
os.path.join(globalconfig["magpiepath"], "Magpie.exe")
)
checks = [
os.path.join(
os.environ["LOCALAPPDATA"], "Magpie/config/v2/config.json"
),
os.path.join(os.environ["LOCALAPPDATA"], "Magpie/config/config.json"),
]
if version:
if version[:3] >= (0, 10, 100): # v0.11.0-preview1
checks = [checks[0]]
else:
checks = [checks[1]]
for ck in checks:
if os.path.exists(ck):
configpath = ck
break
if os.path.exists(configpath) == False:
return
with open(configpath, "r", encoding="utf8") as ff:
config = json.load(ff)
autoRestore = config["autoRestore"]
shortcuts = config["shortcuts"]["scale"]
mp1 = {"SHIFT": 16, "WIN": 91, "CTRL": 17, "ALT": 18}
mp = {0x100: "WIN", 0x200: "CTRL", 0x400: "ALT", 0x800: "SHIFT"}
if full:
self.runmagpie()
if autoRestore == False:
self._wait_magpie_stop_external()
windows.SetForegroundWindow(hwnd)
time.sleep(0.1)
for k in mp:
if shortcuts & k != 0:
windows.keybd_event(mp1[mp[k]], 0, 0, 0)
k2 = shortcuts & 0xFF
windows.keybd_event(k2, 0, 0, 0)
windows.keybd_event(k2, 0, windows.KEYEVENTF_KEYUP, 0)
for k in mp:
if shortcuts & k != 0:
windows.keybd_event(mp1[mp[k]], 0, windows.KEYEVENTF_KEYUP, 0)
# def _4(self,hwnd,full):
# if full:
# self.engine= subproc_w(r'./files/plugins/shareddllproxy64.exe lossless "{}" "{}" {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}'.format(globalconfig['lossless']['path'],hwnd,
# globalconfig['lossless']['scalingMode'],
# globalconfig['lossless']['scalingFitMode'],
# globalconfig['lossless']['scalingType'],
# globalconfig['lossless']['scalingSubtype'],
# globalconfig['lossless']['scaleFactor'],
# globalconfig['lossless']['resizeBeforeScale'],
# globalconfig['lossless']['windowedMode'],
# globalconfig['lossless']['sharpness'],
# globalconfig['lossless']['VRS'],
# globalconfig['lossless']['clipCursor'],
# globalconfig['lossless']['cursorSensitivity'],
# globalconfig['lossless']['hideCursor'],
# globalconfig['lossless']['scaleCursor'],
# globalconfig['lossless']['doubleBuffering'],
# globalconfig['lossless']['vrrSupport'],
# globalconfig['lossless']['hdrSupport'],
# globalconfig['lossless']['allowTearing'],
# globalconfig['lossless']['legacyCaptureApi'],
# globalconfig['lossless']['drawFps'],
# globalconfig['lossless']['gpuId'],
# globalconfig['lossless']['displayId'],
# globalconfig['lossless']['captureOffsetLeft'],
# globalconfig['lossless']['captureOffsetTop'],
# globalconfig['lossless']['captureOffsetRight'],
# globalconfig['lossless']['captureOffsetBottom'],
# globalconfig['lossless']['multiDisplayMode'],
# os.getpid(),
# globalconfig['lossless']['frameGeneration'],
# globalconfig['lossless']['syncInterval']),cwd=globalconfig['lossless']['path'])
# self._waitenginestop()
# else:
# endevent =windows.AutoHandle(windows.CreateEvent(False, False,'LOSSLESS_WAITFOR_STOP_SIGNAL'+str(self.engine.pid)))
# windows.SetEvent(endevent)
@threader
def _waitenginestop_magpie(self):
self.engine.wait()
self.internal_stopped()
def _magpie_builtin(self, hwnd, full):
if full:
profiles_index = globalconfig["profiles_index"]
if profiles_index > len(magpie_config["profiles"]):
profiles_index = 0
jspath = os.path.abspath("./userconfig/magpie_config.json")
with open(jspath, "w", encoding="utf-8") as ff:
ff.write(
json.dumps(
magpie_config, ensure_ascii=False, sort_keys=False, indent=4
)
)
self.engine = subproc_w(
'./files/plugins/Magpie/Magpie.Core.exe {} {} "{}"'.format(
profiles_index, hwnd, jspath
),
cwd="./files/plugins/Magpie/",
)
self._waitenginestop_magpie()
else:
windows.SendMessage(
windows.FindWindow("Magpie_Core_CLI_Message", None),
windows.RegisterWindowMessage("Magpie_Core_CLI_Message_Stop"),
)
# magpie9
# def _0(self,hwnd,full):
# if full:
# SetForegroundWindow(hwnd )
# callmagpie(('./files/plugins/Magpie_v0.9.1'),hwnd,globalconfig['magpiescalemethod'],globalconfig['magpieflags'],globalconfig['magpiecapturemethod'])
# else:
# hwnd=FindWindow('Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22',None)
# if hwnd==0:
# return
# WM_DESTORYHOST=RegisterWindowMessage( "MAGPIE_WM_DESTORYHOST")
# SendMessage(hwnd, WM_DESTORYHOST)
def _alt_enter(self, hwnd, full):
windows.SetForegroundWindow(hwnd)
windows.keybd_event(18, 0, 0, 0) # alt
windows.keybd_event(13, 0, 0, 0) # enter
windows.keybd_event(13, 0, windows.KEYEVENTF_KEYUP, 0)
windows.keybd_event(18, 0, windows.KEYEVENTF_KEYUP, 0)
def _SW_SHOWMAXIMIZED(self, hwnd, full):
if full:
self.savewindowstatus = letfullscreen(hwnd)
else:
recoverwindow(hwnd, self.savewindowstatus)
@threader
def __call__(self, hwnd=0, full=False):
try:
[
self._magpie_builtin,
self._alt_enter,
self._SW_SHOWMAXIMIZED,
self._external_lossless,
self._external_magpie,
][self.fsmethod](hwnd, full)
self.status = full
self.lasthwnd = hwnd
except:
print_exc()

View File

@ -0,0 +1,10 @@
from scalemethod.base import scalebase
from winsharedutils import letfullscreen, recoverwindow
class Method(scalebase):
def changestatus(self, hwnd, full):
if full:
self.savewindowstatus = letfullscreen(hwnd)
else:
recoverwindow(hwnd, self.savewindowstatus)

View File

@ -0,0 +1,12 @@
from scalemethod.base import scalebase
import windows
class Method(scalebase):
def changestatus(self, hwnd, full):
windows.SetForegroundWindow(hwnd)
windows.keybd_event(18, 0, 0, 0) # alt
windows.keybd_event(13, 0, 0, 0) # enter
windows.keybd_event(13, 0, windows.KEYEVENTF_KEYUP, 0)
windows.keybd_event(18, 0, windows.KEYEVENTF_KEYUP, 0)

View File

@ -0,0 +1,35 @@
class scalebase:
def __init__(self, setuistatus) -> None:
self._setuistatus = setuistatus
self.full = True
self.hwnd = None
self.hasend = False
self.init()
def setuistatus(self, current):
if self.hasend:
return
self._setuistatus(current)
self.full = not current
def callstatuschange(self, hwnd):
self.hwnd = hwnd
self.changestatus(hwnd, self.full)
self.setuistatus(self.full)
def endX(self):
if not self.full and self.hwnd:
self.callstatuschange(self.hwnd)
self.end()
return True
self.hasend = True
return False
def changestatus(self, hwnd, full):
raise Exception
def init(self):
pass
def end(self):
pass

View File

@ -0,0 +1,76 @@
from scalemethod.base import scalebase
import os
import windows
from myutils.config import globalconfig
from myutils.hwnd import ListProcess, injectdll
from myutils.subproc import subproc_w
import time
from myutils.wrapper import threader
import re
class Method(scalebase):
@threader
def _wait_lossless_stop_external(self):
while windows.FindWindow("LosslessScaling", None) == 0:
time.sleep(0.5)
while windows.FindWindow("LosslessScaling", None):
time.sleep(0.5)
self.setuistatus(False)
def init(self):
self.injectedpids = set()
def runlossless(self):
exes = [_[1] for _ in ListProcess()]
path = globalconfig["lossless"]["path"]
pexe = os.path.join(path, "LosslessScaling.exe")
if pexe.replace("/", "\\") not in exes:
subproc_w(pexe, cwd=path, name="LosslessScaling")
time.sleep(1)
if globalconfig["hooklossless"]:
for pid, exe in ListProcess():
if exe == pexe.replace("/", "\\"):
if pid in self.injectedpids:
continue
dll = os.path.abspath("./files/plugins/hookmagpie.dll")
injecter = os.path.abspath(
"./files/plugins/shareddllproxy{}.exe".format("64")
)
injectdll(pid, injecter, dll)
self.injectedpids.add(pid)
break
def changestatus(self, hwnd, full):
if full:
self.runlossless()
# self._wait_lossless_stop_external()
windows.SetForegroundWindow(hwnd)
time.sleep(0.1)
configpath = os.path.join(
os.environ["LOCALAPPDATA"], "Lossless Scaling/Settings.xml"
)
if os.path.exists(configpath) == False:
return
with open(configpath, "r", encoding="utf8") as ff:
config = ff.read()
Hotkey = re.findall("<Hotkey>(.*?)</Hotkey>", config)[0]
hotkHotkeyModifierKeysey = re.findall(
"<HotkeyModifierKeys>(.*?)</HotkeyModifierKeys>", config
)[0]
mods = hotkHotkeyModifierKeysey.split(" ")
vkcode = windows.MapVirtualKey(Hotkey)
mp1 = {"Shift": 16, "Windows": 91, "Control": 17, "Alt": 18}
for k in mods:
windows.keybd_event(mp1[k], 0, 0, 0)
windows.keybd_event(vkcode, 0, 0, 0)
windows.keybd_event(vkcode, 0, windows.KEYEVENTF_KEYUP, 0)
for k in mods:
windows.keybd_event(mp1[k], 0, windows.KEYEVENTF_KEYUP, 0)

View File

@ -0,0 +1,103 @@
from scalemethod.base import scalebase
import os, json
import windows, winsharedutils
from myutils.config import globalconfig
from myutils.hwnd import injectdll
from myutils.subproc import subproc_w
import time
from myutils.wrapper import threader
class Method(scalebase):
def init(self):
self.injectedpids = set()
def runmagpie(self):
if windows.FindWindow("Magpie_Hotkey", None) == 0:
subproc_w(
os.path.join(globalconfig["magpiepath"], "Magpie.exe"),
cwd=globalconfig["magpiepath"],
name="magpie",
)
while windows.FindWindow("Magpie_Hotkey", None) == 0:
time.sleep(0.5)
if globalconfig["hookmagpie"]:
pid = windows.GetWindowThreadProcessId(
windows.FindWindow("Magpie_Hotkey", None)
)
if pid in self.injectedpids:
return
dll = os.path.abspath("./files/plugins/hookmagpie.dll")
injecter = os.path.abspath(
"./files/plugins/shareddllproxy{}.exe".format("64")
)
injectdll([pid], injecter, dll)
self.injectedpids.add(pid)
@threader
def _wait_magpie_stop_external(self):
while (
windows.FindWindow(
"Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22", None
)
== 0
):
time.sleep(0.5)
while windows.FindWindow(
"Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22", None
):
time.sleep(0.5)
self.setuistatus(False)
def changestatus(self, hwnd, full):
configpath = os.path.join(globalconfig["magpiepath"], "config/config.json")
if os.path.exists(configpath) == False:
version = winsharedutils.queryversion(
os.path.join(globalconfig["magpiepath"], "Magpie.exe")
)
checks = [
os.path.join(
os.environ["LOCALAPPDATA"], "Magpie/config/v2/config.json"
),
os.path.join(os.environ["LOCALAPPDATA"], "Magpie/config/config.json"),
]
if version:
if version[:3] >= (0, 10, 100): # v0.11.0-preview1
checks = [checks[0]]
else:
checks = [checks[1]]
for ck in checks:
if os.path.exists(ck):
configpath = ck
break
if os.path.exists(configpath) == False:
return
with open(configpath, "r", encoding="utf8") as ff:
config = json.load(ff)
autoRestore = config["autoRestore"]
shortcuts = config["shortcuts"]["scale"]
mp1 = {"SHIFT": 16, "WIN": 91, "CTRL": 17, "ALT": 18}
mp = {0x100: "WIN", 0x200: "CTRL", 0x400: "ALT", 0x800: "SHIFT"}
if full:
self.runmagpie()
if autoRestore == False:
self._wait_magpie_stop_external()
windows.SetForegroundWindow(hwnd)
time.sleep(0.1)
for k in mp:
if shortcuts & k != 0:
windows.keybd_event(mp1[mp[k]], 0, 0, 0)
k2 = shortcuts & 0xFF
windows.keybd_event(k2, 0, 0, 0)
windows.keybd_event(k2, 0, windows.KEYEVENTF_KEYUP, 0)
for k in mp:
if shortcuts & k != 0:
windows.keybd_event(mp1[mp[k]], 0, windows.KEYEVENTF_KEYUP, 0)

View File

@ -0,0 +1,39 @@
from scalemethod.base import scalebase
import os, json
import windows
from myutils.config import globalconfig, magpie_config
from myutils.subproc import subproc_w
from myutils.wrapper import threader
class Method(scalebase):
@threader
def _waitenginestop_magpie(self):
self.engine.wait()
self.setuistatus(False)
def changestatus(self, hwnd, full):
if full:
profiles_index = globalconfig["profiles_index"]
if profiles_index > len(magpie_config["profiles"]):
profiles_index = 0
jspath = os.path.abspath("./userconfig/magpie_config.json")
with open(jspath, "w", encoding="utf-8") as ff:
ff.write(
json.dumps(
magpie_config, ensure_ascii=False, sort_keys=False, indent=4
)
)
self.engine = subproc_w(
'./files/plugins/Magpie/Magpie.Core.exe {} {} "{}"'.format(
profiles_index, hwnd, jspath
),
cwd="./files/plugins/Magpie/",
)
self._waitenginestop_magpie()
else:
windows.SendMessage(
windows.FindWindow("Magpie_Core_CLI_Message", None),
windows.RegisterWindowMessage("Magpie_Core_CLI_Message_Stop"),
)

View File

@ -334,6 +334,7 @@
"./files/plugins/DLL32/libmecab.dll", "./files/plugins/DLL32/libmecab.dll",
"./files/plugins/DLL32/libcurl.dll" "./files/plugins/DLL32/libcurl.dll"
] ]
} },
"scalemethods":["magpie_builtin","alt_enter","SW_SHOWMAXIMIZED","external_lossless","external_magpie"],
"scalemethods_vis":["Magpie","ALT+ENTER","SW_SHOWMAXIMIZED","LosslessScaling","Magpie_External"]
} }

View File

@ -35,7 +35,7 @@ for f in ['LunaTranslator_admin.exe','LunaTranslator.exe']:
shutil.copytree(r'.\files',rf'{targetdir}\files') shutil.copytree(r'.\files',rf'{targetdir}\files')
shutil.copy(r'..\LICENSE',targetdir) shutil.copy(r'..\LICENSE',targetdir)
for f in ['transoptimi','hiraparse','ocrengines','translator','cishu','tts','network','textoutput']: for f in ['transoptimi','hiraparse','ocrengines','translator','cishu','tts','network','textoutput','scalemethod']:
shutil.copytree(rf'.\LunaTranslator\{f}',rf'{targetdir_in}\{f}') shutil.copytree(rf'.\LunaTranslator\{f}',rf'{targetdir_in}\{f}')
def remove(f): def remove(f):