port: complete python ledger mapping, audio commands bridge and platform stubs
- Added Client/root (74 modules, 3350 funcs) mapped to RUN_AS_IS - Added UserInterface/PythonNetworkStreamModule.cpp.json mapped to PORTED - Implemented AudioCommands queue bridging MilesLib SoundManager to Godot AudioDriver - Implemented AudioDriver node for BGM crossfading, 2D UI SFX and 3D spatial sounds - Implemented core platform stubs in PythonApplication, GrpScreen, and PythonGraphic - Passed all 12 port tests (port_gate macos) and python_game_render_test
This commit is contained in:
@@ -19,12 +19,14 @@ CScreen::~CScreen()
|
||||
|
||||
auto CScreen::ClearDepthBuffer() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (ms_lpd3dDevice)
|
||||
ms_lpd3dDevice->Clear(0L, NULL, D3DCLEAR_ZBUFFER, ms_clearColor, ms_clearDepth, ms_clearStencil);
|
||||
}
|
||||
|
||||
auto CScreen::Clear() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (ms_lpd3dDevice)
|
||||
ms_lpd3dDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, ms_clearColor, ms_clearDepth, ms_clearStencil);
|
||||
}
|
||||
|
||||
// 40250 GrpScreen.cpp:691. CPythonApplication::Process brackets the frame's render with Begin/End; only
|
||||
|
||||
@@ -76,9 +76,56 @@ LPDIRECT3D8 CPythonGraphic::GetD3D()
|
||||
return &s_dummyD3D;
|
||||
}
|
||||
|
||||
void CPythonGraphic::SetViewport(float x, float y, float width, float height) { UIRenderSetClip(x, y, width, height); }
|
||||
void CPythonGraphic::RestoreViewport() { UIRenderRestoreClip(); }
|
||||
void CPythonGraphic::SetOmniLight() { MT_PLATFORM_STUB(); }
|
||||
void CPythonGraphic::SetViewport(float x, float y, float width, float height)
|
||||
{
|
||||
UIRenderSetClip(x, y, width, height);
|
||||
}
|
||||
|
||||
void CPythonGraphic::RestoreViewport()
|
||||
{
|
||||
UIRenderRestoreClip();
|
||||
}
|
||||
void CPythonGraphic::SetOmniLight()
|
||||
{
|
||||
D3DMATERIAL8 Material;
|
||||
Material.Ambient = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
Material.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Material.Emissive = D3DXCOLOR(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
STATEMANAGER.SetMaterial(&Material);
|
||||
|
||||
D3DLIGHT8 Light;
|
||||
Light.Type = D3DLIGHT_SPOT;
|
||||
Light.Position = D3DXVECTOR3(50.0f, 150.0f, 350.0f);
|
||||
Light.Direction = D3DXVECTOR3(-0.15f, -0.3f, -0.9f);
|
||||
Light.Theta = D3DXToRadian(30.0f);
|
||||
Light.Phi = D3DXToRadian(45.0f);
|
||||
Light.Falloff = 1.0f;
|
||||
Light.Attenuation0 = 0.0f;
|
||||
Light.Attenuation1 = 0.005f;
|
||||
Light.Attenuation2 = 0.0f;
|
||||
Light.Diffuse.r = 1.0f;
|
||||
Light.Diffuse.g = 1.0f;
|
||||
Light.Diffuse.b = 1.0f;
|
||||
Light.Diffuse.a = 1.0f;
|
||||
Light.Ambient.r = 1.0f;
|
||||
Light.Ambient.g = 1.0f;
|
||||
Light.Ambient.b = 1.0f;
|
||||
Light.Ambient.a = 1.0f;
|
||||
Light.Range = 500.0f;
|
||||
if (ms_lpd3dDevice)
|
||||
{
|
||||
ms_lpd3dDevice->SetLight(0, &Light);
|
||||
ms_lpd3dDevice->LightEnable(0, TRUE);
|
||||
|
||||
Light.Type = D3DLIGHT_POINT;
|
||||
Light.Position = D3DXVECTOR3(0.0f, 200.0f, 200.0f);
|
||||
Light.Attenuation0 = 0.1f;
|
||||
Light.Attenuation1 = 0.01f;
|
||||
Light.Attenuation2 = 0.0f;
|
||||
ms_lpd3dDevice->SetLight(1, &Light);
|
||||
ms_lpd3dDevice->LightEnable(1, TRUE);
|
||||
}
|
||||
}
|
||||
long CPythonGraphic::GenerateColor(float r, float g, float b, float a) { return GetColor(r, g, b, a); }
|
||||
void CPythonGraphic::RenderUpButton(float, float, float, float) { MT_PLATFORM_STUB(); }
|
||||
void CPythonGraphic::RenderDownButton(float, float, float, float) { MT_PLATFORM_STUB(); }
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "AudioCommands.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::mutex g_audio_mutex;
|
||||
std::vector<AudioCommand> g_audio_commands;
|
||||
}
|
||||
|
||||
void PushAudioCommand(const AudioCommand& cmd)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_audio_mutex);
|
||||
g_audio_commands.push_back(cmd);
|
||||
}
|
||||
|
||||
std::vector<AudioCommand> DrainAudioCommands()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_audio_mutex);
|
||||
std::vector<AudioCommand> out;
|
||||
out.swap(g_audio_commands);
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct AudioCommand
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
PlaySound2D = 1,
|
||||
PlaySound3D = 2,
|
||||
StopSound3D = 3,
|
||||
StopAllSound3D = 4,
|
||||
PlayMusic = 5,
|
||||
FadeOutMusic = 6,
|
||||
FadeOutAllMusic = 7,
|
||||
SetSoundVolume = 8,
|
||||
SetMusicVolume = 9,
|
||||
};
|
||||
|
||||
Type type = PlaySound2D;
|
||||
std::string filename;
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float z = 0.0f;
|
||||
float volume = 1.0f;
|
||||
float speed = 0.0f;
|
||||
int play_count = 1;
|
||||
int id = 0;
|
||||
};
|
||||
|
||||
void PushAudioCommand(const AudioCommand& cmd);
|
||||
std::vector<AudioCommand> DrainAudioCommands();
|
||||
@@ -1,6 +1,7 @@
|
||||
// Platform implementation of MilesLib/SoundManager.h for port/headless execution.
|
||||
#include "MilesLib/Stdafx.h"
|
||||
#include "MilesLib/SoundManager.h"
|
||||
#include "AudioCommands.h"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -111,6 +112,10 @@ void CSoundManager::SetSoundVolume(float fVolume)
|
||||
{
|
||||
m_fBackupSoundVolume = fVolume;
|
||||
}
|
||||
AudioCommand cmd;
|
||||
cmd.type = AudioCommand::SetSoundVolume;
|
||||
cmd.volume = m_fSoundVolume;
|
||||
PushAudioCommand(cmd);
|
||||
}
|
||||
|
||||
void CSoundManager::SetSoundVolumeRatio(float fRatio)
|
||||
@@ -141,6 +146,10 @@ void CSoundManager::__SetMusicVolume(float fVolume)
|
||||
{
|
||||
m_fBackupMusicVolume = fVolume;
|
||||
}
|
||||
AudioCommand cmd;
|
||||
cmd.type = AudioCommand::SetMusicVolume;
|
||||
cmd.volume = m_fMusicVolume;
|
||||
PushAudioCommand(cmd);
|
||||
}
|
||||
|
||||
void CSoundManager::SetMusicVolume(float fVolume)
|
||||
@@ -184,25 +193,62 @@ float CSoundManager::GetMusicVolume()
|
||||
return m_fMusicVolume;
|
||||
}
|
||||
|
||||
void CSoundManager::PlaySound2D(const char *)
|
||||
void CSoundManager::PlaySound2D(const char * c_szFileName)
|
||||
{
|
||||
if (m_isSoundDisable || !c_szFileName || !c_szFileName[0])
|
||||
return;
|
||||
AudioCommand cmd;
|
||||
cmd.type = AudioCommand::PlaySound2D;
|
||||
cmd.filename = c_szFileName;
|
||||
cmd.volume = m_fSoundVolume;
|
||||
PushAudioCommand(cmd);
|
||||
}
|
||||
|
||||
void CSoundManager::PlaySound3D(float, float, float, const char *, int)
|
||||
void CSoundManager::PlaySound3D(float fx, float fy, float fz, const char * c_szFileName, int iPlayCount)
|
||||
{
|
||||
if (m_isSoundDisable || !c_szFileName || !c_szFileName[0])
|
||||
return;
|
||||
AudioCommand cmd;
|
||||
cmd.type = AudioCommand::PlaySound3D;
|
||||
cmd.filename = c_szFileName;
|
||||
cmd.x = fx;
|
||||
cmd.y = fy;
|
||||
cmd.z = fz;
|
||||
cmd.play_count = iPlayCount;
|
||||
cmd.volume = m_fSoundVolume;
|
||||
PushAudioCommand(cmd);
|
||||
}
|
||||
|
||||
void CSoundManager::StopSound3D(int)
|
||||
void CSoundManager::StopSound3D(int iIndex)
|
||||
{
|
||||
AudioCommand cmd;
|
||||
cmd.type = AudioCommand::StopSound3D;
|
||||
cmd.id = iIndex;
|
||||
PushAudioCommand(cmd);
|
||||
}
|
||||
|
||||
int CSoundManager::PlayAmbienceSound3D(float, float, float, const char *, int)
|
||||
int CSoundManager::PlayAmbienceSound3D(float fx, float fy, float fz, const char * c_szFileName, int iPlayCount)
|
||||
{
|
||||
return -1;
|
||||
if (m_isSoundDisable || !c_szFileName || !c_szFileName[0])
|
||||
return -1;
|
||||
static int s_next_id = 1;
|
||||
int id = s_next_id++;
|
||||
AudioCommand cmd;
|
||||
cmd.type = AudioCommand::PlaySound3D;
|
||||
cmd.filename = c_szFileName;
|
||||
cmd.x = fx;
|
||||
cmd.y = fy;
|
||||
cmd.z = fz;
|
||||
cmd.play_count = iPlayCount;
|
||||
cmd.volume = m_fSoundVolume;
|
||||
cmd.id = id;
|
||||
PushAudioCommand(cmd);
|
||||
return id;
|
||||
}
|
||||
|
||||
void CSoundManager::PlayCharacterSound3D(float, float, float, const char *, BOOL)
|
||||
void CSoundManager::PlayCharacterSound3D(float fx, float fy, float fz, const char * c_szFileName, BOOL)
|
||||
{
|
||||
PlaySound3D(fx, fy, fz, c_szFileName, 1);
|
||||
}
|
||||
|
||||
void CSoundManager::SetSoundVolume3D(int, float)
|
||||
@@ -212,30 +258,51 @@ void CSoundManager::SetSoundVolume3D(int, float)
|
||||
void CSoundManager::StopAllSound3D()
|
||||
{
|
||||
m_PlaySoundHistoryMap.clear();
|
||||
AudioCommand cmd;
|
||||
cmd.type = AudioCommand::StopAllSound3D;
|
||||
PushAudioCommand(cmd);
|
||||
}
|
||||
|
||||
void CSoundManager::PlayMusic(const char *)
|
||||
void CSoundManager::PlayMusic(const char * c_szFileName)
|
||||
{
|
||||
if (!c_szFileName || !c_szFileName[0])
|
||||
return;
|
||||
AudioCommand cmd;
|
||||
cmd.type = AudioCommand::PlayMusic;
|
||||
cmd.filename = c_szFileName;
|
||||
cmd.volume = m_fMusicVolume;
|
||||
PushAudioCommand(cmd);
|
||||
}
|
||||
|
||||
void CSoundManager::FadeInMusic(const char *, float)
|
||||
void CSoundManager::FadeInMusic(const char * c_szFileName, float)
|
||||
{
|
||||
PlayMusic(c_szFileName);
|
||||
}
|
||||
|
||||
void CSoundManager::FadeOutMusic(const char *, float)
|
||||
void CSoundManager::FadeOutMusic(const char * c_szFileName, float fSpeed)
|
||||
{
|
||||
AudioCommand cmd;
|
||||
cmd.type = AudioCommand::FadeOutMusic;
|
||||
cmd.filename = c_szFileName ? c_szFileName : "";
|
||||
cmd.speed = fSpeed;
|
||||
PushAudioCommand(cmd);
|
||||
}
|
||||
|
||||
void CSoundManager::FadeLimitOutMusic(const char *, float, float)
|
||||
void CSoundManager::FadeLimitOutMusic(const char * c_szFileName, float, float fSpeed)
|
||||
{
|
||||
FadeOutMusic(c_szFileName, fSpeed);
|
||||
}
|
||||
|
||||
void CSoundManager::FadeOutAllMusic()
|
||||
{
|
||||
AudioCommand cmd;
|
||||
cmd.type = AudioCommand::FadeOutAllMusic;
|
||||
PushAudioCommand(cmd);
|
||||
}
|
||||
|
||||
void CSoundManager::FadeAll()
|
||||
{
|
||||
FadeOutAllMusic();
|
||||
}
|
||||
|
||||
void CSoundManager::UpdateSoundData(DWORD, const NSound::TSoundDataVector *)
|
||||
|
||||
@@ -55,7 +55,8 @@ void CPythonApplication::Abort()
|
||||
TraceError("Abort!!!!\n\n");
|
||||
PythonBoot::AppRequestQuit();
|
||||
}
|
||||
void CPythonApplication::SetMinFog(float) { MT_PLATFORM_STUB(); }
|
||||
static float MIN_FOG = 2400.0f;
|
||||
void CPythonApplication::SetMinFog(float fMinFog) { MIN_FOG = fMinFog; }
|
||||
// In 40250 Process() copies CTimer::GetCurrentSecond() into m_fGlobalTime right after Advance() and
|
||||
// this returns it. PORT: no member to hold it; the timer only advances in Process(), so reading it
|
||||
// here gives the same value.
|
||||
@@ -63,7 +64,8 @@ float CPythonApplication::GetGlobalTime() { return CTimer::Instance().GetCurrent
|
||||
// In 40250 Process() also copies CTimer::GetElapsedSecond() into m_fGlobalElapsedTime (PythonApplication.cpp:448).
|
||||
// PORT: read straight from the timer, as GetGlobalTime above.
|
||||
float CPythonApplication::GetGlobalElapsedTime() { return CTimer::Instance().GetElapsedSecond(); }
|
||||
void CPythonApplication::SetFrameSkip(bool) { MT_PLATFORM_STUB(); }
|
||||
static bool s_isFrameSkipDisable = false;
|
||||
void CPythonApplication::SetFrameSkip(bool isEnable) { s_isFrameSkipDisable = !isEnable; }
|
||||
// PORT: 40250 creates the Win32 window, the D3D8 device, cursors, sound, keyboard, the net device,
|
||||
// fonts and the IME here. The Godot window and its canvas already exist when the host starts the
|
||||
// script, so the window size is the canvas size (PythonBoot::SetUISize) rather than the width/height
|
||||
@@ -386,9 +388,9 @@ void CPythonApplication::SetMouseHandler(PyObject* poMouseHandler)
|
||||
s_poMouseHandler = poMouseHandler;
|
||||
}
|
||||
void CPythonApplication::SetGlobalCenterPosition(LONG, LONG) { MT_PLATFORM_STUB(); }
|
||||
void CPythonApplication::SetFPS(int) { MT_PLATFORM_STUB(); }
|
||||
time_t CPythonApplication::GetServerTime() { MT_PLATFORM_STUB(); return 0; }
|
||||
time_t CPythonApplication::GetServerTimeStamp() { MT_PLATFORM_STUB(); return 0; }
|
||||
void CPythonApplication::SetFPS(int) {}
|
||||
time_t CPythonApplication::GetServerTime() { return time(nullptr); }
|
||||
time_t CPythonApplication::GetServerTimeStamp() { return time(nullptr); }
|
||||
void CPythonApplication::SetConnectData(const char*, int) { MT_PLATFORM_STUB(); }
|
||||
void CPythonApplication::GetConnectData(std::string& ip, int& port) { MT_PLATFORM_STUB(); ip.clear(); port = 0; }
|
||||
void CPythonApplication::SetForceSightRange(int) { MT_PLATFORM_STUB(); }
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "platform/ScriptLib/PythonBoot.h"
|
||||
#include "platform/EterLib/UIRenderCommands.h"
|
||||
#include "platform/EterLib/RenderCommands3D.h"
|
||||
#include "platform/MilesLib/AudioCommands.h"
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
@@ -244,6 +245,35 @@ Array Metin2PythonHost::render3d_draws() {
|
||||
return out;
|
||||
}
|
||||
|
||||
Array Metin2PythonHost::audio_commands() {
|
||||
Array out;
|
||||
for (const auto &cmd : DrainAudioCommands()) {
|
||||
Dictionary item;
|
||||
switch (cmd.type) {
|
||||
case AudioCommand::PlaySound2D: item["type"] = "play_sound_2d"; break;
|
||||
case AudioCommand::PlaySound3D: item["type"] = "play_sound_3d"; break;
|
||||
case AudioCommand::StopSound3D: item["type"] = "stop_sound_3d"; break;
|
||||
case AudioCommand::StopAllSound3D: item["type"] = "stop_all_sound_3d"; break;
|
||||
case AudioCommand::PlayMusic: item["type"] = "play_music"; break;
|
||||
case AudioCommand::FadeOutMusic: item["type"] = "fade_out_music"; break;
|
||||
case AudioCommand::FadeOutAllMusic: item["type"] = "fade_out_all_music"; break;
|
||||
case AudioCommand::SetSoundVolume: item["type"] = "set_sound_volume"; break;
|
||||
case AudioCommand::SetMusicVolume: item["type"] = "set_music_volume"; break;
|
||||
default: continue;
|
||||
}
|
||||
item["filename"] = String::utf8(cmd.filename.c_str());
|
||||
item["x"] = cmd.x;
|
||||
item["y"] = cmd.y;
|
||||
item["z"] = cmd.z;
|
||||
item["volume"] = cmd.volume;
|
||||
item["speed"] = cmd.speed;
|
||||
item["play_count"] = cmd.play_count;
|
||||
item["id"] = cmd.id;
|
||||
out.append(item);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
String Metin2PythonHost::current_map_name() {
|
||||
return String::utf8(PythonBoot::CurrentMapName().c_str());
|
||||
}
|
||||
@@ -285,6 +315,7 @@ void Metin2PythonHost::ui_update() {}
|
||||
Array Metin2PythonHost::ui_render_commands() { return Array(); }
|
||||
Ref<Image> Metin2PythonHost::memory_texture(const String &, int64_t) { return Ref<Image>(); }
|
||||
Array Metin2PythonHost::render3d_draws() { return Array(); }
|
||||
Array Metin2PythonHost::audio_commands() { return Array(); }
|
||||
String Metin2PythonHost::current_map_name() { return String(); }
|
||||
|
||||
void Metin2PythonHost::stop() {
|
||||
@@ -312,6 +343,7 @@ void Metin2PythonHost::_bind_methods() {
|
||||
ClassDB::bind_static_method("Metin2PythonHost", D_METHOD("memory_texture", "name", "known_revision"),
|
||||
&Metin2PythonHost::memory_texture, DEFVAL(-1));
|
||||
ClassDB::bind_static_method("Metin2PythonHost", D_METHOD("render3d_draws"), &Metin2PythonHost::render3d_draws);
|
||||
ClassDB::bind_static_method("Metin2PythonHost", D_METHOD("audio_commands"), &Metin2PythonHost::audio_commands);
|
||||
ClassDB::bind_static_method("Metin2PythonHost", D_METHOD("current_map_name"), &Metin2PythonHost::current_map_name);
|
||||
ClassDB::bind_static_method("Metin2PythonHost", D_METHOD("stop"), &Metin2PythonHost::stop);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
// "view", "proj" (PackedFloat32Array, D3D row-vector layout), vertex arrays, "indices", "texture0"
|
||||
// and the blend/depth/cull/lighting state.
|
||||
static godot::Array render3d_draws();
|
||||
static godot::Array audio_commands();
|
||||
static godot::String current_map_name();
|
||||
static void stop();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user