Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ca6cbf41c1 | |||
| 2a9667feca |
@@ -53,22 +53,6 @@ jobs:
|
|||||||
path: ./git-artifcats/Dusk
|
path: ./git-artifcats/Dusk
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
build-vita:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Set up Docker
|
|
||||||
uses: docker/setup-docker-action@v5
|
|
||||||
- name: Build Vita
|
|
||||||
run: ./scripts/build-vita-docker.sh
|
|
||||||
- name: Upload Vita binary
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
with:
|
|
||||||
name: dusk-vita
|
|
||||||
path: build-vita/Dusk.vpk
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
build-knulli:
|
build-knulli:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
module('entity')
|
||||||
|
module('entityposition')
|
||||||
|
module('entitymaterial')
|
||||||
|
module('glm')
|
||||||
|
module('color')
|
||||||
|
|
||||||
|
-- Position
|
||||||
|
local posComp = entityAddComponent(ENTITY_ID, COMPONENT_TYPE_POSITION)
|
||||||
|
entityPositionSetPosition(ENTITY_ID, posComp, vec3(1, 2, 3))
|
||||||
|
|
||||||
|
-- Material
|
||||||
|
local matComp = entityAddComponent(ENTITY_ID, COMPONENT_TYPE_MATERIAL)
|
||||||
|
local material = entityMaterialGetShaderMaterial(ENTITY_ID, matComp)
|
||||||
|
material.unlit.color = colorBlue()
|
||||||
+2
-2
@@ -9,8 +9,8 @@ if PSP then
|
|||||||
inputBind("down", INPUT_ACTION_DOWN)
|
inputBind("down", INPUT_ACTION_DOWN)
|
||||||
inputBind("left", INPUT_ACTION_LEFT)
|
inputBind("left", INPUT_ACTION_LEFT)
|
||||||
inputBind("right", INPUT_ACTION_RIGHT)
|
inputBind("right", INPUT_ACTION_RIGHT)
|
||||||
inputBind("accept", INPUT_ACTION_ACCEPT)
|
inputBind("circle", INPUT_ACTION_CANCEL)
|
||||||
inputBind("cancel", INPUT_ACTION_CANCEL)
|
inputBind("cross", INPUT_ACTION_ACCEPT)
|
||||||
inputBind("select", INPUT_ACTION_RAGEQUIT)
|
inputBind("select", INPUT_ACTION_RAGEQUIT)
|
||||||
inputBind("lstick_up", INPUT_ACTION_UP)
|
inputBind("lstick_up", INPUT_ACTION_UP)
|
||||||
inputBind("lstick_down", INPUT_ACTION_DOWN)
|
inputBind("lstick_down", INPUT_ACTION_DOWN)
|
||||||
|
|||||||
@@ -2,9 +2,4 @@ include(cmake/targets/dolphin.cmake)
|
|||||||
|
|
||||||
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
||||||
DUSK_GAMECUBE
|
DUSK_GAMECUBE
|
||||||
)
|
)
|
||||||
|
|
||||||
# Link libraries
|
|
||||||
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
|
|
||||||
# bba
|
|
||||||
)
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
# Find link platform-specific libraries
|
# Find link platform-specific libraries
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
# find_package(CURL REQUIRED)
|
|
||||||
|
|
||||||
# Setup endianess at compile time to optimize.
|
# Setup endianess at compile time to optimize.
|
||||||
include(TestBigEndian)
|
include(TestBigEndian)
|
||||||
@@ -17,13 +16,12 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Link required libraries.
|
# Link required libraries.
|
||||||
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
||||||
SDL2
|
SDL2
|
||||||
pthread
|
pthread
|
||||||
OpenGL::GL
|
OpenGL::GL
|
||||||
GL
|
GL
|
||||||
m
|
m
|
||||||
# CURL::libcurl
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Define platform-specific macros.
|
# Define platform-specific macros.
|
||||||
@@ -40,6 +38,4 @@ target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
|||||||
DUSK_INPUT_POINTER
|
DUSK_INPUT_POINTER
|
||||||
DUSK_INPUT_GAMEPAD
|
DUSK_INPUT_GAMEPAD
|
||||||
DUSK_TIME_DYNAMIC
|
DUSK_TIME_DYNAMIC
|
||||||
DUSK_NETWORK_IPV6
|
|
||||||
THREAD_PTHREAD=1
|
|
||||||
)
|
)
|
||||||
@@ -24,11 +24,6 @@ target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
|||||||
pspvfpu
|
pspvfpu
|
||||||
pspvram
|
pspvram
|
||||||
psphprm
|
psphprm
|
||||||
pspnet
|
|
||||||
pspnet_inet
|
|
||||||
pspnet_apctl
|
|
||||||
psphttp
|
|
||||||
pspssl
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
|
target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
|
||||||
@@ -44,7 +39,6 @@ target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
|||||||
DUSK_OPENGL_LEGACY
|
DUSK_OPENGL_LEGACY
|
||||||
DUSK_DISPLAY_WIDTH=480
|
DUSK_DISPLAY_WIDTH=480
|
||||||
DUSK_DISPLAY_HEIGHT=272
|
DUSK_DISPLAY_HEIGHT=272
|
||||||
THREAD_PTHREAD=1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Postbuild, create .pbp file for PSP.
|
# Postbuild, create .pbp file for PSP.
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
if(NOT DEFINED ENV{VITASDK})
|
|
||||||
message(FATAL_ERROR "VITASDK environment variable is not set.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include("$ENV{VITASDK}/share/vita.cmake" REQUIRED)
|
|
||||||
|
|
||||||
set(VITA_APP_NAME "Dusk")
|
|
||||||
set(VITA_TITLEID "DUSK00001")
|
|
||||||
set(VITA_VERSION "01.00")
|
|
||||||
|
|
||||||
find_package(SDL2 REQUIRED)
|
|
||||||
|
|
||||||
# Custom flags for cglm
|
|
||||||
set(CGLM_SHARED OFF CACHE BOOL "Build cglm shared" FORCE)
|
|
||||||
set(CGLM_STATIC ON CACHE BOOL "Build cglm static" FORCE)
|
|
||||||
find_package(cglm REQUIRED)
|
|
||||||
|
|
||||||
# Compile lua
|
|
||||||
include(FetchContent)
|
|
||||||
FetchContent_Declare(
|
|
||||||
liblua
|
|
||||||
URL https://www.lua.org/ftp/lua-5.5.0.tar.gz
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(liblua)
|
|
||||||
set(LUA_SRC_DIR "${liblua_SOURCE_DIR}/src")
|
|
||||||
set(LUA_C_FILES
|
|
||||||
lapi.c lauxlib.c lbaselib.c lcode.c lcorolib.c lctype.c ldblib.c ldebug.c
|
|
||||||
ldo.c ldump.c lfunc.c lgc.c linit.c liolib.c llex.c lmathlib.c lmem.c
|
|
||||||
loadlib.c lobject.c lopcodes.c loslib.c lparser.c lstate.c lstring.c
|
|
||||||
lstrlib.c ltable.c ltablib.c ltm.c lundump.c lutf8lib.c lvm.c lzio.c
|
|
||||||
)
|
|
||||||
list(TRANSFORM LUA_C_FILES PREPEND "${LUA_SRC_DIR}/")
|
|
||||||
add_library(liblua STATIC ${LUA_C_FILES})
|
|
||||||
target_include_directories(liblua PUBLIC "${LUA_SRC_DIR}")
|
|
||||||
target_compile_definitions(liblua PRIVATE LUA_USE_C89)
|
|
||||||
add_library(lua::lua ALIAS liblua)
|
|
||||||
set(Lua_FOUND TRUE CACHE BOOL "Lua found" FORCE)
|
|
||||||
|
|
||||||
# Link libraries
|
|
||||||
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
|
||||||
${SDL2_LIBRARIES}
|
|
||||||
liblua
|
|
||||||
cglm
|
|
||||||
SDL2
|
|
||||||
SDL2main
|
|
||||||
zip
|
|
||||||
bz2
|
|
||||||
z
|
|
||||||
zstd
|
|
||||||
crypto
|
|
||||||
lzma
|
|
||||||
m
|
|
||||||
pthread
|
|
||||||
stdc++
|
|
||||||
vitaGL
|
|
||||||
mathneon
|
|
||||||
vitashark
|
|
||||||
kubridge_stub
|
|
||||||
SceAppMgr_stub
|
|
||||||
SceAudio_stub
|
|
||||||
SceCtrl_stub
|
|
||||||
SceCommonDialog_stub
|
|
||||||
SceDisplay_stub
|
|
||||||
SceKernelDmacMgr_stub
|
|
||||||
SceGxm_stub
|
|
||||||
SceShaccCg_stub
|
|
||||||
SceSysmodule_stub
|
|
||||||
ScePower_stub
|
|
||||||
SceTouch_stub
|
|
||||||
SceVshBridge_stub
|
|
||||||
SceIofilemgr_stub
|
|
||||||
SceShaccCgExt
|
|
||||||
libtaihen_stub.a
|
|
||||||
|
|
||||||
|
|
||||||
# SceKernel_stub
|
|
||||||
SceAppUtil_stub
|
|
||||||
SceHid_stub
|
|
||||||
SceRtc_stub
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
|
|
||||||
${SDL2_INCLUDE_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
|
||||||
DUSK_SDL2
|
|
||||||
DUSK_OPENGL
|
|
||||||
DUSK_VITA
|
|
||||||
DUSK_INPUT_GAMEPAD
|
|
||||||
DUSK_PLATFORM_ENDIAN_LITTLE
|
|
||||||
DUSK_OPENGL_LEGACY
|
|
||||||
DUSK_DISPLAY_WIDTH=960
|
|
||||||
DUSK_DISPLAY_HEIGHT=544
|
|
||||||
)
|
|
||||||
|
|
||||||
# Post-build: create SELF from the ELF binary (UNSAFE = homebrew, no signing)
|
|
||||||
vita_create_self(${DUSK_BINARY_TARGET_NAME}.self ${DUSK_BINARY_TARGET_NAME} UNSAFE)
|
|
||||||
|
|
||||||
# Post-build: package SELF + assets into a .vpk installable on the Vita
|
|
||||||
vita_create_vpk(${DUSK_BINARY_TARGET_NAME}.vpk ${VITA_TITLEID} ${DUSK_BINARY_TARGET_NAME}.self
|
|
||||||
VERSION ${VITA_VERSION}
|
|
||||||
NAME ${VITA_APP_NAME}
|
|
||||||
FILE ${DUSK_ASSETS_ZIP} dusk.dsk
|
|
||||||
)
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
FROM vitasdk/vitasdk:latest
|
|
||||||
WORKDIR /workdir
|
|
||||||
|
|
||||||
# Install vitaGL and its dependencies (vitashark, SceShaccCg) via vdpm
|
|
||||||
RUN which vdpm
|
|
||||||
|
|
||||||
# Install Python (needed for Dusk code generation tools)
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
python3 \
|
|
||||||
py3-pip \
|
|
||||||
py3-dotenv
|
|
||||||
|
|
||||||
VOLUME ["/workdir"]
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
docker build -t dusk-vita -f docker/vita/Dockerfile .
|
|
||||||
docker run --rm -v $(pwd):/workdir dusk-vita /bin/bash -c "./scripts/build-vita.sh"
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
if [ -z "$VITASDK" ]; then
|
|
||||||
echo "VITASDK environment variable is not set. Please set it to the path of your VitaSDK installation."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p build-vita
|
|
||||||
cd build-vita
|
|
||||||
cmake \
|
|
||||||
-DCMAKE_TOOLCHAIN_FILE=$VITASDK/share/vita.toolchain.cmake \
|
|
||||||
-DDUSK_TARGET_SYSTEM=vita \
|
|
||||||
..
|
|
||||||
make -j$(nproc)
|
|
||||||
+1
-6
@@ -16,12 +16,7 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
|||||||
add_subdirectory(dusksdl2)
|
add_subdirectory(dusksdl2)
|
||||||
add_subdirectory(duskgl)
|
add_subdirectory(duskgl)
|
||||||
|
|
||||||
elseif(DUSK_TARGET_SYSTEM STREQUAL "vita")
|
elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
|
||||||
add_subdirectory(duskvita)
|
|
||||||
add_subdirectory(dusksdl2)
|
|
||||||
add_subdirectory(duskgl)
|
|
||||||
|
|
||||||
elseif(DUSK_TARGET_SYSTEM STREQUAL "wii" OR DUSK_TARGET_SYSTEM STREQUAL "gamecube")
|
|
||||||
add_subdirectory(duskdolphin)
|
add_subdirectory(duskdolphin)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
@@ -72,9 +72,10 @@ add_subdirectory(locale)
|
|||||||
add_subdirectory(physics)
|
add_subdirectory(physics)
|
||||||
add_subdirectory(scene)
|
add_subdirectory(scene)
|
||||||
add_subdirectory(script)
|
add_subdirectory(script)
|
||||||
add_subdirectory(system)
|
|
||||||
add_subdirectory(time)
|
add_subdirectory(time)
|
||||||
add_subdirectory(ui)
|
add_subdirectory(ui)
|
||||||
add_subdirectory(network)
|
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
# add_subdirectory(thread)
|
|
||||||
|
# if(DUSK_TARGET_SYSTEM STREQUAL "linux" OR DUSK_TARGET_SYSTEM STREQUAL "psp")
|
||||||
|
# add_subdirectory(thread)
|
||||||
|
# endif()
|
||||||
@@ -64,7 +64,7 @@ errorret_t displayInit(void) {
|
|||||||
|
|
||||||
glm_perspective(
|
glm_perspective(
|
||||||
glm_rad(45.0f),
|
glm_rad(45.0f),
|
||||||
SCREEN.aspect,
|
(float_t)SCREEN.width / (float_t)SCREEN.height,
|
||||||
0.1f,
|
0.1f,
|
||||||
100.0f,
|
100.0f,
|
||||||
proj
|
proj
|
||||||
@@ -101,6 +101,9 @@ errorret_t displayUpdate(void) {
|
|||||||
|
|
||||||
errorChain(sceneRender());
|
errorChain(sceneRender());
|
||||||
|
|
||||||
|
// Render UI
|
||||||
|
// uiRender();
|
||||||
|
|
||||||
// Finish up
|
// Finish up
|
||||||
screenUnbind();
|
screenUnbind();
|
||||||
screenRender();
|
screenRender();
|
||||||
|
|||||||
@@ -40,17 +40,6 @@ uint32_t frameBufferGetHeight(const framebuffer_t *framebuffer) {
|
|||||||
return frameBufferPlatformGetHeight(framebuffer);
|
return frameBufferPlatformGetHeight(framebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
float_t frameBufferGetAspect(const framebuffer_t *framebuffer) {
|
|
||||||
#ifdef frameBufferPlatformGetAspect
|
|
||||||
return frameBufferPlatformGetAspect(framebuffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t width = frameBufferGetWidth(framebuffer);
|
|
||||||
uint32_t height = frameBufferGetHeight(framebuffer);
|
|
||||||
if(height == 0) return 1.0f; // Avoid divide by zero, just return 1:1 aspect.
|
|
||||||
return (float_t)width / (float_t)height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void frameBufferClear(const uint8_t flags, const color_t color) {
|
void frameBufferClear(const uint8_t flags, const color_t color) {
|
||||||
frameBufferPlatformClear(flags, color);
|
frameBufferPlatformClear(flags, color);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,16 +58,6 @@ uint32_t frameBufferGetWidth(const framebuffer_t *framebuffer);
|
|||||||
*/
|
*/
|
||||||
uint32_t frameBufferGetHeight(const framebuffer_t *framebuffer);
|
uint32_t frameBufferGetHeight(const framebuffer_t *framebuffer);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the aspect ratio of the framebuffer. This is ALMOST always just
|
|
||||||
* the width / height, however some platforms may choose to override this if
|
|
||||||
* they have stretched styled back buffers, e.g. 640x480 stretched.
|
|
||||||
*
|
|
||||||
* @param framebuffer The framebuffer to get the aspect ratio of.
|
|
||||||
* @return The aspect ratio of the framebuffer.
|
|
||||||
*/
|
|
||||||
float_t frameBufferGetAspect(const framebuffer_t *framebuffer);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds the framebuffer for rendering, or the backbuffer if the framebuffer
|
* Binds the framebuffer for rendering, or the backbuffer if the framebuffer
|
||||||
* provided is NULL.
|
* provided is NULL.
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ errorret_t screenBind() {
|
|||||||
// Screen mode backbuffer uses the full display size
|
// Screen mode backbuffer uses the full display size
|
||||||
SCREEN.width = frameBufferGetWidth(FRAMEBUFFER_BOUND);
|
SCREEN.width = frameBufferGetWidth(FRAMEBUFFER_BOUND);
|
||||||
SCREEN.height = frameBufferGetHeight(FRAMEBUFFER_BOUND);
|
SCREEN.height = frameBufferGetHeight(FRAMEBUFFER_BOUND);
|
||||||
SCREEN.aspect = frameBufferGetAspect(FRAMEBUFFER_BOUND);
|
SCREEN.aspect = (float_t)SCREEN.width / (float_t)SCREEN.height;
|
||||||
|
|
||||||
// No needd for a framebuffer.
|
// No needd for a framebuffer.
|
||||||
#ifdef DUSK_DISPLAY_SIZE_DYNAMIC
|
#ifdef DUSK_DISPLAY_SIZE_DYNAMIC
|
||||||
@@ -100,7 +100,8 @@ errorret_t screenBind() {
|
|||||||
int32_t fbWidth, fbHeight;
|
int32_t fbWidth, fbHeight;
|
||||||
fbWidth = frameBufferGetWidth(FRAMEBUFFER_BOUND);
|
fbWidth = frameBufferGetWidth(FRAMEBUFFER_BOUND);
|
||||||
fbHeight = frameBufferGetHeight(FRAMEBUFFER_BOUND);
|
fbHeight = frameBufferGetHeight(FRAMEBUFFER_BOUND);
|
||||||
float_t currentAspect = frameBufferGetAspect(FRAMEBUFFER_BOUND);
|
|
||||||
|
float_t currentAspect = (float_t)fbWidth / (float_t)fbHeight;
|
||||||
if(currentAspect == SCREEN.aspectRatio.ratio) {
|
if(currentAspect == SCREEN.aspectRatio.ratio) {
|
||||||
// No need to use framebuffer.
|
// No need to use framebuffer.
|
||||||
SCREEN.width = fbWidth;
|
SCREEN.width = fbWidth;
|
||||||
@@ -128,14 +129,13 @@ errorret_t screenBind() {
|
|||||||
if(SCREEN.framebufferReady) {
|
if(SCREEN.framebufferReady) {
|
||||||
// Is current framebuffer the correct size?
|
// Is current framebuffer the correct size?
|
||||||
int32_t curFbWidth, curFbHeight;
|
int32_t curFbWidth, curFbHeight;
|
||||||
float_t curFbAspect = frameBufferGetAspect(&SCREEN.framebuffer);
|
|
||||||
curFbWidth = frameBufferGetWidth(&SCREEN.framebuffer);
|
curFbWidth = frameBufferGetWidth(&SCREEN.framebuffer);
|
||||||
curFbHeight = frameBufferGetHeight(&SCREEN.framebuffer);
|
curFbHeight = frameBufferGetHeight(&SCREEN.framebuffer);
|
||||||
if(curFbWidth == newFbWidth && curFbHeight == newFbHeight) {
|
if(curFbWidth == newFbWidth && curFbHeight == newFbHeight) {
|
||||||
// Correct size, nothing to do.
|
// Correct size, nothing to do.
|
||||||
SCREEN.width = newFbWidth;
|
SCREEN.width = newFbWidth;
|
||||||
SCREEN.height = newFbHeight;
|
SCREEN.height = newFbHeight;
|
||||||
SCREEN.aspect = curFbAspect;
|
SCREEN.aspect = (float_t)SCREEN.width / (float_t)SCREEN.height;
|
||||||
errorChain(frameBufferBind(&SCREEN.framebuffer));
|
errorChain(frameBufferBind(&SCREEN.framebuffer));
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,9 @@ errorret_t textDraw(
|
|||||||
const float_t x,
|
const float_t x,
|
||||||
const float_t y,
|
const float_t y,
|
||||||
const char_t *text,
|
const char_t *text,
|
||||||
const color_t color,
|
#if MESH_ENABLE_COLOR
|
||||||
|
const color_t color,
|
||||||
|
#endif
|
||||||
const tileset_t *tileset,
|
const tileset_t *tileset,
|
||||||
texture_t *texture
|
texture_t *texture
|
||||||
) {
|
) {
|
||||||
@@ -81,11 +83,6 @@ errorret_t textDraw(
|
|||||||
|
|
||||||
errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, texture));
|
errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, texture));
|
||||||
|
|
||||||
#if MESH_ENABLE_COLOR
|
|
||||||
#else
|
|
||||||
errorChain(shaderSetColor(&SHADER_UNLIT, SHADER_UNLIT_COLOR, color));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// errorChain(spriteBatchPush(
|
// errorChain(spriteBatchPush(
|
||||||
// // texture,
|
// // texture,
|
||||||
// posX, posY,
|
// posX, posY,
|
||||||
|
|||||||
@@ -66,7 +66,9 @@ errorret_t textDraw(
|
|||||||
const float_t x,
|
const float_t x,
|
||||||
const float_t y,
|
const float_t y,
|
||||||
const char_t *text,
|
const char_t *text,
|
||||||
const color_t color,
|
#if MESH_ENABLE_COLOR
|
||||||
|
const color_t color,
|
||||||
|
#endif
|
||||||
const tileset_t *tileset,
|
const tileset_t *tileset,
|
||||||
texture_t *texture
|
texture_t *texture
|
||||||
);
|
);
|
||||||
|
|||||||
+18
-107
@@ -20,77 +20,14 @@
|
|||||||
#include "entity/component/physics/entityphysics.h"
|
#include "entity/component/physics/entityphysics.h"
|
||||||
#include "game/game.h"
|
#include "game/game.h"
|
||||||
#include "physics/physicsmanager.h"
|
#include "physics/physicsmanager.h"
|
||||||
#include "network/network.h"
|
|
||||||
#include "network/networkinfo.h"
|
|
||||||
#include "system/system.h"
|
|
||||||
|
|
||||||
#include "display/mesh/cube.h"
|
#include "display/mesh/cube.h"
|
||||||
#include "display/mesh/plane.h"
|
#include "display/mesh/plane.h"
|
||||||
|
|
||||||
engine_t ENGINE;
|
engine_t ENGINE;
|
||||||
entityid_t phBoxEnt;
|
|
||||||
componentid_t phBoxPhys;
|
|
||||||
|
|
||||||
float_t onlineSwapTime = FLT_MAX;
|
|
||||||
|
|
||||||
void goOnline();
|
|
||||||
void goOffline();
|
|
||||||
|
|
||||||
void onNetworkConnected(void *user) {
|
|
||||||
onlineSwapTime = TIME.time + 3.0f;
|
|
||||||
|
|
||||||
networkinfo_t info = networkGetInfo();
|
|
||||||
if(info.type == NETWORK_TYPE_IPV4) {
|
|
||||||
sceneLog(
|
|
||||||
"Connected to network with IPv4 address: " NETWORK_INFO_FORMAT_IPV4 "\n",
|
|
||||||
info.ipv4.ip[0], info.ipv4.ip[1], info.ipv4.ip[2], info.ipv4.ip[3]
|
|
||||||
);
|
|
||||||
#ifdef DUSK_NETWORK_IPV6
|
|
||||||
} else if(info.type == NETWORK_TYPE_IPV6) {
|
|
||||||
sceneLog(
|
|
||||||
"Connected to network with IPv6 address: " NETWORK_INFO_FORMAT_IPV6 "\n",
|
|
||||||
info.ipv6.ip[0], info.ipv6.ip[1], info.ipv6.ip[2], info.ipv6.ip[3],
|
|
||||||
info.ipv6.ip[4], info.ipv6.ip[5], info.ipv6.ip[6], info.ipv6.ip[7],
|
|
||||||
info.ipv6.ip[8], info.ipv6.ip[9], info.ipv6.ip[10], info.ipv6.ip[11],
|
|
||||||
info.ipv6.ip[12], info.ipv6.ip[13], info.ipv6.ip[14], info.ipv6.ip[15]
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
sceneLog("Network connected, I will disconnect at: %.2f1.\n", onlineSwapTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onNetworkFailed(errorret_t error, void *user) {
|
|
||||||
onlineSwapTime = TIME.time + 3.0f;
|
|
||||||
sceneLog("Failed to connect to network, will try again at %.2f1.\n", onlineSwapTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onNetworkDisconnected(errorret_t error, void *user) {
|
|
||||||
onlineSwapTime = TIME.time + 3.0f;
|
|
||||||
sceneLog("Network disconnected, will go online at %.2f1.\n", onlineSwapTime);
|
|
||||||
errorCatch(errorPrint(error));
|
|
||||||
}
|
|
||||||
|
|
||||||
void onNetworkDisconnectFinished(void *user) {
|
|
||||||
onlineSwapTime = TIME.time + 3.0f;
|
|
||||||
sceneLog("Finished disconnecting from network, will go online at %.2f1.\n", onlineSwapTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void goOnline() {
|
|
||||||
sceneLog("Going online...\n");
|
|
||||||
networkRequestConnection(
|
|
||||||
onNetworkConnected,
|
|
||||||
onNetworkFailed,
|
|
||||||
onNetworkDisconnected,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void goOffline() {
|
|
||||||
sceneLog("Going offline...\n");
|
|
||||||
networkRequestDisconnection(onNetworkDisconnectFinished, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Kept module-level only because engineUpdate needs them for the reset. */
|
||||||
|
static entityid_t phBoxEnt;
|
||||||
|
static componentid_t phBoxPhys;
|
||||||
|
|
||||||
errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
||||||
memoryZero(&ENGINE, sizeof(engine_t));
|
memoryZero(&ENGINE, sizeof(engine_t));
|
||||||
@@ -99,7 +36,6 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
ENGINE.argv = argv;
|
ENGINE.argv = argv;
|
||||||
|
|
||||||
// Init systems. Order is important.
|
// Init systems. Order is important.
|
||||||
errorChain(systemInit());
|
|
||||||
timeInit();
|
timeInit();
|
||||||
errorChain(inputInit());
|
errorChain(inputInit());
|
||||||
errorChain(assetInit());
|
errorChain(assetInit());
|
||||||
@@ -110,13 +46,9 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
errorChain(sceneInit());
|
errorChain(sceneInit());
|
||||||
entityManagerInit();
|
entityManagerInit();
|
||||||
physicsManagerInit();
|
physicsManagerInit();
|
||||||
// errorChain(networkInit());
|
|
||||||
errorChain(gameInit());
|
errorChain(gameInit());
|
||||||
|
|
||||||
sceneLog("Init done, going to queue online in 3 seconds...\n");
|
/* ---- Camera ---- */
|
||||||
onlineSwapTime = TIME.time + 3.0f;
|
|
||||||
|
|
||||||
// Camera
|
|
||||||
entityid_t cam = entityManagerAdd();
|
entityid_t cam = entityManagerAdd();
|
||||||
componentid_t camPos = entityAddComponent(cam, COMPONENT_TYPE_POSITION);
|
componentid_t camPos = entityAddComponent(cam, COMPONENT_TYPE_POSITION);
|
||||||
float_t distance = 6.0f;
|
float_t distance = 6.0f;
|
||||||
@@ -127,13 +59,13 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
(vec3){ distance, distance, distance }
|
(vec3){ distance, distance, distance }
|
||||||
);
|
);
|
||||||
componentid_t camCam = entityAddComponent(cam, COMPONENT_TYPE_CAMERA);
|
componentid_t camCam = entityAddComponent(cam, COMPONENT_TYPE_CAMERA);
|
||||||
entityCameraSetZFar(cam, camCam, 100.0f);
|
entityCameraSetZFar(cam, camCam, distance * 6.0f);
|
||||||
|
|
||||||
// Floor
|
/* ---- Static floor (visual + physics) ---- */
|
||||||
entityid_t floorEnt = entityManagerAdd();
|
entityid_t floorEnt = entityManagerAdd();
|
||||||
componentid_t floorPos = entityAddComponent(floorEnt, COMPONENT_TYPE_POSITION);
|
componentid_t floorPos = entityAddComponent(floorEnt, COMPONENT_TYPE_POSITION);
|
||||||
componentid_t floorMesh = entityAddComponent(floorEnt, COMPONENT_TYPE_MESH);
|
componentid_t floorMesh = entityAddComponent(floorEnt, COMPONENT_TYPE_MESH);
|
||||||
componentid_t floorMat = entityAddComponent(floorEnt, COMPONENT_TYPE_MATERIAL);
|
componentid_t floorMat = entityAddComponent(floorEnt, COMPONENT_TYPE_MATERIAL);
|
||||||
componentid_t floorPhys = entityAddComponent(floorEnt, COMPONENT_TYPE_PHYSICS);
|
componentid_t floorPhys = entityAddComponent(floorEnt, COMPONENT_TYPE_PHYSICS);
|
||||||
|
|
||||||
entityPositionSetPosition(floorEnt, floorPos, (vec3){ -5.0f, 0.0f, -5.0f });
|
entityPositionSetPosition(floorEnt, floorPos, (vec3){ -5.0f, 0.0f, -5.0f });
|
||||||
@@ -142,24 +74,22 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
entityMaterialGetShaderMaterial(floorEnt, floorMat)->unlit.color = COLOR_GREEN;
|
entityMaterialGetShaderMaterial(floorEnt, floorMat)->unlit.color = COLOR_GREEN;
|
||||||
|
|
||||||
entityphysics_t *floorPhysData = entityPhysicsGet(floorEnt, floorPhys);
|
entityphysics_t *floorPhysData = entityPhysicsGet(floorEnt, floorPhys);
|
||||||
floorPhysData->type = PHYSICS_BODY_STATIC;
|
floorPhysData->type = PHYSICS_BODY_STATIC;
|
||||||
floorPhysData->shape.type = PHYSICS_SHAPE_PLANE;
|
floorPhysData->shape.type = PHYSICS_SHAPE_PLANE;
|
||||||
floorPhysData->shape.data.plane.normal[0] = 0.0f;
|
floorPhysData->shape.data.plane.normal[0] = 0.0f;
|
||||||
floorPhysData->shape.data.plane.normal[1] = 1.0f;
|
floorPhysData->shape.data.plane.normal[1] = 1.0f;
|
||||||
floorPhysData->shape.data.plane.normal[2] = 0.0f;
|
floorPhysData->shape.data.plane.normal[2] = 0.0f;
|
||||||
floorPhysData->shape.data.plane.distance = 0.0f;
|
floorPhysData->shape.data.plane.distance = 0.0f;
|
||||||
|
|
||||||
// Box
|
// Test Box
|
||||||
phBoxEnt = entityManagerAdd();
|
phBoxEnt = entityManagerAdd();
|
||||||
componentid_t boxPos = entityAddComponent(phBoxEnt, COMPONENT_TYPE_POSITION);
|
|
||||||
componentid_t boxMesh = entityAddComponent(phBoxEnt, COMPONENT_TYPE_MESH);
|
componentid_t boxMesh = entityAddComponent(phBoxEnt, COMPONENT_TYPE_MESH);
|
||||||
componentid_t boxMat = entityAddComponent(phBoxEnt, COMPONENT_TYPE_MATERIAL);
|
// componentid_t boxMat = entityAddComponent(phBoxEnt, COMPONENT_TYPE_MATERIAL);
|
||||||
phBoxPhys = entityAddComponent(phBoxEnt, COMPONENT_TYPE_PHYSICS);
|
|
||||||
|
|
||||||
entityMeshSetMesh(phBoxEnt, boxMesh, &CUBE_MESH_SIMPLE);
|
entityMeshSetMesh(phBoxEnt, boxMesh, &CUBE_MESH_SIMPLE);
|
||||||
entityMaterialGetShaderMaterial(phBoxEnt, boxMat)->unlit.color = COLOR_RED;
|
// entityMaterialGetShaderMaterial(phBoxEnt, boxMat)->unlit.color = COLOR_RED;
|
||||||
entityPositionSetPosition(phBoxEnt, boxPos, (vec3){ 0.0f, 4.0f, 0.0f });
|
componentid_t boxScript = entityAddComponent(phBoxEnt, COMPONENT_TYPE_SCRIPT);
|
||||||
|
errorChain(entityScriptExecAsset(phBoxEnt, boxScript, "entity/test.lua"));
|
||||||
|
|
||||||
/* Run the init script. */
|
/* Run the init script. */
|
||||||
scriptcontext_t ctx;
|
scriptcontext_t ctx;
|
||||||
errorChain(scriptContextInit(&ctx));
|
errorChain(scriptContextInit(&ctx));
|
||||||
@@ -170,21 +100,12 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errorret_t engineUpdate(void) {
|
errorret_t engineUpdate(void) {
|
||||||
// errorChain(networkUpdate());
|
|
||||||
|
|
||||||
timeUpdate();
|
timeUpdate();
|
||||||
inputUpdate();
|
inputUpdate();
|
||||||
|
|
||||||
uiUpdate();
|
uiUpdate();
|
||||||
errorChain(sceneUpdate());
|
errorChain(sceneUpdate());
|
||||||
|
|
||||||
/* Reset the box to its start position on demand. */
|
|
||||||
if(inputIsDown(INPUT_ACTION_ACCEPT)) {
|
|
||||||
componentid_t posComp = entityGetComponent(phBoxEnt, COMPONENT_TYPE_POSITION);
|
|
||||||
entityPositionSetPosition(phBoxEnt, posComp, (vec3){ 0.0f, 4.0f, 0.0f });
|
|
||||||
entityPhysicsSetVelocity(phBoxEnt, phBoxPhys, (vec3){ 0.0f, 0.0f, 0.0f });
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Step physics: positions are updated directly on POSITION components. */
|
/* Step physics: positions are updated directly on POSITION components. */
|
||||||
physicsManagerUpdate();
|
physicsManagerUpdate();
|
||||||
|
|
||||||
@@ -193,15 +114,6 @@ errorret_t engineUpdate(void) {
|
|||||||
|
|
||||||
if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false;
|
if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false;
|
||||||
|
|
||||||
if(TIME.time >= onlineSwapTime) {
|
|
||||||
onlineSwapTime = FLT_MAX;
|
|
||||||
if(NETWORK.state == NETWORK_STATE_CONNECTED) {
|
|
||||||
goOffline();
|
|
||||||
} else {
|
|
||||||
goOnline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +122,6 @@ void engineExit(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errorret_t engineDispose(void) {
|
errorret_t engineDispose(void) {
|
||||||
// errorChain(networkDispose());
|
|
||||||
sceneDispose();
|
sceneDispose();
|
||||||
errorChain(gameDispose());
|
errorChain(gameDispose());
|
||||||
entityManagerDispose();
|
entityManagerDispose();
|
||||||
|
|||||||
@@ -4,4 +4,5 @@
|
|||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
add_subdirectory(display)
|
add_subdirectory(display)
|
||||||
add_subdirectory(physics)
|
add_subdirectory(physics)
|
||||||
|
add_subdirectory(script)
|
||||||
@@ -55,6 +55,65 @@ void entityCameraSetZFar(
|
|||||||
cam->farClip = zFar;
|
cam->farClip = zFar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entitycameraprojectiontype_t entityCameraGetProjType(
|
||||||
|
const entityid_t ent,
|
||||||
|
const componentid_t comp
|
||||||
|
) {
|
||||||
|
entitycamera_t *cam = (entitycamera_t *)componentGetData(
|
||||||
|
ent, comp, COMPONENT_TYPE_CAMERA
|
||||||
|
);
|
||||||
|
return cam->projType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityCameraSetProjType(
|
||||||
|
const entityid_t ent,
|
||||||
|
const componentid_t comp,
|
||||||
|
const entitycameraprojectiontype_t type
|
||||||
|
) {
|
||||||
|
entitycamera_t *cam = (entitycamera_t *)componentGetData(
|
||||||
|
ent, comp, COMPONENT_TYPE_CAMERA
|
||||||
|
);
|
||||||
|
cam->projType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
float_t entityCameraGetFov(
|
||||||
|
const entityid_t ent,
|
||||||
|
const componentid_t comp
|
||||||
|
) {
|
||||||
|
entitycamera_t *cam = (entitycamera_t *)componentGetData(
|
||||||
|
ent, comp, COMPONENT_TYPE_CAMERA
|
||||||
|
);
|
||||||
|
return cam->perspective.fov;
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityCameraSetFov(
|
||||||
|
const entityid_t ent,
|
||||||
|
const componentid_t comp,
|
||||||
|
const float_t fov
|
||||||
|
) {
|
||||||
|
entitycamera_t *cam = (entitycamera_t *)componentGetData(
|
||||||
|
ent, comp, COMPONENT_TYPE_CAMERA
|
||||||
|
);
|
||||||
|
cam->perspective.fov = fov;
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityCameraSetOrthographic(
|
||||||
|
const entityid_t ent,
|
||||||
|
const componentid_t comp,
|
||||||
|
const float_t left,
|
||||||
|
const float_t right,
|
||||||
|
const float_t top,
|
||||||
|
const float_t bottom
|
||||||
|
) {
|
||||||
|
entitycamera_t *cam = (entitycamera_t *)componentGetData(
|
||||||
|
ent, comp, COMPONENT_TYPE_CAMERA
|
||||||
|
);
|
||||||
|
cam->orthographic.left = left;
|
||||||
|
cam->orthographic.right = right;
|
||||||
|
cam->orthographic.top = top;
|
||||||
|
cam->orthographic.bottom = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
void entityCameraGetProjection(
|
void entityCameraGetProjection(
|
||||||
const entityid_t ent,
|
const entityid_t ent,
|
||||||
const componentid_t comp,
|
const componentid_t comp,
|
||||||
|
|||||||
@@ -96,4 +96,73 @@ void entityCameraSetZFar(
|
|||||||
const entityid_t ent,
|
const entityid_t ent,
|
||||||
const componentid_t comp,
|
const componentid_t comp,
|
||||||
const float_t zFar
|
const float_t zFar
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the projection type of a camera.
|
||||||
|
*
|
||||||
|
* @param ent The entity ID.
|
||||||
|
* @param comp The component ID.
|
||||||
|
* @return The projection type.
|
||||||
|
*/
|
||||||
|
entitycameraprojectiontype_t entityCameraGetProjType(
|
||||||
|
const entityid_t ent,
|
||||||
|
const componentid_t comp
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the projection type of a camera.
|
||||||
|
*
|
||||||
|
* @param ent The entity ID.
|
||||||
|
* @param comp The component ID.
|
||||||
|
* @param type The projection type.
|
||||||
|
*/
|
||||||
|
void entityCameraSetProjType(
|
||||||
|
const entityid_t ent,
|
||||||
|
const componentid_t comp,
|
||||||
|
const entitycameraprojectiontype_t type
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the field of view (in radians) of a perspective camera.
|
||||||
|
*
|
||||||
|
* @param ent The entity ID.
|
||||||
|
* @param comp The component ID.
|
||||||
|
* @return The field of view in radians.
|
||||||
|
*/
|
||||||
|
float_t entityCameraGetFov(
|
||||||
|
const entityid_t ent,
|
||||||
|
const componentid_t comp
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the field of view (in radians) of a perspective camera.
|
||||||
|
*
|
||||||
|
* @param ent The entity ID.
|
||||||
|
* @param comp The component ID.
|
||||||
|
* @param fov The field of view in radians.
|
||||||
|
*/
|
||||||
|
void entityCameraSetFov(
|
||||||
|
const entityid_t ent,
|
||||||
|
const componentid_t comp,
|
||||||
|
const float_t fov
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the orthographic projection bounds of a camera.
|
||||||
|
*
|
||||||
|
* @param ent The entity ID.
|
||||||
|
* @param comp The component ID.
|
||||||
|
* @param left Left bound.
|
||||||
|
* @param right Right bound.
|
||||||
|
* @param top Top bound.
|
||||||
|
* @param bottom Bottom bound.
|
||||||
|
*/
|
||||||
|
void entityCameraSetOrthographic(
|
||||||
|
const entityid_t ent,
|
||||||
|
const componentid_t comp,
|
||||||
|
const float_t left,
|
||||||
|
const float_t right,
|
||||||
|
const float_t top,
|
||||||
|
const float_t bottom
|
||||||
);
|
);
|
||||||
@@ -100,6 +100,44 @@ bool_t entityPhysicsIsOnGround(
|
|||||||
return phys->onGround;
|
return phys->onGround;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
physicsbodytype_t entityPhysicsGetBodyType(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId
|
||||||
|
) {
|
||||||
|
entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
|
||||||
|
assertNotNull(phys, "Failed to get physics component data");
|
||||||
|
return phys->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityPhysicsSetBodyType(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
const physicsbodytype_t type
|
||||||
|
) {
|
||||||
|
entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
|
||||||
|
assertNotNull(phys, "Failed to get physics component data");
|
||||||
|
phys->type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
float_t entityPhysicsGetGravityScale(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId
|
||||||
|
) {
|
||||||
|
entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
|
||||||
|
assertNotNull(phys, "Failed to get physics component data");
|
||||||
|
return phys->gravityScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityPhysicsSetGravityScale(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
const float_t scale
|
||||||
|
) {
|
||||||
|
entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
|
||||||
|
assertNotNull(phys, "Failed to get physics component data");
|
||||||
|
phys->gravityScale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
void entityPhysicsDispose(
|
void entityPhysicsDispose(
|
||||||
const entityid_t entityId,
|
const entityid_t entityId,
|
||||||
const componentid_t componentId
|
const componentid_t componentId
|
||||||
|
|||||||
@@ -122,6 +122,56 @@ bool_t entityPhysicsIsOnGround(
|
|||||||
const componentid_t componentId
|
const componentid_t componentId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the body type of the entity's physics body.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @return The body type (static, dynamic, kinematic).
|
||||||
|
*/
|
||||||
|
physicsbodytype_t entityPhysicsGetBodyType(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the body type of the entity's physics body.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @param type The new body type.
|
||||||
|
*/
|
||||||
|
void entityPhysicsSetBodyType(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
const physicsbodytype_t type
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the gravity scale of the entity's physics body.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @return The gravity scale factor.
|
||||||
|
*/
|
||||||
|
float_t entityPhysicsGetGravityScale(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the gravity scale of the entity's physics body.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @param scale The new gravity scale factor.
|
||||||
|
*/
|
||||||
|
void entityPhysicsSetGravityScale(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
const float_t scale
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases the body slot back to PHYSICS_WORLD. Called automatically when
|
* Releases the body slot back to PHYSICS_WORLD. Called automatically when
|
||||||
* the component is disposed via the component system.
|
* the component is disposed via the component system.
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
# Copyright (c) 2026 Dominic Masters
|
||||||
#
|
#
|
||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
# Sources
|
# Sources
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
assetvita.c
|
entityscript.c
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "entityscript.h"
|
||||||
|
#include "entity/component.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
void entityScriptInit(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId
|
||||||
|
) {
|
||||||
|
entityscript_t *script = (entityscript_t*)componentGetData(
|
||||||
|
entityId, componentId, COMPONENT_TYPE_SCRIPT
|
||||||
|
);
|
||||||
|
scriptContextInit(&script->scriptContext);
|
||||||
|
|
||||||
|
// Define script globals.
|
||||||
|
char_t strScript[64];
|
||||||
|
snprintf(strScript, sizeof(strScript), "ENTITY_ID = %d\n", entityId);
|
||||||
|
errorret_t ret = scriptContextExec(&script->scriptContext, strScript);
|
||||||
|
if(ret.code != ERROR_OK) {
|
||||||
|
errorCatch(errorPrint(ret));
|
||||||
|
assertUnreachable("Failed to set up script globals");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t entityScriptExec(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
const char_t *script
|
||||||
|
) {
|
||||||
|
entityscript_t *entityScript = (entityscript_t*)componentGetData(
|
||||||
|
entityId, componentId, COMPONENT_TYPE_SCRIPT
|
||||||
|
);
|
||||||
|
return scriptContextExec(&entityScript->scriptContext, script);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t entityScriptExecAsset(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
const char_t *assetName
|
||||||
|
) {
|
||||||
|
entityscript_t *entityScript = (entityscript_t*)componentGetData(
|
||||||
|
entityId, componentId, COMPONENT_TYPE_SCRIPT
|
||||||
|
);
|
||||||
|
return scriptContextExecFile(&entityScript->scriptContext, assetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityScriptDispose(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId
|
||||||
|
) {
|
||||||
|
entityscript_t *script = (entityscript_t*)componentGetData(
|
||||||
|
entityId, componentId, COMPONENT_TYPE_SCRIPT
|
||||||
|
);
|
||||||
|
scriptContextDispose(&script->scriptContext);
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "entity/entitybase.h"
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
scriptcontext_t scriptContext;
|
||||||
|
} entityscript_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the script entity component.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
*/
|
||||||
|
void entityScriptInit(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a script on the entity's script component.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @param script The script to execute.
|
||||||
|
* @return The error return value.
|
||||||
|
*/
|
||||||
|
errorret_t entityScriptExec(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
const char_t *script
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a script from an asset on the entity's script component.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @param assetName The name of the script asset to execute.
|
||||||
|
* @return The error return value.
|
||||||
|
*/
|
||||||
|
errorret_t entityScriptExecAsset(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
const char_t *assetName
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of the script entity component.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
*/
|
||||||
|
void entityScriptDispose(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId
|
||||||
|
);
|
||||||
@@ -10,9 +10,11 @@
|
|||||||
#include "entity/component/display/entitymesh.h"
|
#include "entity/component/display/entitymesh.h"
|
||||||
#include "entity/component/display/entitymaterial.h"
|
#include "entity/component/display/entitymaterial.h"
|
||||||
#include "entity/component/physics/entityphysics.h"
|
#include "entity/component/physics/entityphysics.h"
|
||||||
|
#include "entity/component/script/entityscript.h"
|
||||||
|
|
||||||
X(POSITION, entityposition_t, position, entityPositionInit, NULL)
|
X(POSITION, entityposition_t, position, entityPositionInit, NULL)
|
||||||
X(CAMERA, entitycamera_t, camera, entityCameraInit, NULL)
|
X(CAMERA, entitycamera_t, camera, entityCameraInit, NULL)
|
||||||
X(MESH, entitymesh_t, mesh, entityMeshInit, NULL)
|
X(MESH, entitymesh_t, mesh, entityMeshInit, NULL)
|
||||||
X(MATERIAL, entitymaterial_t, material, entityMaterialInit, NULL)
|
X(MATERIAL, entitymaterial_t, material, entityMaterialInit, NULL)
|
||||||
X(PHYSICS, entityphysics_t, physics, entityPhysicsInit, entityPhysicsDispose)
|
X(PHYSICS, entityphysics_t, physics, entityPhysicsInit, entityPhysicsDispose)
|
||||||
|
X(SCRIPT, entityscript_t, script, entityScriptInit, entityScriptDispose)
|
||||||
@@ -8,8 +8,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "dusk.h"
|
#include "dusk.h"
|
||||||
|
|
||||||
#define ENTITY_COUNT_MAX 6
|
#define ENTITY_COUNT_MAX 64
|
||||||
#define ENTITY_COMPONENT_COUNT_MAX 6
|
#define ENTITY_COMPONENT_COUNT_MAX 16
|
||||||
|
|
||||||
typedef uint8_t entityid_t;
|
typedef uint8_t entityid_t;
|
||||||
typedef uint8_t componentid_t;
|
typedef uint8_t componentid_t;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include "entitymanager.h"
|
#include "entitymanager.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "scene/scene.h"
|
|
||||||
|
|
||||||
entitymanager_t ENTITY_MANAGER;
|
entitymanager_t ENTITY_MANAGER;
|
||||||
|
|
||||||
@@ -19,8 +18,8 @@ void entityManagerInit(void) {
|
|||||||
sizeof(entityid_t) * COMPONENT_TYPE_COUNT * ENTITY_COUNT_MAX
|
sizeof(entityid_t) * COMPONENT_TYPE_COUNT * ENTITY_COUNT_MAX
|
||||||
);
|
);
|
||||||
|
|
||||||
sceneLog(
|
printf(
|
||||||
"Entity Manager size: %zu bytes (%.2f KB)\n",
|
"Entity Manager size is currently: %zu bytes (%.2f KB)\n",
|
||||||
sizeof(entitymanager_t),
|
sizeof(entitymanager_t),
|
||||||
sizeof(entitymanager_t) / 1024.0f
|
sizeof(entitymanager_t) / 1024.0f
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
network.c
|
|
||||||
networkinfo.c
|
|
||||||
)
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "network.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "log/log.h"
|
|
||||||
|
|
||||||
network_t NETWORK;
|
|
||||||
|
|
||||||
errorret_t networkInit() {
|
|
||||||
memoryZero(&NETWORK, sizeof(network_t));
|
|
||||||
|
|
||||||
NETWORK.errorState.code = ERROR_OK;
|
|
||||||
NETWORK.onDisconnect = NULL;
|
|
||||||
|
|
||||||
return networkPlatformInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t networkUpdate() {
|
|
||||||
errorChain(networkPlatformUpdate());
|
|
||||||
|
|
||||||
if(NETWORK.state == NETWORK_STATE_CONNECTED && !networkIsConnected()) {
|
|
||||||
NETWORK.state = NETWORK_STATE_DISCONNECTED;
|
|
||||||
|
|
||||||
if(NETWORK.onDisconnect) {
|
|
||||||
errorret_t ret;
|
|
||||||
if(NETWORK.errorState.code == ERROR_OK) {
|
|
||||||
ret = errorThrowImpl(
|
|
||||||
&NETWORK.errorState,
|
|
||||||
ERROR_NOT_OK,
|
|
||||||
__FILE__, __func__, __LINE__,
|
|
||||||
"Network connection lost"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ret.code = NETWORK.errorState.code;
|
|
||||||
ret.state = &NETWORK.errorState;
|
|
||||||
}
|
|
||||||
NETWORK.onDisconnect(ret, NETWORK.disconnectUser);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool_t networkIsConnected() {
|
|
||||||
return networkPlatformIsConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
void networkRequestConnection(
|
|
||||||
void (*onConnected)(void *user),
|
|
||||||
void (*onFailed)(errorret_t error, void *user),
|
|
||||||
void (*onDisconnect)(errorret_t error, void *user),
|
|
||||||
void *user
|
|
||||||
) {
|
|
||||||
assertNotNull(onConnected, "onConnected callback must not be null");
|
|
||||||
assertNotNull(onFailed, "onFailed callback must not be null");
|
|
||||||
assertNotNull(onDisconnect, "onDisconnect callback must not be null");
|
|
||||||
|
|
||||||
NETWORK.state = NETWORK_STATE_CONNECTING;
|
|
||||||
NETWORK.onDisconnect = onDisconnect;
|
|
||||||
NETWORK.disconnectUser = user;
|
|
||||||
|
|
||||||
#ifndef networkPlatformRequestConnection
|
|
||||||
// This is a platform cannot be requested to go online, this would basically
|
|
||||||
// be for platforms like Linux or Windows where the OS is responsible for
|
|
||||||
// maintaining the network connection.
|
|
||||||
|
|
||||||
if(networkIsConnected()) {
|
|
||||||
NETWORK.state = NETWORK_STATE_CONNECTED;
|
|
||||||
onConnected(user);
|
|
||||||
} else {
|
|
||||||
errorret_t ret = errorThrowImpl(
|
|
||||||
&NETWORK.errorState,
|
|
||||||
ERROR_NOT_OK,
|
|
||||||
__FILE__, __func__, __LINE__,
|
|
||||||
"No network connection available"
|
|
||||||
);
|
|
||||||
onFailed(ret, user);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
networkPlatformRequestConnection(onConnected, onFailed, onDisconnect, user);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void networkRequestDisconnection(
|
|
||||||
void (*onComplete)(void *user),
|
|
||||||
void *user
|
|
||||||
) {
|
|
||||||
assertNotNull(onComplete, "onComplete callback must not be null");
|
|
||||||
NETWORK.state = NETWORK_STATE_DISCONNECTING;
|
|
||||||
|
|
||||||
#ifndef networkPlatformRequestDisconnection
|
|
||||||
NETWORK.state = NETWORK_STATE_DISCONNECTED;
|
|
||||||
onComplete(user);
|
|
||||||
#else
|
|
||||||
networkPlatformRequestDisconnection(onComplete, user);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void networkDisconnectedDuringDispose(void *u) {
|
|
||||||
logDebug("Network disconnected during dispose\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t networkDispose() {
|
|
||||||
if(NETWORK.state == NETWORK_STATE_CONNECTED) {
|
|
||||||
networkRequestDisconnection(networkDisconnectedDuringDispose, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
errorChain(networkPlatformDispose());
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "error/error.h"
|
|
||||||
#include "network/networkplatform.h"
|
|
||||||
#ifndef networkPlatformInit
|
|
||||||
#error "networkPlatformInit must be defined"
|
|
||||||
#endif
|
|
||||||
#ifndef networkPlatformUpdate
|
|
||||||
#error "networkPlatformUpdate must be defined"
|
|
||||||
#endif
|
|
||||||
#ifndef networkPlatformDispose
|
|
||||||
#error "networkPlatformDispose must be defined"
|
|
||||||
#endif
|
|
||||||
#ifndef networkPlatformIsConnected
|
|
||||||
#error "networkPlatformIsConnected must be defined"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NETWORK_STATE_DISCONNECTED,
|
|
||||||
NETWORK_STATE_CONNECTING,
|
|
||||||
NETWORK_STATE_CONNECTED,
|
|
||||||
NETWORK_STATE_DISCONNECTING,
|
|
||||||
} networkstate_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
networkplatform_t platform;
|
|
||||||
errorstate_t errorState;
|
|
||||||
networkstate_t state;
|
|
||||||
|
|
||||||
void (*onDisconnect)(errorret_t error, void *user);
|
|
||||||
void *disconnectUser;
|
|
||||||
} network_t;
|
|
||||||
|
|
||||||
extern network_t NETWORK;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the network system. This will NOT connect to the network.
|
|
||||||
*
|
|
||||||
* @return An error code indicating success or failure.
|
|
||||||
*/
|
|
||||||
errorret_t networkInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the network manager, dispatching any completed async request
|
|
||||||
* callbacks on the main thread.
|
|
||||||
*
|
|
||||||
* @return An error code indicating success or failure.
|
|
||||||
*/
|
|
||||||
errorret_t networkUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes of the network manager. This will NOT disconnect from the network.
|
|
||||||
*
|
|
||||||
* @return An error code indicating success or failure.
|
|
||||||
*/
|
|
||||||
errorret_t networkDispose();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the system is connected to AN network, this doesn't mean that
|
|
||||||
* requests will succeed, doesn't mean there's internet, just that we could
|
|
||||||
* possibly make network requests. If this is false, this usually means
|
|
||||||
* something like;
|
|
||||||
* - A network cable is not connnected
|
|
||||||
* - No Wi-Fi Connection has been established
|
|
||||||
* - No IP Address has been assigned
|
|
||||||
*
|
|
||||||
* That kinda stuff.
|
|
||||||
*
|
|
||||||
* In future I will probably have REASONS for why it's not connected, for
|
|
||||||
* example;
|
|
||||||
* - On PSP you need to "request" network access
|
|
||||||
* - On GameCube, network settings need to be defined, including DHCP, etc.
|
|
||||||
* - On Windows, this may require additional permissions
|
|
||||||
*
|
|
||||||
* @return True if some network connection is detected.
|
|
||||||
*/
|
|
||||||
bool_t networkIsConnected();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See networkIsConnected for a bit more info, but this is for some
|
|
||||||
* platforms (mainly PSP) to request the system to start doing networking.
|
|
||||||
*
|
|
||||||
* You should only call this once and assume that it is "pending" until either
|
|
||||||
* onComplete or onFailed is invoked. If you call this twice it is undefined
|
|
||||||
* behavior.
|
|
||||||
*
|
|
||||||
* onDisconnect must be provided, and is called whenever the network is lost
|
|
||||||
* after a successful connection. This will NOT be called if disconnect is
|
|
||||||
* manually triggered, but WILL if an error occurs, or a network stack bug, etc.
|
|
||||||
*
|
|
||||||
* @param onConnected Callback to invoke when the network is connected.
|
|
||||||
* @param onFailed Callback to invoke if the network connection fails.
|
|
||||||
* @param onDisconnect Called after a successful connection, when disconnected.
|
|
||||||
* @param user User data to pass to the callbacks.
|
|
||||||
*/
|
|
||||||
void networkRequestConnection(
|
|
||||||
void (*onConnected)(void *user),
|
|
||||||
void (*onFailed)(errorret_t error, void *user),
|
|
||||||
void (*onDisconnect)(errorret_t error, void *user),
|
|
||||||
void *user
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests the system to disconnect from the network. This is basically just
|
|
||||||
* for PSP, but I guess it could be used on other platforms in future if they
|
|
||||||
* have some kind of "network connection mode" that needs to be exited.
|
|
||||||
*
|
|
||||||
* You should only call this once and assume that it is "pending" until
|
|
||||||
* onComplete is invoked. If you call this twice it is undefined behavior.
|
|
||||||
*
|
|
||||||
* If it fails, you still get onComplete called, but may fail if you try to
|
|
||||||
* reconnect later unfortunately.
|
|
||||||
*
|
|
||||||
* @param onComplete Callback to invoke when the network is disconnected.
|
|
||||||
* @param user User data to pass to the callback.
|
|
||||||
*/
|
|
||||||
void networkRequestDisconnection(
|
|
||||||
void (*onComplete)(void *user),
|
|
||||||
void *user
|
|
||||||
);
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "network.h"
|
|
||||||
#include "networkinfo.h"
|
|
||||||
#include "network/networkplatform.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
|
|
||||||
#ifndef networkPlatformGetInfo
|
|
||||||
#error "networkPlatformGetInfo must be defined"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
networkinfo_t networkGetInfo() {
|
|
||||||
assertTrue(
|
|
||||||
NETWORK.state == NETWORK_STATE_CONNECTED,
|
|
||||||
"networkGetInfo called when not connected"
|
|
||||||
);
|
|
||||||
|
|
||||||
return networkPlatformGetInfo();
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "dusk.h"
|
|
||||||
|
|
||||||
#define NETWORK_INFO_IPV4_DNS_COUNT_MAX 2
|
|
||||||
#define NETWORK_INFO_IPV4_OCTET_COUNT 4
|
|
||||||
#define NETWORK_INFO_IPV6_OCTET_COUNT 16
|
|
||||||
#define NETWORK_INFO_IPV6_DNS_COUNT_MAX 2
|
|
||||||
#define NETWORK_INFO_FORMAT_IPV4 "%u.%u.%u.%u"
|
|
||||||
#define NETWORK_INFO_FORMAT_IPV6 \
|
|
||||||
"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NETWORK_TYPE_IPV4,
|
|
||||||
#ifdef DUSK_NETWORK_IPV6
|
|
||||||
NETWORK_TYPE_IPV6,
|
|
||||||
#endif
|
|
||||||
} networktype_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t ip[NETWORK_INFO_IPV4_OCTET_COUNT];
|
|
||||||
// uint8_t subnet[NETWORK_INFO_IPV4_OCTET_COUNT];
|
|
||||||
// uint8_t gateway[NETWORK_INFO_IPV4_OCTET_COUNT];
|
|
||||||
// uint8_t dns[NETWORK_INFO_IPV4_OCTET_COUNT][NETWORK_INFO_IPV4_DNS_COUNT_MAX];
|
|
||||||
} networkinfoipv4_t;
|
|
||||||
|
|
||||||
#ifdef DUSK_NETWORK_IPV6
|
|
||||||
typedef struct {
|
|
||||||
uint8_t ip[NETWORK_INFO_IPV6_OCTET_COUNT];
|
|
||||||
// uint8_t subnet[NETWORK_INFO_IPV6_OCTET_COUNT];
|
|
||||||
// uint8_t gateway[NETWORK_INFO_IPV6_OCTET_COUNT];
|
|
||||||
// uint8_t dns[NETWORK_INFO_IPV6_OCTET_COUNT][NETWORK_INFO_IPV6_DNS_COUNT_MAX];
|
|
||||||
} networkinfoipv6_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
networktype_t type;
|
|
||||||
union {
|
|
||||||
networkinfoipv4_t ipv4;
|
|
||||||
#ifdef DUSK_NETWORK_IPV6
|
|
||||||
networkinfoipv6_t ipv6;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
} networkinfo_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the network information for the currently active network connection.
|
|
||||||
*
|
|
||||||
* @return Network information for the currently active network connection.
|
|
||||||
*/
|
|
||||||
networkinfo_t networkGetInfo();
|
|
||||||
@@ -12,59 +12,12 @@
|
|||||||
#include "entity/entitymanager.h"
|
#include "entity/entitymanager.h"
|
||||||
#include "display/shader/shaderunlit.h"
|
#include "display/shader/shaderunlit.h"
|
||||||
#include "display/mesh/cube.h"
|
#include "display/mesh/cube.h"
|
||||||
#include "display/spritebatch/spritebatch.h"
|
|
||||||
#include "display/text/text.h"
|
|
||||||
#include "display/screen/screen.h"
|
|
||||||
|
|
||||||
scene_t SCENE;
|
scene_t SCENE;
|
||||||
|
|
||||||
char_t SCENE_LOG[SCENE_LOG_SIZE];
|
|
||||||
|
|
||||||
void sceneLog(const char *fmt, ...) {
|
|
||||||
char temp[512];
|
|
||||||
|
|
||||||
// 1. Format input like printf
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vsnprintf(temp, sizeof(temp), fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
printf("%s", temp);
|
|
||||||
|
|
||||||
// 2. Split into lines
|
|
||||||
char *lines[64];
|
|
||||||
int line_count = 0;
|
|
||||||
|
|
||||||
char *ptr = temp;
|
|
||||||
while (*ptr && line_count < 64) {
|
|
||||||
lines[line_count++] = ptr;
|
|
||||||
|
|
||||||
char *nl = strchr(ptr, '\n');
|
|
||||||
if (!nl) break;
|
|
||||||
|
|
||||||
*nl = '\0';
|
|
||||||
ptr = nl + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Prepend lines in reverse order (so final order is correct)
|
|
||||||
for (int i = 0; i < line_count; i++) {
|
|
||||||
char new_log[SCENE_LOG_SIZE];
|
|
||||||
|
|
||||||
snprintf(new_log, sizeof(new_log), "%s\n%s", lines[i], SCENE_LOG);
|
|
||||||
|
|
||||||
// Copy back safely
|
|
||||||
strncpy(SCENE_LOG, new_log, SCENE_LOG_SIZE - 1);
|
|
||||||
SCENE_LOG[SCENE_LOG_SIZE - 1] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t sceneInit(void) {
|
errorret_t sceneInit(void) {
|
||||||
memoryZero(&SCENE, sizeof(scene_t));
|
memoryZero(&SCENE, sizeof(scene_t));
|
||||||
|
|
||||||
memoryZero(SCENE_LOG, sizeof(SCENE_LOG));
|
|
||||||
sceneLog("Init\n");
|
|
||||||
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +52,6 @@ errorret_t sceneRender(void) {
|
|||||||
mat4 view, proj, model;
|
mat4 view, proj, model;
|
||||||
errorChain(shaderBind(&SHADER_UNLIT));
|
errorChain(shaderBind(&SHADER_UNLIT));
|
||||||
|
|
||||||
// For each camera.
|
|
||||||
for(entityid_t camIndex = 0; camIndex < camCount; camIndex++) {
|
for(entityid_t camIndex = 0; camIndex < camCount; camIndex++) {
|
||||||
entityid_t camEnt = camEnts[camIndex];
|
entityid_t camEnt = camEnts[camIndex];
|
||||||
componentid_t camComp = camComps[camIndex];
|
componentid_t camComp = camComps[camIndex];
|
||||||
@@ -158,37 +110,6 @@ errorret_t sceneRender(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here is where UI will go
|
|
||||||
glm_ortho(
|
|
||||||
0.0f, SCREEN.width,
|
|
||||||
SCREEN.height, 0.0f,
|
|
||||||
0.1f, 100.0f,
|
|
||||||
proj
|
|
||||||
);
|
|
||||||
glm_lookat(
|
|
||||||
(vec3){ 0.0f, 0.0f, 1.0f },
|
|
||||||
(vec3){ 0.0f, 0.0f, 0.0f },
|
|
||||||
(vec3){ 0.0f, 1.0f, 0.0f },
|
|
||||||
view
|
|
||||||
);
|
|
||||||
glm_mat4_identity(model);
|
|
||||||
|
|
||||||
errorChain(shaderBind(&SHADER_UNLIT));
|
|
||||||
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_PROJECTION, proj));
|
|
||||||
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_VIEW, view));
|
|
||||||
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, model));
|
|
||||||
// errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_0TEXTURE, &DEFAULT_FONT_TEXTURE));
|
|
||||||
// errorChain(shaderSetColor(&SHADER_UNLIT, SHADER_UNLIT_COLOR, COLOR_WHITE));
|
|
||||||
errorChain(textDraw(
|
|
||||||
32, 32,
|
|
||||||
// "Hello World",
|
|
||||||
SCENE_LOG,
|
|
||||||
COLOR_WHITE,
|
|
||||||
&DEFAULT_FONT_TILESET,
|
|
||||||
&DEFAULT_FONT_TEXTURE
|
|
||||||
));
|
|
||||||
errorChain(spriteBatchFlush());
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,6 @@ typedef struct {
|
|||||||
|
|
||||||
extern scene_t SCENE;
|
extern scene_t SCENE;
|
||||||
|
|
||||||
#define SCENE_LOG_SIZE 1024
|
|
||||||
extern char_t SCENE_LOG[SCENE_LOG_SIZE];
|
|
||||||
void sceneLog(const char *fmt, ...);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the scene subsystem.
|
* Initialize the scene subsystem.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -11,4 +11,5 @@ add_subdirectory(locale)
|
|||||||
add_subdirectory(system)
|
add_subdirectory(system)
|
||||||
add_subdirectory(scene)
|
add_subdirectory(scene)
|
||||||
add_subdirectory(time)
|
add_subdirectory(time)
|
||||||
add_subdirectory(ui)
|
add_subdirectory(ui)
|
||||||
|
add_subdirectory(entity)
|
||||||
@@ -52,7 +52,9 @@ int moduleTextDraw(lua_State *L) {
|
|||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
text,
|
text,
|
||||||
color == NULL ? COLOR_WHITE : *color,
|
#if MESH_ENABLE_COLOR
|
||||||
|
color == NULL ? COLOR_WHITE : *color,
|
||||||
|
#endif
|
||||||
&DEFAULT_FONT_TILESET,
|
&DEFAULT_FONT_TILESET,
|
||||||
&DEFAULT_FONT_TEXTURE
|
&DEFAULT_FONT_TEXTURE
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,5 +6,11 @@
|
|||||||
# Sources
|
# Sources
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
inputvita.c
|
moduleentity.c
|
||||||
|
moduleentityposition.c
|
||||||
|
moduleentitycamera.c
|
||||||
|
moduleentitymesh.c
|
||||||
|
moduleentitymaterial.c
|
||||||
|
moduleentityphysics.c
|
||||||
|
moduleentityscript.c
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "moduleentity.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "entity/entitymanager.h"
|
||||||
|
#include "entity/entity.h"
|
||||||
|
#include "entity/component.h"
|
||||||
|
|
||||||
|
void moduleEntity(scriptcontext_t *ctx) {
|
||||||
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
|
lua_State *l = ctx->luaState;
|
||||||
|
|
||||||
|
// Component type constants
|
||||||
|
lua_pushnumber(l, COMPONENT_TYPE_POSITION);
|
||||||
|
lua_setglobal(l, "COMPONENT_TYPE_POSITION");
|
||||||
|
|
||||||
|
lua_pushnumber(l, COMPONENT_TYPE_CAMERA);
|
||||||
|
lua_setglobal(l, "COMPONENT_TYPE_CAMERA");
|
||||||
|
|
||||||
|
lua_pushnumber(l, COMPONENT_TYPE_MESH);
|
||||||
|
lua_setglobal(l, "COMPONENT_TYPE_MESH");
|
||||||
|
|
||||||
|
lua_pushnumber(l, COMPONENT_TYPE_MATERIAL);
|
||||||
|
lua_setglobal(l, "COMPONENT_TYPE_MATERIAL");
|
||||||
|
|
||||||
|
lua_pushnumber(l, COMPONENT_TYPE_PHYSICS);
|
||||||
|
lua_setglobal(l, "COMPONENT_TYPE_PHYSICS");
|
||||||
|
|
||||||
|
lua_pushnumber(l, COMPONENT_TYPE_SCRIPT);
|
||||||
|
lua_setglobal(l, "COMPONENT_TYPE_SCRIPT");
|
||||||
|
|
||||||
|
// Entity functions
|
||||||
|
lua_register(l, "entityCreate", moduleEntityCreate);
|
||||||
|
lua_register(l, "entityAddComponent", moduleEntityAddComponent);
|
||||||
|
lua_register(l, "entityGetComponent", moduleEntityGetComponent);
|
||||||
|
lua_register(l, "entityDispose", moduleEntityDispose);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityCreate(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
entityid_t id = entityManagerAdd();
|
||||||
|
entityInit(id);
|
||||||
|
lua_pushnumber(L, id);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityAddComponent(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityAddComponent: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityAddComponent: componentType must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t entityId = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componenttype_t type = (componenttype_t)lua_tonumber(L, 2);
|
||||||
|
componentid_t compId = entityAddComponent(entityId, type);
|
||||||
|
lua_pushnumber(L, compId);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityGetComponent(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityGetComponent: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityGetComponent: componentType must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t entityId = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componenttype_t type = (componenttype_t)lua_tonumber(L, 2);
|
||||||
|
componentid_t compId = entityGetComponent(entityId, type);
|
||||||
|
|
||||||
|
if(compId == 0xFF) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
} else {
|
||||||
|
lua_pushnumber(L, compId);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityDispose(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityDispose: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t entityId = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
entityDispose(entityId);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the entity module within the given script context.
|
||||||
|
* Provides: entityCreate, entityAddComponent, entityGetComponent, entityDispose
|
||||||
|
* and all COMPONENT_TYPE_* constants.
|
||||||
|
*
|
||||||
|
* @param ctx The script context to register the module in.
|
||||||
|
*/
|
||||||
|
void moduleEntity(scriptcontext_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: reserves and initializes a new entity.
|
||||||
|
* Returns: entityId (integer)
|
||||||
|
*/
|
||||||
|
int moduleEntityCreate(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: adds a component of the given type to an entity.
|
||||||
|
* Args: entityId (integer), componentType (integer)
|
||||||
|
* Returns: componentId (integer)
|
||||||
|
*/
|
||||||
|
int moduleEntityAddComponent(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: gets the component ID for the given type on an entity.
|
||||||
|
* Args: entityId (integer), componentType (integer)
|
||||||
|
* Returns: componentId (integer), or nil if the entity lacks the component
|
||||||
|
*/
|
||||||
|
int moduleEntityGetComponent(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: disposes of the entity with the given ID.
|
||||||
|
* Args: entityId (integer)
|
||||||
|
*/
|
||||||
|
int moduleEntityDispose(lua_State *L);
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "moduleentitycamera.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "entity/component/display/entitycamera.h"
|
||||||
|
|
||||||
|
void moduleEntityCamera(scriptcontext_t *ctx) {
|
||||||
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
|
lua_State *l = ctx->luaState;
|
||||||
|
|
||||||
|
// Projection type constants
|
||||||
|
lua_pushnumber(l, ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE);
|
||||||
|
lua_setglobal(l, "ENTITY_CAMERA_PROJECTION_PERSPECTIVE");
|
||||||
|
|
||||||
|
lua_pushnumber(l, ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED);
|
||||||
|
lua_setglobal(l, "ENTITY_CAMERA_PROJECTION_PERSPECTIVE_FLIPPED");
|
||||||
|
|
||||||
|
lua_pushnumber(l, ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC);
|
||||||
|
lua_setglobal(l, "ENTITY_CAMERA_PROJECTION_ORTHOGRAPHIC");
|
||||||
|
|
||||||
|
// Camera functions
|
||||||
|
lua_register(l, "entityCameraGetZNear", moduleEntityCameraGetZNear);
|
||||||
|
lua_register(l, "entityCameraSetZNear", moduleEntityCameraSetZNear);
|
||||||
|
lua_register(l, "entityCameraGetZFar", moduleEntityCameraGetZFar);
|
||||||
|
lua_register(l, "entityCameraSetZFar", moduleEntityCameraSetZFar);
|
||||||
|
lua_register(l, "entityCameraGetProjType", moduleEntityCameraGetProjType);
|
||||||
|
lua_register(l, "entityCameraSetProjType", moduleEntityCameraSetProjType);
|
||||||
|
lua_register(l, "entityCameraGetFov", moduleEntityCameraGetFov);
|
||||||
|
lua_register(l, "entityCameraSetFov", moduleEntityCameraSetFov);
|
||||||
|
lua_register(l, "entityCameraSetOrthographic", moduleEntityCameraSetOrthographic);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityCameraGetZNear(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityCameraGetZNear: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityCameraGetZNear: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
lua_pushnumber(L, entityCameraGetZNear(eid, cid));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityCameraSetZNear(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityCameraSetZNear: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityCameraSetZNear: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 3)) {
|
||||||
|
luaL_error(L, "entityCameraSetZNear: zNear must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
float_t zNear = (float_t)lua_tonumber(L, 3);
|
||||||
|
entityCameraSetZNear(eid, cid, zNear);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityCameraGetZFar(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityCameraGetZFar: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityCameraGetZFar: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
lua_pushnumber(L, entityCameraGetZFar(eid, cid));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityCameraSetZFar(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityCameraSetZFar: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityCameraSetZFar: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 3)) {
|
||||||
|
luaL_error(L, "entityCameraSetZFar: zFar must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
float_t zFar = (float_t)lua_tonumber(L, 3);
|
||||||
|
entityCameraSetZFar(eid, cid, zFar);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityCameraGetProjType(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityCameraGetProjType: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityCameraGetProjType: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
lua_pushnumber(L, entityCameraGetProjType(eid, cid));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityCameraSetProjType(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityCameraSetProjType: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityCameraSetProjType: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 3)) {
|
||||||
|
luaL_error(L, "entityCameraSetProjType: projType must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
entitycameraprojectiontype_t type = (entitycameraprojectiontype_t)lua_tonumber(L, 3);
|
||||||
|
entityCameraSetProjType(eid, cid, type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityCameraGetFov(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityCameraGetFov: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityCameraGetFov: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
lua_pushnumber(L, entityCameraGetFov(eid, cid));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityCameraSetFov(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityCameraSetFov: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityCameraSetFov: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 3)) {
|
||||||
|
luaL_error(L, "entityCameraSetFov: fov must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
float_t fov = (float_t)lua_tonumber(L, 3);
|
||||||
|
entityCameraSetFov(eid, cid, fov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityCameraSetOrthographic(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityCameraSetOrthographic: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityCameraSetOrthographic: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 3) || !lua_isnumber(L, 4) ||
|
||||||
|
!lua_isnumber(L, 5) || !lua_isnumber(L, 6)) {
|
||||||
|
luaL_error(L, "entityCameraSetOrthographic: left/right/top/bottom must be numbers");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
float_t left = (float_t)lua_tonumber(L, 3);
|
||||||
|
float_t right = (float_t)lua_tonumber(L, 4);
|
||||||
|
float_t top = (float_t)lua_tonumber(L, 5);
|
||||||
|
float_t bottom = (float_t)lua_tonumber(L, 6);
|
||||||
|
entityCameraSetOrthographic(eid, cid, left, right, top, bottom);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the entitycamera module within the given script context.
|
||||||
|
* Provides get/set functions for znear, zfar, and projection type constants.
|
||||||
|
*
|
||||||
|
* @param ctx The script context to register the module in.
|
||||||
|
*/
|
||||||
|
void moduleEntityCamera(scriptcontext_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityCameraGetZNear(entityId, componentId) -> number
|
||||||
|
*/
|
||||||
|
int moduleEntityCameraGetZNear(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityCameraSetZNear(entityId, componentId, number)
|
||||||
|
*/
|
||||||
|
int moduleEntityCameraSetZNear(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityCameraGetZFar(entityId, componentId) -> number
|
||||||
|
*/
|
||||||
|
int moduleEntityCameraGetZFar(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityCameraSetZFar(entityId, componentId, number)
|
||||||
|
*/
|
||||||
|
int moduleEntityCameraSetZFar(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityCameraGetProjType(entityId, componentId) -> number
|
||||||
|
*/
|
||||||
|
int moduleEntityCameraGetProjType(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityCameraSetProjType(entityId, componentId, number)
|
||||||
|
*/
|
||||||
|
int moduleEntityCameraSetProjType(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityCameraGetFov(entityId, componentId) -> number (radians)
|
||||||
|
*/
|
||||||
|
int moduleEntityCameraGetFov(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityCameraSetFov(entityId, componentId, number)
|
||||||
|
*/
|
||||||
|
int moduleEntityCameraSetFov(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityCameraSetOrthographic(entityId, componentId, left, right, top, bottom)
|
||||||
|
*/
|
||||||
|
int moduleEntityCameraSetOrthographic(lua_State *L);
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "moduleentitymaterial.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "entity/component/display/entitymaterial.h"
|
||||||
|
#include "display/shader/shaderunlit.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
void moduleEntityMaterial(scriptcontext_t *ctx) {
|
||||||
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
|
lua_State *l = ctx->luaState;
|
||||||
|
|
||||||
|
// shadermaterial_mt: wraps shadermaterial_t* pointer
|
||||||
|
if(luaL_newmetatable(l, "shadermaterial_mt")) {
|
||||||
|
lua_pushcfunction(l, moduleEntityMaterialShaderMaterialIndex);
|
||||||
|
lua_setfield(l, -2, "__index");
|
||||||
|
}
|
||||||
|
lua_pop(l, 1);
|
||||||
|
|
||||||
|
// shaderunlitmaterial_mt: wraps shaderunlitmaterial_t* pointer
|
||||||
|
if(luaL_newmetatable(l, "shaderunlitmaterial_mt")) {
|
||||||
|
lua_pushcfunction(l, moduleEntityMaterialUnlitIndex);
|
||||||
|
lua_setfield(l, -2, "__index");
|
||||||
|
lua_pushcfunction(l, moduleEntityMaterialUnlitNewIndex);
|
||||||
|
lua_setfield(l, -2, "__newindex");
|
||||||
|
}
|
||||||
|
lua_pop(l, 1);
|
||||||
|
|
||||||
|
lua_register(l, "entityMaterialGetShader", moduleEntityMaterialGetShader);
|
||||||
|
lua_register(l, "entityMaterialSetShader", moduleEntityMaterialSetShader);
|
||||||
|
lua_register(l, "entityMaterialGetShaderMaterial", moduleEntityMaterialGetShaderMaterial);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityMaterialGetShader(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "Entity ID must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "Component ID must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
shader_t *shader = entityMaterialGetShader(eid, cid);
|
||||||
|
|
||||||
|
if(shader == NULL) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
} else {
|
||||||
|
lua_pushlightuserdata(L, shader);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityMaterialSetShader(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "Entity ID must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "Component ID must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
|
||||||
|
shader_t *shader = NULL;
|
||||||
|
if(!lua_isnil(L, 3)) {
|
||||||
|
if(!lua_isuserdata(L, 3)) {
|
||||||
|
luaL_error(L, "Shader must be a userdata or nil");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
shader = (shader_t *)lua_touserdata(L, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
entityMaterialSetShader(eid, cid, shader);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityMaterialGetShaderMaterial(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityMaterialGetShaderMaterial: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityMaterialGetShaderMaterial: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
shadermaterial_t *mat = entityMaterialGetShaderMaterial(eid, cid);
|
||||||
|
|
||||||
|
if(mat == NULL) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
shadermaterial_t **pmat = (shadermaterial_t **)lua_newuserdata(
|
||||||
|
L, sizeof(shadermaterial_t *)
|
||||||
|
);
|
||||||
|
*pmat = mat;
|
||||||
|
luaL_getmetatable(L, "shadermaterial_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityMaterialShaderMaterialIndex(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
shadermaterial_t *mat = *(shadermaterial_t **)luaL_checkudata(
|
||||||
|
L, 1, "shadermaterial_mt"
|
||||||
|
);
|
||||||
|
assertNotNull(mat, "Shader material pointer cannot be NULL");
|
||||||
|
|
||||||
|
const char_t *key = lua_tostring(L, 2);
|
||||||
|
if(key != NULL && stringCompare(key, "unlit") == 0) {
|
||||||
|
shaderunlitmaterial_t **punlit = (shaderunlitmaterial_t **)lua_newuserdata(
|
||||||
|
L, sizeof(shaderunlitmaterial_t *)
|
||||||
|
);
|
||||||
|
*punlit = &(mat->unlit);
|
||||||
|
luaL_getmetatable(L, "shaderunlitmaterial_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityMaterialUnlitIndex(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
shaderunlitmaterial_t *unlit = *(shaderunlitmaterial_t **)luaL_checkudata(
|
||||||
|
L, 1, "shaderunlitmaterial_mt"
|
||||||
|
);
|
||||||
|
assertNotNull(unlit, "Unlit material pointer cannot be NULL");
|
||||||
|
|
||||||
|
const char_t *key = lua_tostring(L, 2);
|
||||||
|
if(key == NULL) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stringCompare(key, "color") == 0) {
|
||||||
|
color_t *color = (color_t *)lua_newuserdata(L, sizeof(color_t));
|
||||||
|
*color = unlit->color;
|
||||||
|
luaL_getmetatable(L, "color_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stringCompare(key, "texture") == 0) {
|
||||||
|
if(unlit->texture == NULL) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
} else {
|
||||||
|
lua_pushlightuserdata(L, unlit->texture);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityMaterialUnlitNewIndex(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
shaderunlitmaterial_t *unlit = *(shaderunlitmaterial_t **)luaL_checkudata(
|
||||||
|
L, 1, "shaderunlitmaterial_mt"
|
||||||
|
);
|
||||||
|
assertNotNull(unlit, "Unlit material pointer cannot be NULL");
|
||||||
|
|
||||||
|
const char_t *key = lua_tostring(L, 2);
|
||||||
|
if(key == NULL) return 0;
|
||||||
|
|
||||||
|
if(stringCompare(key, "color") == 0) {
|
||||||
|
color_t *color = (color_t *)luaL_checkudata(L, 3, "color_mt");
|
||||||
|
unlit->color = *color;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stringCompare(key, "texture") == 0) {
|
||||||
|
if(lua_isnil(L, 3)) {
|
||||||
|
unlit->texture = NULL;
|
||||||
|
} else if(lua_isuserdata(L, 3)) {
|
||||||
|
unlit->texture = (texture_t *)lua_touserdata(L, 3);
|
||||||
|
} else {
|
||||||
|
luaL_error(L, "shaderunlitmaterial texture must be a userdata or nil");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the entitymaterial module within the given script context.
|
||||||
|
* Provides get/set functions for the shader pointer (lightuserdata).
|
||||||
|
*
|
||||||
|
* @param ctx The script context to register the module in.
|
||||||
|
*/
|
||||||
|
void moduleEntityMaterial(scriptcontext_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityMaterialGetShader(entityId, componentId) -> lightuserdata or nil
|
||||||
|
*/
|
||||||
|
int moduleEntityMaterialGetShader(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityMaterialSetShader(entityId, componentId, shader_lightuserdata|nil)
|
||||||
|
*/
|
||||||
|
int moduleEntityMaterialSetShader(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityMaterialGetShaderMaterial(entityId, componentId)
|
||||||
|
* Returns a shadermaterial userdata (shadermaterial_mt) holding a pointer
|
||||||
|
* into the entity's material component, or nil on failure.
|
||||||
|
*/
|
||||||
|
int moduleEntityMaterialGetShaderMaterial(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __index metamethod for shadermaterial_mt userdata.
|
||||||
|
* Supports field: "unlit" -> shaderunlitmaterial_mt userdata.
|
||||||
|
*/
|
||||||
|
int moduleEntityMaterialShaderMaterialIndex(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __index metamethod for shaderunlitmaterial_mt userdata.
|
||||||
|
* Supports fields: "color" -> color_mt copy, "texture" -> lightuserdata or nil.
|
||||||
|
*/
|
||||||
|
int moduleEntityMaterialUnlitIndex(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __newindex metamethod for shaderunlitmaterial_mt userdata.
|
||||||
|
* Supports fields: "color" <- color_mt, "texture" <- lightuserdata or nil.
|
||||||
|
*/
|
||||||
|
int moduleEntityMaterialUnlitNewIndex(lua_State *L);
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "moduleentitymesh.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "entity/component/display/entitymesh.h"
|
||||||
|
|
||||||
|
void moduleEntityMesh(scriptcontext_t *ctx) {
|
||||||
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
|
lua_State *l = ctx->luaState;
|
||||||
|
lua_register(l, "entityMeshGetMesh", moduleEntityMeshGetMesh);
|
||||||
|
lua_register(l, "entityMeshSetMesh", moduleEntityMeshSetMesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityMeshGetMesh(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityMeshGetMesh: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityMeshGetMesh: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
mesh_t *mesh = entityMeshGetMesh(eid, cid);
|
||||||
|
|
||||||
|
if(mesh == NULL) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
} else {
|
||||||
|
lua_pushlightuserdata(L, mesh);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityMeshSetMesh(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityMeshSetMesh: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityMeshSetMesh: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
|
||||||
|
mesh_t *mesh = NULL;
|
||||||
|
if(!lua_isnil(L, 3)) {
|
||||||
|
if(!lua_isuserdata(L, 3)) {
|
||||||
|
luaL_error(L, "entityMeshSetMesh: mesh must be a userdata or nil");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
mesh = (mesh_t *)lua_touserdata(L, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
entityMeshSetMesh(eid, cid, mesh);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the entitymesh module within the given script context.
|
||||||
|
* Provides get/set functions for the mesh pointer (lightuserdata).
|
||||||
|
*
|
||||||
|
* @param ctx The script context to register the module in.
|
||||||
|
*/
|
||||||
|
void moduleEntityMesh(scriptcontext_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityMeshGetMesh(entityId, componentId) -> lightuserdata or nil
|
||||||
|
*/
|
||||||
|
int moduleEntityMeshGetMesh(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityMeshSetMesh(entityId, componentId, mesh_lightuserdata|nil)
|
||||||
|
*/
|
||||||
|
int moduleEntityMeshSetMesh(lua_State *L);
|
||||||
@@ -0,0 +1,383 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "moduleentityphysics.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "entity/component/physics/entityphysics.h"
|
||||||
|
|
||||||
|
void moduleEntityPhysics(scriptcontext_t *ctx) {
|
||||||
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
|
lua_State *l = ctx->luaState;
|
||||||
|
|
||||||
|
// Body type constants
|
||||||
|
lua_pushnumber(l, PHYSICS_BODY_STATIC);
|
||||||
|
lua_setglobal(l, "PHYSICS_BODY_STATIC");
|
||||||
|
|
||||||
|
lua_pushnumber(l, PHYSICS_BODY_DYNAMIC);
|
||||||
|
lua_setglobal(l, "PHYSICS_BODY_DYNAMIC");
|
||||||
|
|
||||||
|
lua_pushnumber(l, PHYSICS_BODY_KINEMATIC);
|
||||||
|
lua_setglobal(l, "PHYSICS_BODY_KINEMATIC");
|
||||||
|
|
||||||
|
// Shape type constants
|
||||||
|
lua_pushnumber(l, PHYSICS_SHAPE_CUBE);
|
||||||
|
lua_setglobal(l, "PHYSICS_SHAPE_CUBE");
|
||||||
|
|
||||||
|
lua_pushnumber(l, PHYSICS_SHAPE_SPHERE);
|
||||||
|
lua_setglobal(l, "PHYSICS_SHAPE_SPHERE");
|
||||||
|
|
||||||
|
lua_pushnumber(l, PHYSICS_SHAPE_CAPSULE);
|
||||||
|
lua_setglobal(l, "PHYSICS_SHAPE_CAPSULE");
|
||||||
|
|
||||||
|
lua_pushnumber(l, PHYSICS_SHAPE_PLANE);
|
||||||
|
lua_setglobal(l, "PHYSICS_SHAPE_PLANE");
|
||||||
|
|
||||||
|
// Physics shape metatable
|
||||||
|
if(luaL_newmetatable(l, "physicsshape_mt")) {
|
||||||
|
lua_pushcfunction(l, moduleEntityPhysicsShapeToString);
|
||||||
|
lua_setfield(l, -2, "__tostring");
|
||||||
|
}
|
||||||
|
lua_pop(l, 1);
|
||||||
|
|
||||||
|
// Shape constructors
|
||||||
|
lua_register(l, "physicsShapeCube", modulePhysicsShapeCube);
|
||||||
|
lua_register(l, "physicsShapeSphere", modulePhysicsShapeSphere);
|
||||||
|
lua_register(l, "physicsShapeCapsule", modulePhysicsShapeCapsule);
|
||||||
|
lua_register(l, "physicsShapePlane", modulePhysicsShapePlane);
|
||||||
|
|
||||||
|
// Entity physics functions
|
||||||
|
lua_register(l, "entityPhysicsGetVelocity", moduleEntityPhysicsGetVelocity);
|
||||||
|
lua_register(l, "entityPhysicsSetVelocity", moduleEntityPhysicsSetVelocity);
|
||||||
|
lua_register(l, "entityPhysicsApplyImpulse", moduleEntityPhysicsApplyImpulse);
|
||||||
|
lua_register(l, "entityPhysicsIsOnGround", moduleEntityPhysicsIsOnGround);
|
||||||
|
lua_register(l, "entityPhysicsGetShape", moduleEntityPhysicsGetShape);
|
||||||
|
lua_register(l, "entityPhysicsSetShape", moduleEntityPhysicsSetShape);
|
||||||
|
lua_register(l, "entityPhysicsGetBodyType", moduleEntityPhysicsGetBodyType);
|
||||||
|
lua_register(l, "entityPhysicsSetBodyType", moduleEntityPhysicsSetBodyType);
|
||||||
|
lua_register(l, "entityPhysicsGetGravityScale", moduleEntityPhysicsGetGravityScale);
|
||||||
|
lua_register(l, "entityPhysicsSetGravityScale", moduleEntityPhysicsSetGravityScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPhysicsShapeToString(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
physicsshape_t *shape = (physicsshape_t *)luaL_checkudata(L, 1, "physicsshape_mt");
|
||||||
|
assertNotNull(shape, "Physics shape pointer cannot be NULL");
|
||||||
|
|
||||||
|
const char_t *typeName = "unknown";
|
||||||
|
switch(shape->type) {
|
||||||
|
case PHYSICS_SHAPE_CUBE: typeName = "cube"; break;
|
||||||
|
case PHYSICS_SHAPE_SPHERE: typeName = "sphere"; break;
|
||||||
|
case PHYSICS_SHAPE_CAPSULE: typeName = "capsule"; break;
|
||||||
|
case PHYSICS_SHAPE_PLANE: typeName = "plane"; break;
|
||||||
|
}
|
||||||
|
lua_pushfstring(L, "physicsshape(%s)", typeName);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPhysicsGetVelocity(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPhysicsGetVelocity: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPhysicsGetVelocity: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
|
||||||
|
vec3 *v = (vec3 *)lua_newuserdata(L, sizeof(vec3));
|
||||||
|
memoryZero(v, sizeof(vec3));
|
||||||
|
entityPhysicsGetVelocity(eid, cid, *v);
|
||||||
|
luaL_getmetatable(L, "vec3_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPhysicsSetVelocity(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPhysicsSetVelocity: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPhysicsSetVelocity: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
vec3 *v = (vec3 *)luaL_checkudata(L, 3, "vec3_mt");
|
||||||
|
entityPhysicsSetVelocity(eid, cid, *v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPhysicsApplyImpulse(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPhysicsApplyImpulse: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPhysicsApplyImpulse: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
vec3 *v = (vec3 *)luaL_checkudata(L, 3, "vec3_mt");
|
||||||
|
entityPhysicsApplyImpulse(eid, cid, *v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPhysicsIsOnGround(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPhysicsIsOnGround: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPhysicsIsOnGround: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
lua_pushboolean(L, entityPhysicsIsOnGround(eid, cid) ? 1 : 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPhysicsSetShape(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPhysicsSetShape: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPhysicsSetShape: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
physicsshape_t *shape = (physicsshape_t *)luaL_checkudata(L, 3, "physicsshape_mt");
|
||||||
|
entityPhysicsSetShape(eid, cid, *shape);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPhysicsGetShape(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPhysicsGetShape: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPhysicsGetShape: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
|
||||||
|
physicsshape_t *shape = (physicsshape_t *)lua_newuserdata(L, sizeof(physicsshape_t));
|
||||||
|
*shape = entityPhysicsGetShape(eid, cid);
|
||||||
|
luaL_getmetatable(L, "physicsshape_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPhysicsGetBodyType(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPhysicsGetBodyType: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPhysicsGetBodyType: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
lua_pushnumber(L, entityPhysicsGetBodyType(eid, cid));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPhysicsSetBodyType(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPhysicsSetBodyType: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPhysicsSetBodyType: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 3)) {
|
||||||
|
luaL_error(L, "entityPhysicsSetBodyType: bodyType must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
physicsbodytype_t type = (physicsbodytype_t)lua_tonumber(L, 3);
|
||||||
|
entityPhysicsSetBodyType(eid, cid, type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPhysicsGetGravityScale(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPhysicsGetGravityScale: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPhysicsGetGravityScale: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
lua_pushnumber(L, entityPhysicsGetGravityScale(eid, cid));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPhysicsSetGravityScale(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPhysicsSetGravityScale: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPhysicsSetGravityScale: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 3)) {
|
||||||
|
luaL_error(L, "entityPhysicsSetGravityScale: scale must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
float_t scale = (float_t)lua_tonumber(L, 3);
|
||||||
|
entityPhysicsSetGravityScale(eid, cid, scale);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int modulePhysicsShapeCube(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
float_t hx = lua_isnumber(L, 1) ? (float_t)lua_tonumber(L, 1) : 0.5f;
|
||||||
|
float_t hy = lua_isnumber(L, 2) ? (float_t)lua_tonumber(L, 2) : 0.5f;
|
||||||
|
float_t hz = lua_isnumber(L, 3) ? (float_t)lua_tonumber(L, 3) : 0.5f;
|
||||||
|
|
||||||
|
physicsshape_t *shape = (physicsshape_t *)lua_newuserdata(L, sizeof(physicsshape_t));
|
||||||
|
memoryZero(shape, sizeof(physicsshape_t));
|
||||||
|
shape->type = PHYSICS_SHAPE_CUBE;
|
||||||
|
shape->data.cube.halfExtents[0] = hx;
|
||||||
|
shape->data.cube.halfExtents[1] = hy;
|
||||||
|
shape->data.cube.halfExtents[2] = hz;
|
||||||
|
luaL_getmetatable(L, "physicsshape_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int modulePhysicsShapeSphere(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "physicsShapeSphere: radius must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float_t radius = (float_t)lua_tonumber(L, 1);
|
||||||
|
|
||||||
|
physicsshape_t *shape = (physicsshape_t *)lua_newuserdata(L, sizeof(physicsshape_t));
|
||||||
|
memoryZero(shape, sizeof(physicsshape_t));
|
||||||
|
shape->type = PHYSICS_SHAPE_SPHERE;
|
||||||
|
shape->data.sphere.radius = radius;
|
||||||
|
luaL_getmetatable(L, "physicsshape_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int modulePhysicsShapeCapsule(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "physicsShapeCapsule: radius must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "physicsShapeCapsule: halfHeight must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float_t radius = (float_t)lua_tonumber(L, 1);
|
||||||
|
float_t halfHeight = (float_t)lua_tonumber(L, 2);
|
||||||
|
|
||||||
|
physicsshape_t *shape = (physicsshape_t *)lua_newuserdata(L, sizeof(physicsshape_t));
|
||||||
|
memoryZero(shape, sizeof(physicsshape_t));
|
||||||
|
shape->type = PHYSICS_SHAPE_CAPSULE;
|
||||||
|
shape->data.capsule.radius = radius;
|
||||||
|
shape->data.capsule.halfHeight = halfHeight;
|
||||||
|
luaL_getmetatable(L, "physicsshape_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int modulePhysicsShapePlane(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "physicsShapePlane: normalX must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "physicsShapePlane: normalY must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 3)) {
|
||||||
|
luaL_error(L, "physicsShapePlane: normalZ must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 4)) {
|
||||||
|
luaL_error(L, "physicsShapePlane: distance must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float_t nx = (float_t)lua_tonumber(L, 1);
|
||||||
|
float_t ny = (float_t)lua_tonumber(L, 2);
|
||||||
|
float_t nz = (float_t)lua_tonumber(L, 3);
|
||||||
|
float_t distance = (float_t)lua_tonumber(L, 4);
|
||||||
|
|
||||||
|
physicsshape_t *shape = (physicsshape_t *)lua_newuserdata(L, sizeof(physicsshape_t));
|
||||||
|
memoryZero(shape, sizeof(physicsshape_t));
|
||||||
|
shape->type = PHYSICS_SHAPE_PLANE;
|
||||||
|
shape->data.plane.normal[0] = nx;
|
||||||
|
shape->data.plane.normal[1] = ny;
|
||||||
|
shape->data.plane.normal[2] = nz;
|
||||||
|
shape->data.plane.distance = distance;
|
||||||
|
luaL_getmetatable(L, "physicsshape_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the entityphysics module within the given script context.
|
||||||
|
* Provides velocity, impulse, onGround, and shape functions, plus body type
|
||||||
|
* and shape type constants. Shape constructors: physicsShapeCube,
|
||||||
|
* physicsShapeSphere, physicsShapeCapsule, physicsShapePlane.
|
||||||
|
*
|
||||||
|
* @param ctx The script context to register the module in.
|
||||||
|
*/
|
||||||
|
void moduleEntityPhysics(scriptcontext_t *ctx);
|
||||||
|
|
||||||
|
/** Lua binding: entityPhysicsGetVelocity(entityId, componentId) -> vec3 */
|
||||||
|
int moduleEntityPhysicsGetVelocity(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: entityPhysicsSetVelocity(entityId, componentId, vec3) */
|
||||||
|
int moduleEntityPhysicsSetVelocity(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: entityPhysicsApplyImpulse(entityId, componentId, vec3) */
|
||||||
|
int moduleEntityPhysicsApplyImpulse(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: entityPhysicsIsOnGround(entityId, componentId) -> boolean */
|
||||||
|
int moduleEntityPhysicsIsOnGround(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: entityPhysicsSetShape(entityId, componentId, physicsshape) */
|
||||||
|
int moduleEntityPhysicsSetShape(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: physicsShapeCube(halfX, halfY, halfZ) -> physicsshape */
|
||||||
|
int modulePhysicsShapeCube(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: physicsShapeSphere(radius) -> physicsshape */
|
||||||
|
int modulePhysicsShapeSphere(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: physicsShapeCapsule(radius, halfHeight) -> physicsshape */
|
||||||
|
int modulePhysicsShapeCapsule(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: physicsShapePlane(normalX, normalY, normalZ, distance) -> physicsshape */
|
||||||
|
int modulePhysicsShapePlane(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: entityPhysicsGetShape(entityId, componentId) -> physicsshape */
|
||||||
|
int moduleEntityPhysicsGetShape(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: entityPhysicsGetBodyType(entityId, componentId) -> number */
|
||||||
|
int moduleEntityPhysicsGetBodyType(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: entityPhysicsSetBodyType(entityId, componentId, number) */
|
||||||
|
int moduleEntityPhysicsSetBodyType(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: entityPhysicsGetGravityScale(entityId, componentId) -> number */
|
||||||
|
int moduleEntityPhysicsGetGravityScale(lua_State *L);
|
||||||
|
|
||||||
|
/** Lua binding: entityPhysicsSetGravityScale(entityId, componentId, number) */
|
||||||
|
int moduleEntityPhysicsSetGravityScale(lua_State *L);
|
||||||
|
|
||||||
|
/** Metatable __tostring for physicsshape userdata */
|
||||||
|
int moduleEntityPhysicsShapeToString(lua_State *L);
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "moduleentityposition.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "entity/component/display/entityposition.h"
|
||||||
|
|
||||||
|
void moduleEntityPosition(scriptcontext_t *ctx) {
|
||||||
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
|
lua_State *l = ctx->luaState;
|
||||||
|
|
||||||
|
lua_register(l, "entityPositionGetPosition", moduleEntityPositionGetPosition);
|
||||||
|
lua_register(l, "entityPositionSetPosition", moduleEntityPositionSetPosition);
|
||||||
|
lua_register(l, "entityPositionGetRotation", moduleEntityPositionGetRotation);
|
||||||
|
lua_register(l, "entityPositionSetRotation", moduleEntityPositionSetRotation);
|
||||||
|
lua_register(l, "entityPositionGetScale", moduleEntityPositionGetScale);
|
||||||
|
lua_register(l, "entityPositionSetScale", moduleEntityPositionSetScale);
|
||||||
|
lua_register(l, "entityPositionLookAt", moduleEntityPositionLookAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPositionGetPosition(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPositionGetPosition: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPositionGetPosition: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
|
||||||
|
vec3 *v = (vec3 *)lua_newuserdata(L, sizeof(vec3));
|
||||||
|
memoryZero(v, sizeof(vec3));
|
||||||
|
entityPositionGetPosition(eid, cid, *v);
|
||||||
|
luaL_getmetatable(L, "vec3_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPositionSetPosition(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPositionSetPosition: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPositionSetPosition: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
vec3 *v = (vec3 *)luaL_checkudata(L, 3, "vec3_mt");
|
||||||
|
entityPositionSetPosition(eid, cid, *v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPositionGetRotation(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPositionGetRotation: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPositionGetRotation: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
|
||||||
|
vec3 *v = (vec3 *)lua_newuserdata(L, sizeof(vec3));
|
||||||
|
memoryZero(v, sizeof(vec3));
|
||||||
|
entityPositionGetRotation(eid, cid, *v);
|
||||||
|
luaL_getmetatable(L, "vec3_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPositionSetRotation(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPositionSetRotation: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPositionSetRotation: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
vec3 *v = (vec3 *)luaL_checkudata(L, 3, "vec3_mt");
|
||||||
|
entityPositionSetRotation(eid, cid, *v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPositionGetScale(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPositionGetScale: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPositionGetScale: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
|
||||||
|
vec3 *v = (vec3 *)lua_newuserdata(L, sizeof(vec3));
|
||||||
|
memoryZero(v, sizeof(vec3));
|
||||||
|
entityPositionGetScale(eid, cid, *v);
|
||||||
|
luaL_getmetatable(L, "vec3_mt");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPositionSetScale(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPositionSetScale: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPositionSetScale: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
vec3 *v = (vec3 *)luaL_checkudata(L, 3, "vec3_mt");
|
||||||
|
entityPositionSetScale(eid, cid, *v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityPositionLookAt(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityPositionLookAt: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityPositionLookAt: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
vec3 *target = (vec3 *)luaL_checkudata(L, 3, "vec3_mt");
|
||||||
|
vec3 *up = (vec3 *)luaL_checkudata(L, 4, "vec3_mt");
|
||||||
|
vec3 *eye = (vec3 *)luaL_checkudata(L, 5, "vec3_mt");
|
||||||
|
entityPositionLookAt(eid, cid, *target, *up, *eye);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the entityposition module within the given script context.
|
||||||
|
* Provides get/set functions for position, rotation, scale, and lookAt.
|
||||||
|
*
|
||||||
|
* @param ctx The script context to register the module in.
|
||||||
|
*/
|
||||||
|
void moduleEntityPosition(scriptcontext_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityPositionGetPosition(entityId, componentId) -> vec3
|
||||||
|
*/
|
||||||
|
int moduleEntityPositionGetPosition(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityPositionSetPosition(entityId, componentId, vec3)
|
||||||
|
*/
|
||||||
|
int moduleEntityPositionSetPosition(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityPositionGetRotation(entityId, componentId) -> vec3 (radians)
|
||||||
|
*/
|
||||||
|
int moduleEntityPositionGetRotation(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityPositionSetRotation(entityId, componentId, vec3) (radians)
|
||||||
|
*/
|
||||||
|
int moduleEntityPositionSetRotation(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityPositionGetScale(entityId, componentId) -> vec3
|
||||||
|
*/
|
||||||
|
int moduleEntityPositionGetScale(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityPositionSetScale(entityId, componentId, vec3)
|
||||||
|
*/
|
||||||
|
int moduleEntityPositionSetScale(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityPositionLookAt(entityId, componentId, target, up, eye)
|
||||||
|
* All vec3 arguments.
|
||||||
|
*/
|
||||||
|
int moduleEntityPositionLookAt(lua_State *L);
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "moduleentityscript.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "error/error.h"
|
||||||
|
#include "entity/component/script/entityscript.h"
|
||||||
|
|
||||||
|
void moduleEntityScript(scriptcontext_t *ctx) {
|
||||||
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
|
lua_State *l = ctx->luaState;
|
||||||
|
lua_register(l, "entityScriptExec", moduleEntityScriptExec);
|
||||||
|
lua_register(l, "entityScriptExecAsset", moduleEntityScriptExecAsset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityScriptExec(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityScriptExec: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityScriptExec: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isstring(L, 3)) {
|
||||||
|
luaL_error(L, "entityScriptExec: script must be a string");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
const char_t *script = lua_tostring(L, 3);
|
||||||
|
|
||||||
|
errorret_t ret = entityScriptExec(eid, cid, script);
|
||||||
|
if(ret.code != ERROR_OK) {
|
||||||
|
errorCatch(errorPrint(ret));
|
||||||
|
luaL_error(L, "entityScriptExec failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleEntityScriptExecAsset(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
luaL_error(L, "entityScriptExecAsset: entityId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
luaL_error(L, "entityScriptExecAsset: componentId must be a number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!lua_isstring(L, 3)) {
|
||||||
|
luaL_error(L, "entityScriptExecAsset: assetName must be a string");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityid_t eid = (entityid_t)lua_tonumber(L, 1);
|
||||||
|
componentid_t cid = (componentid_t)lua_tonumber(L, 2);
|
||||||
|
const char_t *assetName = lua_tostring(L, 3);
|
||||||
|
|
||||||
|
errorret_t ret = entityScriptExecAsset(eid, cid, assetName);
|
||||||
|
if(ret.code != ERROR_OK) {
|
||||||
|
errorCatch(errorPrint(ret));
|
||||||
|
luaL_error(L, "entityScriptExecAsset failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the entityscript module within the given script context.
|
||||||
|
* Provides functions to execute Lua code on another entity's script component.
|
||||||
|
*
|
||||||
|
* @param ctx The script context to register the module in.
|
||||||
|
*/
|
||||||
|
void moduleEntityScript(scriptcontext_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityScriptExec(entityId, componentId, scriptString)
|
||||||
|
* Executes an inline Lua string on the target entity's script component.
|
||||||
|
*/
|
||||||
|
int moduleEntityScriptExec(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua binding: entityScriptExecAsset(entityId, componentId, assetName)
|
||||||
|
* Executes a Lua script file from assets on the target entity's script component.
|
||||||
|
*/
|
||||||
|
int moduleEntityScriptExecAsset(lua_State *L);
|
||||||
@@ -22,6 +22,13 @@
|
|||||||
#include "script/module/display/modulescreen.h"
|
#include "script/module/display/modulescreen.h"
|
||||||
#include "script/module/display/moduletexture.h"
|
#include "script/module/display/moduletexture.h"
|
||||||
#include "script/module/display/moduletileset.h"
|
#include "script/module/display/moduletileset.h"
|
||||||
|
#include "script/module/entity/moduleentity.h"
|
||||||
|
#include "script/module/entity/moduleentityposition.h"
|
||||||
|
#include "script/module/entity/moduleentitycamera.h"
|
||||||
|
#include "script/module/entity/moduleentitymesh.h"
|
||||||
|
#include "script/module/entity/moduleentitymaterial.h"
|
||||||
|
#include "script/module/entity/moduleentityphysics.h"
|
||||||
|
#include "script/module/entity/moduleentityscript.h"
|
||||||
#include "script/scriptgame.h"
|
#include "script/scriptgame.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
|
||||||
@@ -42,6 +49,13 @@ const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
|||||||
{ .name = "texture", .callback = moduleTexture },
|
{ .name = "texture", .callback = moduleTexture },
|
||||||
{ .name = "tileset", .callback = moduleTileset },
|
{ .name = "tileset", .callback = moduleTileset },
|
||||||
{ .name = "shader", .callback = moduleShader },
|
{ .name = "shader", .callback = moduleShader },
|
||||||
|
{ .name = "entity", .callback = moduleEntity },
|
||||||
|
{ .name = "entityposition", .callback = moduleEntityPosition },
|
||||||
|
{ .name = "entitycamera", .callback = moduleEntityCamera },
|
||||||
|
{ .name = "entitymesh", .callback = moduleEntityMesh },
|
||||||
|
{ .name = "entitymaterial", .callback = moduleEntityMaterial },
|
||||||
|
{ .name = "entityphysics", .callback = moduleEntityPhysics },
|
||||||
|
{ .name = "entityscript", .callback = moduleEntityScript },
|
||||||
|
|
||||||
#ifdef SCRIPT_GAME_LIST
|
#ifdef SCRIPT_GAME_LIST
|
||||||
SCRIPT_GAME_LIST
|
SCRIPT_GAME_LIST
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
system.c
|
|
||||||
)
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "system.h"
|
|
||||||
#include "system/systemplatform.h"
|
|
||||||
|
|
||||||
#ifndef systemGetActiveDialogTypePlatform
|
|
||||||
#error "systemGetActiveDialogTypePlatform is not defined"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef systemInitPlatform
|
|
||||||
#error "systemInitPlatform is not defined"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
errorret_t systemInit() {
|
|
||||||
return systemInitPlatform();
|
|
||||||
}
|
|
||||||
|
|
||||||
systemdialogtype_t systemGetActiveDialogType() {
|
|
||||||
return systemGetActiveDialogTypePlatform();
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "error/error.h"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SYSTEM_DIALOG_TYPE_NONE,
|
|
||||||
SYSTEM_DIALOG_TYPE_RENDER_BLOCKING,
|
|
||||||
SYSTEM_DIALOG_TYPE_TICK_BLOCKING
|
|
||||||
} systemdialogtype_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the system module. This is called really early in the init
|
|
||||||
* process of the engine.
|
|
||||||
*
|
|
||||||
* @return Error code indicating success or failure.
|
|
||||||
*/
|
|
||||||
errorret_t systemInit(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basically this is only used on a few system types, it is to ask the plaform,
|
|
||||||
* e.g. PSP "What dialog is currently open?" and then the engine will change the
|
|
||||||
* behavior of the main loop to accomodate.
|
|
||||||
*
|
|
||||||
* For example, PSP can show dialogs for things like, save files, wifi, system
|
|
||||||
* information, etc. When these are open, the engine really can't do much and
|
|
||||||
* the system needs to finish processing.
|
|
||||||
*
|
|
||||||
* For most systems this will go unused.
|
|
||||||
*
|
|
||||||
* @return Dialog type currently open.
|
|
||||||
*/
|
|
||||||
systemdialogtype_t systemGetActiveDialogType();
|
|
||||||
@@ -18,6 +18,4 @@ target_sources(${DUSK_BINARY_TARGET_NAME}
|
|||||||
add_subdirectory(asset)
|
add_subdirectory(asset)
|
||||||
add_subdirectory(log)
|
add_subdirectory(log)
|
||||||
add_subdirectory(display)
|
add_subdirectory(display)
|
||||||
add_subdirectory(input)
|
add_subdirectory(input)
|
||||||
add_subdirectory(network)
|
|
||||||
add_subdirectory(system)
|
|
||||||
@@ -76,7 +76,7 @@ errorret_t displayInitDolphin(void) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Setup cull modes
|
// Setup cull modes
|
||||||
GX_SetCullMode(GX_CULL_NONE);
|
GX_SetCullMode(GX_CULL_BACK);
|
||||||
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
|
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
|
||||||
GX_SetZMode(GX_TRUE, GX_ALWAYS, GX_FALSE);
|
GX_SetZMode(GX_TRUE, GX_ALWAYS, GX_FALSE);
|
||||||
GX_SetDispCopyGamma(GX_GM_1_0);
|
GX_SetDispCopyGamma(GX_GM_1_0);
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include "display/framebuffer/framebuffer.h"
|
#include "display/framebuffer/framebuffer.h"
|
||||||
#include "display/display.h"
|
#include "display/display.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "system/systemdolphin.h"
|
|
||||||
|
|
||||||
errorret_t frameBufferInitBackBufferDolphin(void) {
|
errorret_t frameBufferInitBackBufferDolphin(void) {
|
||||||
errorOk();
|
errorOk();
|
||||||
@@ -16,27 +15,14 @@ errorret_t frameBufferInitBackBufferDolphin(void) {
|
|||||||
|
|
||||||
uint32_t frameBufferGetWidthDolphin(const framebufferdolphin_t *framebuffer) {
|
uint32_t frameBufferGetWidthDolphin(const framebufferdolphin_t *framebuffer) {
|
||||||
assertNotNull(framebuffer, "Cannot get width of NULL framebuffer.");
|
assertNotNull(framebuffer, "Cannot get width of NULL framebuffer.");
|
||||||
|
|
||||||
return DISPLAY.screenMode->fbWidth;
|
return DISPLAY.screenMode->fbWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t frameBufferGetHeightDolphin(const framebufferdolphin_t *framebuffer) {
|
uint32_t frameBufferGetHeightDolphin(const framebufferdolphin_t *framebuffer) {
|
||||||
assertNotNull(framebuffer, "Cannot get height of NULL framebuffer.");
|
assertNotNull(framebuffer, "Cannot get height of NULL framebuffer.");
|
||||||
return DISPLAY.screenMode->efbHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
float_t frameBufferGetAspectDolphin(const framebufferdolphin_t *framebuffer) {
|
return DISPLAY.screenMode->efbHeight;
|
||||||
assertNotNull(framebuffer, "Cannot get aspect of NULL framebuffer.");
|
|
||||||
switch(systemGetAspectRatioDolphin()) {
|
|
||||||
case CONF_ASPECT_16_9:
|
|
||||||
return 16.0f / 9.0f;
|
|
||||||
case CONF_ASPECT_4_3:
|
|
||||||
return 4.0f / 3.0f;
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
(float_t)DISPLAY.screenMode->fbWidth /
|
|
||||||
(float_t)DISPLAY.screenMode->efbHeight
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t frameBufferBindDolphin(framebufferdolphin_t *framebuffer) {
|
errorret_t frameBufferBindDolphin(framebufferdolphin_t *framebuffer) {
|
||||||
|
|||||||
@@ -38,15 +38,6 @@ uint32_t frameBufferGetWidthDolphin(const framebufferdolphin_t *framebuffer);
|
|||||||
*/
|
*/
|
||||||
uint32_t frameBufferGetHeightDolphin(const framebufferdolphin_t *framebuffer);
|
uint32_t frameBufferGetHeightDolphin(const framebufferdolphin_t *framebuffer);
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the aspect ratio of the framebuffer. (Dolphin implementation). Taking
|
|
||||||
* the Wii aspect setting into consideration.
|
|
||||||
*
|
|
||||||
* @param framebuffer The framebuffer to get the aspect ratio of.
|
|
||||||
* @return The aspect ratio of the framebuffer.
|
|
||||||
*/
|
|
||||||
float_t frameBufferGetAspectDolphin(const framebufferdolphin_t *framebuffer);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds the framebuffer for rendering. (Dolphin implementation).
|
* Binds the framebuffer for rendering. (Dolphin implementation).
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -13,6 +13,5 @@ typedef framebufferdolphin_t framebufferplatform_t;
|
|||||||
#define frameBufferPlatformInitBackBuffer frameBufferInitBackBufferDolphin
|
#define frameBufferPlatformInitBackBuffer frameBufferInitBackBufferDolphin
|
||||||
#define frameBufferPlatformGetWidth frameBufferGetWidthDolphin
|
#define frameBufferPlatformGetWidth frameBufferGetWidthDolphin
|
||||||
#define frameBufferPlatformGetHeight frameBufferGetHeightDolphin
|
#define frameBufferPlatformGetHeight frameBufferGetHeightDolphin
|
||||||
#define frameBufferPlatformGetAspect frameBufferGetAspectDolphin
|
|
||||||
#define frameBufferPlatformBind frameBufferBindDolphin
|
#define frameBufferPlatformBind frameBufferBindDolphin
|
||||||
#define frameBufferPlatformClear frameBufferClearDolphin
|
#define frameBufferPlatformClear frameBufferClearDolphin
|
||||||
@@ -52,7 +52,6 @@ errorret_t meshDrawDolphin(
|
|||||||
assertTrue(offsetof(meshvertex_t, pos) == 8, "pos offset wrong");
|
assertTrue(offsetof(meshvertex_t, pos) == 8, "pos offset wrong");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Flush vertex data to GPU. This is required before drawing with GX.
|
|
||||||
DCFlushRange(
|
DCFlushRange(
|
||||||
(void*)&mesh->vertices[vertexOffset],
|
(void*)&mesh->vertices[vertexOffset],
|
||||||
sizeof(meshvertex_t) * vertexCount
|
sizeof(meshvertex_t) * vertexCount
|
||||||
|
|||||||
@@ -43,10 +43,10 @@ errorret_t shaderBindDolphin(shaderdolphin_t *shader) {
|
|||||||
|
|
||||||
|
|
||||||
GX_LoadProjectionMtx(
|
GX_LoadProjectionMtx(
|
||||||
shader->dolphinProj,
|
shader->matrixProjection,
|
||||||
shader->isProjectionPerspective ? GX_PERSPECTIVE : GX_ORTHOGRAPHIC
|
shader->isProjectionPerspective ? GX_PERSPECTIVE : GX_ORTHOGRAPHIC
|
||||||
);
|
);
|
||||||
GX_LoadPosMtxImm(shader->dolphinModelView, GX_PNMTX0);
|
GX_LoadPosMtxImm(shader->matrixModelView, GX_PNMTX0);
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
@@ -193,13 +193,13 @@ errorret_t shaderUpdateMVPDolphin() {
|
|||||||
|
|
||||||
// Need to update projection?
|
// Need to update projection?
|
||||||
if((SHADER_BOUND->dirtyMatrix & SHADER_DOLPHIN_DIRTY_PROJ) != 0) {
|
if((SHADER_BOUND->dirtyMatrix & SHADER_DOLPHIN_DIRTY_PROJ) != 0) {
|
||||||
shaderMat4ToMtx44(SHADER_BOUND->proj, SHADER_BOUND->dolphinProj);
|
shaderMat4ToMtx44(SHADER_BOUND->proj, SHADER_BOUND->matrixProjection);
|
||||||
|
|
||||||
// Fix projection Z mapping between GLM and GX.
|
// Fix projection Z mapping between GLM and GX.
|
||||||
float A = SHADER_BOUND->dolphinProj[2][2];
|
float A = SHADER_BOUND->matrixProjection[2][2];
|
||||||
float B = SHADER_BOUND->dolphinProj[2][3];
|
float B = SHADER_BOUND->matrixProjection[2][3];
|
||||||
SHADER_BOUND->dolphinProj[2][2] = 0.5f * (A + 1.0f);
|
SHADER_BOUND->matrixProjection[2][2] = 0.5f * (A + 1.0f);
|
||||||
SHADER_BOUND->dolphinProj[2][3] = 0.5f * B;
|
SHADER_BOUND->matrixProjection[2][3] = 0.5f * B;
|
||||||
|
|
||||||
// Is this perspective or ortho originally? Dolphin cares for some reason.
|
// Is this perspective or ortho originally? Dolphin cares for some reason.
|
||||||
const float_t epsilon = 0.0001f;
|
const float_t epsilon = 0.0001f;
|
||||||
@@ -209,7 +209,7 @@ errorret_t shaderUpdateMVPDolphin() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
GX_LoadProjectionMtx(
|
GX_LoadProjectionMtx(
|
||||||
SHADER_BOUND->dolphinProj,
|
SHADER_BOUND->matrixProjection,
|
||||||
SHADER_BOUND->isProjectionPerspective ? GX_PERSPECTIVE : GX_ORTHOGRAPHIC
|
SHADER_BOUND->isProjectionPerspective ? GX_PERSPECTIVE : GX_ORTHOGRAPHIC
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -217,18 +217,23 @@ errorret_t shaderUpdateMVPDolphin() {
|
|||||||
// Need to update view or model?
|
// Need to update view or model?
|
||||||
bool_t mvDirt = false;
|
bool_t mvDirt = false;
|
||||||
if((SHADER_BOUND->dirtyMatrix & SHADER_DOLPHIN_DIRTY_VIEW) != 0) {
|
if((SHADER_BOUND->dirtyMatrix & SHADER_DOLPHIN_DIRTY_VIEW) != 0) {
|
||||||
|
shaderMat4ToMtx(SHADER_BOUND->view, SHADER_BOUND->matrixView);
|
||||||
mvDirt = true;
|
mvDirt = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((SHADER_BOUND->dirtyMatrix & SHADER_DOLPHIN_DIRTY_MODEL) != 0) {
|
if((SHADER_BOUND->dirtyMatrix & SHADER_DOLPHIN_DIRTY_MODEL) != 0) {
|
||||||
|
shaderMat4ToMtx(SHADER_BOUND->model, SHADER_BOUND->matrixModel);
|
||||||
mvDirt = true;
|
mvDirt = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Model/View Matrix
|
// Set Model/View Matrix
|
||||||
if(mvDirt) {
|
if(mvDirt) {
|
||||||
glm_mat4_mul(SHADER_BOUND->view, SHADER_BOUND->model, SHADER_BOUND->modelView);
|
guMtxConcat(
|
||||||
shaderMat4ToMtx(SHADER_BOUND->modelView, SHADER_BOUND->dolphinModelView);
|
SHADER_BOUND->matrixView,
|
||||||
GX_LoadPosMtxImm(SHADER_BOUND->dolphinModelView, GX_PNMTX0);
|
SHADER_BOUND->matrixModel,
|
||||||
|
SHADER_BOUND->matrixModelView
|
||||||
|
);
|
||||||
|
GX_LoadPosMtxImm(SHADER_BOUND->matrixModelView, GX_PNMTX0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHADER_BOUND->dirtyMatrix = 0;
|
SHADER_BOUND->dirtyMatrix = 0;
|
||||||
@@ -250,8 +255,6 @@ void shaderMat4ToMtx(const mat4 inGlmMatrix, Mtx outGXMatrix) {
|
|||||||
assertNotNull(inGlmMatrix, "Input matrix cannot be null");
|
assertNotNull(inGlmMatrix, "Input matrix cannot be null");
|
||||||
assertNotNull(outGXMatrix, "Output matrix cannot be null");
|
assertNotNull(outGXMatrix, "Output matrix cannot be null");
|
||||||
|
|
||||||
guMtxIdentity(outGXMatrix);
|
|
||||||
|
|
||||||
for(int row = 0; row < 3; ++row) {
|
for(int row = 0; row < 3; ++row) {
|
||||||
for(int col = 0; col < 4; ++col) {
|
for(int col = 0; col < 4; ++col) {
|
||||||
outGXMatrix[row][col] = inGlmMatrix[col][row];
|
outGXMatrix[row][col] = inGlmMatrix[col][row];
|
||||||
|
|||||||
@@ -24,12 +24,13 @@ typedef struct shaderdolphin_s {
|
|||||||
mat4 view;
|
mat4 view;
|
||||||
mat4 proj;
|
mat4 proj;
|
||||||
mat4 model;
|
mat4 model;
|
||||||
mat4 modelView;
|
|
||||||
|
|
||||||
Mtx dolphinProj;
|
|
||||||
Mtx dolphinModelView;
|
|
||||||
|
|
||||||
bool_t isProjectionPerspective;
|
bool_t isProjectionPerspective;
|
||||||
|
Mtx44 matrixProjection;
|
||||||
|
Mtx matrixView;
|
||||||
|
Mtx matrixModel;
|
||||||
|
Mtx matrixModelView;
|
||||||
|
|
||||||
uint_fast8_t dirtyMatrix;
|
uint_fast8_t dirtyMatrix;
|
||||||
} shaderdolphin_t;
|
} shaderdolphin_t;
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
#ifdef DUSK_GAMECUBE
|
|
||||||
#define CONF_ASPECT_4_3 0
|
|
||||||
#define CONF_ASPECT_16_9 1
|
|
||||||
#define CONF_GetAspectRatio() CONF_ASPECT_4_3
|
|
||||||
|
|
||||||
#define CONF_GetLanguage() SYS_GetLanguage()
|
|
||||||
#endif
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
networkdolphin.c
|
|
||||||
)
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
// /**
|
|
||||||
// * Copyright (c) 2026 Dominic Masters
|
|
||||||
// *
|
|
||||||
// * This software is released under the MIT License.
|
|
||||||
// * https://opensource.org/licenses/MIT
|
|
||||||
// */
|
|
||||||
|
|
||||||
#include "network/network.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
|
|
||||||
errorret_t networkDolphinInit() {
|
|
||||||
// s32 ret = net_init();
|
|
||||||
// if(ret < 0) errorThrow("Failed to init network stack: %d", ret);
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t networkDolphinUpdate() {
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t networkDolphinDispose() {
|
|
||||||
// #ifdef DUSK_WII
|
|
||||||
// net_deinit();
|
|
||||||
// #endif
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool_t networkDolphinIsConnected() {
|
|
||||||
return NETWORK.state == NETWORK_STATE_CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void networkDolphinRequestConnection(
|
|
||||||
void (*onConnected)(void *user),
|
|
||||||
void (*onFailed)(errorret_t error, void *user),
|
|
||||||
void (*onDisconnect)(errorret_t error, void *user),
|
|
||||||
void *user
|
|
||||||
) {
|
|
||||||
assertTrue(
|
|
||||||
NETWORK.state == NETWORK_STATE_CONNECTING,
|
|
||||||
"Network host should be in a connecting state."
|
|
||||||
);
|
|
||||||
|
|
||||||
NETWORK.platform.onConnected = onConnected;
|
|
||||||
NETWORK.platform.onFailed = onFailed;
|
|
||||||
NETWORK.platform.onConnectedUser = user;
|
|
||||||
|
|
||||||
memoryZero(NETWORK.platform.ip, sizeof(NETWORK.platform.ip));
|
|
||||||
memoryZero(NETWORK.platform.netmask, sizeof(NETWORK.platform.netmask));
|
|
||||||
memoryZero(NETWORK.platform.gateway, sizeof(NETWORK.platform.gateway));
|
|
||||||
|
|
||||||
// Negotiate DHCP using the Wi-Fi settings saved in Wii System Menu.
|
|
||||||
// This call blocks until the interface is configured or times out.
|
|
||||||
#ifdef DUSK_WII
|
|
||||||
s32 ret = if_config(
|
|
||||||
NETWORK.platform.ip,
|
|
||||||
NETWORK.platform.netmask,
|
|
||||||
NETWORK.platform.gateway,
|
|
||||||
true,
|
|
||||||
20
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
s32 ret = -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(ret >= 0) {
|
|
||||||
NETWORK.state = NETWORK_STATE_CONNECTED;
|
|
||||||
assertNotNull(
|
|
||||||
NETWORK.platform.onConnected,
|
|
||||||
"Network platform onConnected callback should be set."
|
|
||||||
);
|
|
||||||
NETWORK.platform.onConnected(NETWORK.platform.onConnectedUser);
|
|
||||||
} else {
|
|
||||||
NETWORK.state = NETWORK_STATE_DISCONNECTED;
|
|
||||||
assertNotNull(
|
|
||||||
NETWORK.platform.onFailed,
|
|
||||||
"Network platform onFailed callback should be set."
|
|
||||||
);
|
|
||||||
errorret_t error = errorThrowImpl(
|
|
||||||
&NETWORK.errorState,
|
|
||||||
ERROR_NOT_OK,
|
|
||||||
__FILE__, __func__, __LINE__,
|
|
||||||
"Failed to connect to network"
|
|
||||||
);
|
|
||||||
NETWORK.platform.onFailed(error, NETWORK.platform.onConnectedUser);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void networkDolphinRequestDisconnection(
|
|
||||||
void (*onComplete)(void *user),
|
|
||||||
void *user
|
|
||||||
) {
|
|
||||||
assertTrue(
|
|
||||||
NETWORK.state == NETWORK_STATE_DISCONNECTING,
|
|
||||||
"Network host should be in a disconnecting state."
|
|
||||||
);
|
|
||||||
|
|
||||||
NETWORK.state = NETWORK_STATE_DISCONNECTED;
|
|
||||||
onComplete(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
networkinfo_t networkDolphinGetInfo() {
|
|
||||||
networkinfo_t info;
|
|
||||||
memoryZero(&info, sizeof(networkinfo_t));
|
|
||||||
|
|
||||||
info.type = NETWORK_TYPE_IPV4;
|
|
||||||
int ret = sscanf(
|
|
||||||
NETWORK.platform.ip,
|
|
||||||
"%hhu.%hhu.%hhu.%hhu",
|
|
||||||
&info.ipv4.ip[0],
|
|
||||||
&info.ipv4.ip[1],
|
|
||||||
&info.ipv4.ip[2],
|
|
||||||
&info.ipv4.ip[3]
|
|
||||||
);
|
|
||||||
assertTrue(ret == 4, "Failed to parse IP address");
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "error/error.h"
|
|
||||||
#include "network/networkinfo.h"
|
|
||||||
#include <network.h>
|
|
||||||
|
|
||||||
#define NETWORK_DOLPHIN_IP_MAX 16
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char_t ip[NETWORK_DOLPHIN_IP_MAX];
|
|
||||||
char_t netmask[NETWORK_DOLPHIN_IP_MAX];
|
|
||||||
char_t gateway[NETWORK_DOLPHIN_IP_MAX];
|
|
||||||
|
|
||||||
void *onConnectedUser;
|
|
||||||
void (*onConnected)(void *user);
|
|
||||||
void (*onFailed)(errorret_t error, void *user);
|
|
||||||
} networkdolphin_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the Wii network stack via IOS. Does not connect; use
|
|
||||||
* networkDolphinRequestConnection for that.
|
|
||||||
*
|
|
||||||
* @return Error state (if any).
|
|
||||||
*/
|
|
||||||
errorret_t networkDolphinInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called each frame. No-op on Wii since connection is synchronous.
|
|
||||||
*
|
|
||||||
* @return Error state (if any).
|
|
||||||
*/
|
|
||||||
errorret_t networkDolphinUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes the Wii network stack.
|
|
||||||
*
|
|
||||||
* @return Error state (if any).
|
|
||||||
*/
|
|
||||||
errorret_t networkDolphinDispose();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the Wii is connected to a network.
|
|
||||||
*
|
|
||||||
* @return True if connected.
|
|
||||||
*/
|
|
||||||
bool_t networkDolphinIsConnected();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests the Wii to connect to the network using the Wi-Fi settings saved
|
|
||||||
* in the Wii System Menu. Blocks until connected or failed.
|
|
||||||
*
|
|
||||||
* @param onConnected Callback on successful connection.
|
|
||||||
* @param onFailed Callback if connection fails.
|
|
||||||
* @param onDisconnect Callback when connection is later lost.
|
|
||||||
* @param user User data passed to all callbacks.
|
|
||||||
*/
|
|
||||||
void networkDolphinRequestConnection(
|
|
||||||
void (*onConnected)(void *user),
|
|
||||||
void (*onFailed)(errorret_t error, void *user),
|
|
||||||
void (*onDisconnect)(errorret_t error, void *user),
|
|
||||||
void *user
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests the Wii to disconnect from the network.
|
|
||||||
*
|
|
||||||
* @param onComplete Callback when disconnection is complete.
|
|
||||||
* @param user User data passed to the callback.
|
|
||||||
*/
|
|
||||||
void networkDolphinRequestDisconnection(
|
|
||||||
void (*onComplete)(void *user),
|
|
||||||
void *user
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current network IP information.
|
|
||||||
*
|
|
||||||
* @return Network info for the active connection.
|
|
||||||
*/
|
|
||||||
networkinfo_t networkDolphinGetInfo();
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "networkdolphin.h"
|
|
||||||
|
|
||||||
#define networkPlatformInit networkDolphinInit
|
|
||||||
#define networkPlatformUpdate networkDolphinUpdate
|
|
||||||
#define networkPlatformDispose networkDolphinDispose
|
|
||||||
#define networkPlatformIsConnected networkDolphinIsConnected
|
|
||||||
#define networkPlatformRequestConnection networkDolphinRequestConnection
|
|
||||||
#define networkPlatformRequestDisconnection networkDolphinRequestDisconnection
|
|
||||||
#define networkPlatformGetInfo networkDolphinGetInfo
|
|
||||||
|
|
||||||
typedef networkdolphin_t networkplatform_t;
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
systemdolphin.c
|
|
||||||
)
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "systemdolphin.h"
|
|
||||||
#include "input/input.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
|
|
||||||
errorret_t systemInitDolphin(void) {
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
systemdialogtype_t systemGetActiveDialogTypeDolphin(void) {
|
|
||||||
return SYSTEM_DIALOG_TYPE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t systemGetAspectRatioDolphin(void) {
|
|
||||||
return CONF_GetAspectRatio();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t systemGetLanguageDolphin(void) {
|
|
||||||
return CONF_GetLanguage();
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "system/system.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the Dolphin system module.
|
|
||||||
*
|
|
||||||
* @return Error code indicating success or failure.
|
|
||||||
*/
|
|
||||||
errorret_t systemInitDolphin(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns which Dolphin system dialog is currently open (if any).
|
|
||||||
*
|
|
||||||
* @return Currently open system dialog type.
|
|
||||||
*/
|
|
||||||
systemdialogtype_t systemGetActiveDialogTypeDolphin(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns either CONF_ASPECT_4_3 or CONF_ASPECT_16_9 depending on the aspect
|
|
||||||
* ratio of the system. I do believe that Gamecube will only ever return 4:3.
|
|
||||||
*
|
|
||||||
* Refer to;
|
|
||||||
* https://github.com/devkitPro/libogc/blob/20d90e944b83c8991538e88b00b1e5f309428e85/gc/ogc/conf.h#L190
|
|
||||||
*
|
|
||||||
* @return Aspect ratio of the system.
|
|
||||||
*/
|
|
||||||
int32_t systemGetAspectRatioDolphin(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the language the system is set to. This is used for things like
|
|
||||||
* locale management, to try to match the system language if possible.
|
|
||||||
*
|
|
||||||
* Refer to;
|
|
||||||
* https://github.com/devkitPro/libogc/blob/20d90e944b83c8991538e88b00b1e5f309428e85/gc/ogc/conf.h#L190
|
|
||||||
*
|
|
||||||
* On gamecube, refer to;
|
|
||||||
* https://libogc.devkitpro.org/system_8h.html
|
|
||||||
*
|
|
||||||
* @return System language.
|
|
||||||
*/
|
|
||||||
int32_t systemGetLanguageDolphin(void);
|
|
||||||
|
|
||||||
// There's actually a tonne more things Wii can return, this is it for now
|
|
||||||
// though.
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "system/systemdolphin.h"
|
|
||||||
|
|
||||||
#define systemInitPlatform systemInitDolphin
|
|
||||||
#define systemGetActiveDialogTypePlatform systemGetActiveDialogTypeDolphin
|
|
||||||
+3
-8
@@ -19,12 +19,7 @@
|
|||||||
#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0
|
#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0
|
||||||
#define glClearDepth(depth) glClearDepthf(depth)
|
#define glClearDepth(depth) glClearDepthf(depth)
|
||||||
#else
|
#else
|
||||||
// For some platforms (Vita) we do not include GL extensions.
|
#define GL_GLEXT_PROTOTYPES
|
||||||
#ifndef GL_GLEXT_PROTOTYPES
|
#include <GL/gl.h>
|
||||||
#define GL_GLEXT_PROTOTYPES
|
#include <GL/glext.h>
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <GL/glext.h>
|
|
||||||
#else
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
@@ -12,6 +12,4 @@ target_include_directories(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
# Subdirs
|
# Subdirs
|
||||||
add_subdirectory(asset)
|
add_subdirectory(asset)
|
||||||
add_subdirectory(log)
|
add_subdirectory(log)
|
||||||
add_subdirectory(input)
|
add_subdirectory(input)
|
||||||
add_subdirectory(network)
|
|
||||||
add_subdirectory(system)
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
networklinux.c
|
|
||||||
)
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "networklinux.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
|
|
||||||
errorret_t networkLinuxInit() {
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t networkLinuxUpdate() {
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool_t networkLinuxIsConnected() {
|
|
||||||
// Call the OS network stack to check for connectivity.
|
|
||||||
struct ifaddrs *ifaddr, *ifa;
|
|
||||||
if(getifaddrs(&ifaddr) == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if any non loopback interfaces have running flag set.
|
|
||||||
bool_t connected = false;
|
|
||||||
for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
|
||||||
if (!ifa->ifa_name || !ifa->ifa_flags) continue;
|
|
||||||
|
|
||||||
// Skip loopback (localhost)
|
|
||||||
if(ifa->ifa_flags & IFF_LOOPBACK) continue;
|
|
||||||
|
|
||||||
// Is interface up and running?
|
|
||||||
if(!(ifa->ifa_flags & IFF_UP)) continue;
|
|
||||||
if(!(ifa->ifa_flags & IFF_RUNNING)) continue;
|
|
||||||
|
|
||||||
connected = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the linked list of interfaces
|
|
||||||
freeifaddrs(ifaddr);
|
|
||||||
|
|
||||||
return connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t networkLinuxDispose() {
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
networkinfo_t networkLinuxGetInfo() {
|
|
||||||
networkinfo_t info;
|
|
||||||
memset(&info, 0, sizeof(networkinfo_t));
|
|
||||||
|
|
||||||
bool_t found = false;
|
|
||||||
|
|
||||||
struct ifaddrs *ifaddr, *ifa;
|
|
||||||
if(getifaddrs(&ifaddr) == -1) {
|
|
||||||
assertUnreachable("getifaddrs failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the first non-loopback interface with an IP address
|
|
||||||
for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
|
||||||
if (!ifa->ifa_name || !ifa->ifa_flags) continue;
|
|
||||||
|
|
||||||
// Skip loopback (localhost)
|
|
||||||
if(ifa->ifa_flags & IFF_LOOPBACK) continue;
|
|
||||||
|
|
||||||
// Is interface up and running?
|
|
||||||
if(!(ifa->ifa_flags & IFF_UP)) continue;
|
|
||||||
if(!(ifa->ifa_flags & IFF_RUNNING)) continue;
|
|
||||||
if(ifa->ifa_addr == NULL) continue;
|
|
||||||
|
|
||||||
// Check for IPv4 address
|
|
||||||
if(ifa->ifa_addr->sa_family == AF_INET) {
|
|
||||||
info.type = NETWORK_TYPE_IPV4;
|
|
||||||
|
|
||||||
struct sockaddr_in *sa = (struct sockaddr_in *)ifa->ifa_addr;
|
|
||||||
memoryCopy(
|
|
||||||
info.ipv4.ip,
|
|
||||||
&sa->sin_addr,
|
|
||||||
NETWORK_INFO_IPV4_OCTET_COUNT
|
|
||||||
);
|
|
||||||
|
|
||||||
found = true;
|
|
||||||
|
|
||||||
// sa = (struct sockaddr_in *)ifa->ifa_netmask;
|
|
||||||
// memoryCopy(
|
|
||||||
// info.ipv4.subnet,
|
|
||||||
// &sa->sin_addr,
|
|
||||||
// NETWORK_INFO_IPV4_OCTET_COUNT
|
|
||||||
// );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for IPv6 address
|
|
||||||
#ifdef DUSK_NETWORK_IPV6
|
|
||||||
if(ifa->ifa_addr->sa_family == AF_INET6) {
|
|
||||||
info.type = NETWORK_TYPE_IPV6;
|
|
||||||
|
|
||||||
struct sockaddr_in6 *sa = (struct sockaddr_in6 *)ifa->ifa_addr;
|
|
||||||
memoryCopy(
|
|
||||||
info.ipv6.ip,
|
|
||||||
&sa->sin6_addr,
|
|
||||||
NETWORK_INFO_IPV6_OCTET_COUNT
|
|
||||||
);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
freeifaddrs(ifaddr);
|
|
||||||
|
|
||||||
assertTrue(found, "No active network interface found?");
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "error/error.h"
|
|
||||||
#include "network/networkinfo.h"
|
|
||||||
#include <ifaddrs.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
void *nothing;
|
|
||||||
} networklinux_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the network manager. Must be called before any other network
|
|
||||||
* functions.
|
|
||||||
*
|
|
||||||
* @return Any error that occurs.
|
|
||||||
*/
|
|
||||||
errorret_t networkLinuxInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the network manager, called once per frame to handle completed
|
|
||||||
* HTTP requests.
|
|
||||||
*
|
|
||||||
* @return Any error that occurs.
|
|
||||||
*/
|
|
||||||
errorret_t networkLinuxUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true — Linux uses the OS network stack which is always available.
|
|
||||||
*
|
|
||||||
* @return true
|
|
||||||
*/
|
|
||||||
bool_t networkLinuxIsConnected();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes the network manager.
|
|
||||||
*
|
|
||||||
* @return Any error that occurs.
|
|
||||||
*/
|
|
||||||
errorret_t networkLinuxDispose();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the network information for the currently active network connection.
|
|
||||||
*
|
|
||||||
* @return Network information for the currently active network connection.
|
|
||||||
*/
|
|
||||||
networkinfo_t networkLinuxGetInfo();
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "networklinux.h"
|
|
||||||
|
|
||||||
#define networkPlatformInit networkLinuxInit
|
|
||||||
#define networkPlatformUpdate networkLinuxUpdate
|
|
||||||
#define networkPlatformDispose networkLinuxDispose
|
|
||||||
#define networkPlatformIsConnected networkLinuxIsConnected
|
|
||||||
#define networkPlatformGetInfo networkLinuxGetInfo
|
|
||||||
|
|
||||||
typedef networklinux_t networkplatform_t;
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
systemlinux.c
|
|
||||||
)
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "systemlinux.h"
|
|
||||||
|
|
||||||
errorret_t systemInitLinux() {
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
systemdialogtype_t systemGetActiveDialogTypeLinux() {
|
|
||||||
return SYSTEM_DIALOG_TYPE_NONE;
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "system/system.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the Linux system module.
|
|
||||||
*/
|
|
||||||
errorret_t systemInitLinux(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Currently just returns SYSTEM_DIALOG_TYPE_NONE.
|
|
||||||
*
|
|
||||||
* @return Currently open system dialog type.
|
|
||||||
*/
|
|
||||||
systemdialogtype_t systemGetActiveDialogTypeLinux();
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "system/systemlinux.h"
|
|
||||||
|
|
||||||
#define systemInitPlatform systemInitLinux
|
|
||||||
#define systemGetActiveDialogTypePlatform systemGetActiveDialogTypeLinux
|
|
||||||
@@ -17,6 +17,4 @@ target_sources(${DUSK_BINARY_TARGET_NAME}
|
|||||||
# Subdirs
|
# Subdirs
|
||||||
add_subdirectory(asset)
|
add_subdirectory(asset)
|
||||||
add_subdirectory(input)
|
add_subdirectory(input)
|
||||||
add_subdirectory(log)
|
add_subdirectory(log)
|
||||||
add_subdirectory(network)
|
|
||||||
add_subdirectory(system)
|
|
||||||
@@ -7,9 +7,6 @@
|
|||||||
|
|
||||||
#include "input/input.h"
|
#include "input/input.h"
|
||||||
|
|
||||||
// #define INPUT_PSP_GAMEPAD_BUTTON_ACCEPT INPUT_SDL2_GAMEPAD_BUTTON_CUSTOM
|
|
||||||
// #define INPUT_PSP_GAMEPAD_BUTTON_CANCEL INPUT_SDL2_GAMEPAD_BUTTON_CUSTOM
|
|
||||||
|
|
||||||
inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
||||||
{ .name = "triangle", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_Y } },
|
{ .name = "triangle", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_Y } },
|
||||||
{ .name = "cross", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_A } },
|
{ .name = "cross", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_A } },
|
||||||
@@ -24,10 +21,6 @@ inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
|||||||
{ .name = "l", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_LEFTSHOULDER } },
|
{ .name = "l", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_LEFTSHOULDER } },
|
||||||
{ .name = "r", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER } },
|
{ .name = "r", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER } },
|
||||||
|
|
||||||
// Refer to systempsp.c for some extra info.
|
|
||||||
{ .name = "accept", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_A } },
|
|
||||||
{ .name = "cancel", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_B } },
|
|
||||||
|
|
||||||
{ .name = "lstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
|
{ .name = "lstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
|
||||||
{ .name = "lstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
|
{ .name = "lstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
|
||||||
{ .name = "lstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = true } } },
|
{ .name = "lstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = true } } },
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
networkpsp.c
|
|
||||||
)
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "networkpsp.h"
|
|
||||||
|
|
||||||
#define networkPlatformInit networkPSPInit
|
|
||||||
#define networkPlatformUpdate networkPSPUpdate
|
|
||||||
#define networkPlatformDispose networkPSPDispose
|
|
||||||
#define networkPlatformIsConnected networkPSPIsConnected
|
|
||||||
#define networkPlatformRequestConnection networkPSPRequestConnection
|
|
||||||
#define networkPlatformRequestDisconnection networkPSPRequestDisconnection
|
|
||||||
#define networkPlatformGetInfo networkPSPGetInfo
|
|
||||||
|
|
||||||
typedef networkpsp_t networkplatform_t;
|
|
||||||
@@ -1,259 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "network/network.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "display/displaysdl2.h"
|
|
||||||
|
|
||||||
errorret_t networkPSPInit() {
|
|
||||||
// Requests the PSP to load the network modules.
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = sceUtilityLoadNetModule(PSP_NET_MODULE_COMMON);
|
|
||||||
if(ret < 0) errorThrow("Failed to init NET COMMON: 0x%08X", ret);
|
|
||||||
|
|
||||||
ret = sceUtilityLoadNetModule(PSP_NET_MODULE_INET);
|
|
||||||
if(ret < 0) errorThrow("Failed to init NET INET: 0x%08X", ret);
|
|
||||||
|
|
||||||
// ret = sceUtilityLoadNetModule(PSP_NET_MODULE_PARSEURI);
|
|
||||||
// if(ret < 0) errorThrow("Failed to init NET PARSEURI: 0x%08X", ret);
|
|
||||||
|
|
||||||
// ret = sceUtilityLoadNetModule(PSP_NET_MODULE_PARSEHTTP);
|
|
||||||
// if(ret < 0) errorThrow("Failed to init NET PARSEHTTP: 0x%08X", ret);
|
|
||||||
|
|
||||||
// ret = sceUtilityLoadNetModule(PSP_NET_MODULE_SSL);
|
|
||||||
// if(ret < 0) errorThrow("Failed to init NET SSL: 0x%08X", ret);
|
|
||||||
|
|
||||||
// ret = sceUtilityLoadNetModule(PSP_NET_MODULE_HTTP);
|
|
||||||
// if(ret < 0) errorThrow("Failed to init NET HTTP: 0x%08X", ret);
|
|
||||||
|
|
||||||
// ret = sceSslInit(0x28000);
|
|
||||||
// if(ret < 0) errorThrow("sceSslInit failed: 0x%08X", ret);
|
|
||||||
|
|
||||||
// ret = sceHttpInit(0x25800);
|
|
||||||
// if(ret < 0) errorThrow("sceHttpInit failed: 0x%08X", ret);
|
|
||||||
|
|
||||||
// ret = sceHttpsInit(0, 0, 0, 0);
|
|
||||||
// if(ret < 0) errorThrow("sceHttpsInit failed: 0x%08X", ret);
|
|
||||||
|
|
||||||
// ret = sceHttpsLoadDefaultCert(0, 0);
|
|
||||||
// if(ret < 0) errorThrow("sceHttpsLoadDefaultCert failed: 0x%08X", ret);
|
|
||||||
|
|
||||||
// ret = sceHttpLoadSystemCookie();
|
|
||||||
// if(ret < 0) errorThrow("sceHttpLoadSystemCookie failed: 0x%08X", ret);
|
|
||||||
|
|
||||||
// All good.
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t networkPSPUpdate() {
|
|
||||||
int ret;
|
|
||||||
if(NETWORK.state == NETWORK_STATE_CONNECTING) {
|
|
||||||
switch(sceUtilityNetconfGetStatus()) {
|
|
||||||
case PSP_UTILITY_DIALOG_INIT:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PSP_UTILITY_DIALOG_NONE:
|
|
||||||
NETWORK.state = NETWORK_STATE_DISCONNECTED;
|
|
||||||
errorThrow("PSP Netconf dialog disappeared without result");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PSP_UTILITY_DIALOG_VISIBLE:
|
|
||||||
// 1 is mandatory?
|
|
||||||
ret = sceUtilityNetconfUpdate(1);
|
|
||||||
if(ret != 0) {
|
|
||||||
errorThrow("sceUtilityNetconfUpdate failed: 0x%08X", ret);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PSP_UTILITY_DIALOG_QUIT:
|
|
||||||
ret = sceUtilityNetconfShutdownStart();
|
|
||||||
if(ret != 0) {
|
|
||||||
errorThrow("sceUtilityNetconfShutdownStart failed: 0x%08X", ret);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PSP_UTILITY_DIALOG_FINISHED:
|
|
||||||
// Did we connect?
|
|
||||||
int apState = 0;
|
|
||||||
sceNetApctlGetState(&apState);
|
|
||||||
|
|
||||||
if(apState == PSP_NET_APCTL_STATE_GOT_IP) {
|
|
||||||
NETWORK.state = NETWORK_STATE_CONNECTED;
|
|
||||||
assertNotNull(
|
|
||||||
NETWORK.platform.onConnected,
|
|
||||||
"Network platform onConnected callback should be set."
|
|
||||||
);
|
|
||||||
NETWORK.platform.onConnected(NETWORK.platform.onConnectedUser);
|
|
||||||
} else {
|
|
||||||
NETWORK.state = NETWORK_STATE_DISCONNECTED;
|
|
||||||
|
|
||||||
assertNotNull(
|
|
||||||
NETWORK.platform.onFailed,
|
|
||||||
"Network platform onFailed callback should be set."
|
|
||||||
);
|
|
||||||
|
|
||||||
// Kill the PSP network stack.
|
|
||||||
errorret_t err = networkPSPTerm();
|
|
||||||
if(err.code != ERROR_OK) {
|
|
||||||
errorCatch(errorPrint(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t error = errorThrowImpl(
|
|
||||||
&NETWORK.errorState,
|
|
||||||
ERROR_NOT_OK,
|
|
||||||
__FILE__, __func__, __LINE__,
|
|
||||||
"Failed to connect to network"
|
|
||||||
);
|
|
||||||
NETWORK.platform.onFailed(error, NETWORK.platform.onConnectedUser);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
errorThrow("Unknown PSP Netconf dialog status: %d", sceUtilityNetconfGetStatus());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t networkPSPDispose() {
|
|
||||||
sceUtilityNetconfGetStatus();
|
|
||||||
errorCatch(errorPrint(networkPSPTerm()));
|
|
||||||
|
|
||||||
sceUtilityUnloadNetModule(PSP_NET_MODULE_HTTP);
|
|
||||||
sceUtilityUnloadNetModule(PSP_NET_MODULE_INET);
|
|
||||||
sceUtilityUnloadNetModule(PSP_NET_MODULE_COMMON);
|
|
||||||
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool_t networkPSPIsConnected() {
|
|
||||||
return NETWORK.state == NETWORK_STATE_CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void networkPSPRequestConnection(
|
|
||||||
void (*onConnected)(void *user),
|
|
||||||
void (*onFailed)(errorret_t error, void *user),
|
|
||||||
void (*onDisconnect)(errorret_t error, void *user),
|
|
||||||
void *user
|
|
||||||
) {
|
|
||||||
assertTrue(
|
|
||||||
NETWORK.state == NETWORK_STATE_CONNECTING,
|
|
||||||
"Network host should be in a connecting state."
|
|
||||||
);
|
|
||||||
|
|
||||||
NETWORK.platform.onConnected = onConnected;
|
|
||||||
NETWORK.platform.onFailed = onFailed;
|
|
||||||
NETWORK.platform.onConnectedUser = user;
|
|
||||||
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
// Init the PSP network stack.
|
|
||||||
ret = sceNetInit(0x20000, 0x20, 4096, 0x20, 4096);
|
|
||||||
assertTrue(ret >= 0, "Failed to init net: 0x%08X");
|
|
||||||
|
|
||||||
ret = sceNetInetInit();
|
|
||||||
assertTrue(ret >= 0, "Failed to init net inet: 0x%08X");
|
|
||||||
|
|
||||||
ret = sceNetResolverInit();
|
|
||||||
assertTrue(ret >= 0, "Failed to init net resolver: 0x%08X");
|
|
||||||
|
|
||||||
ret = sceNetApctlInit(0x1800, 0x30);
|
|
||||||
assertTrue(ret >= 0, "Failed to init net apctl: 0x%08X");
|
|
||||||
|
|
||||||
|
|
||||||
// This is all related to getting the PSP online, refer to;
|
|
||||||
// https://github.com/joel16/CMFileManager-PSP/blob/00dab16c64cd48bf6452fc274a3b898d77c39a8d/app/source/net.cpp#L97
|
|
||||||
// since I follow this implementation closely.
|
|
||||||
memoryZero(&NETWORK.platform.dialogData, sizeof(NETWORK.platform.dialogData));
|
|
||||||
memoryZero(&NETWORK.platform.dialogAdhoc, sizeof(NETWORK.platform.dialogAdhoc));
|
|
||||||
|
|
||||||
NETWORK.platform.dialogData.base.size = sizeof(pspUtilityNetconfData);
|
|
||||||
NETWORK.platform.dialogData.base.language = systemPSPGetLanguage();
|
|
||||||
NETWORK.platform.dialogData.base.buttonSwap = systemPSPGetCrossButtonSetting();
|
|
||||||
NETWORK.platform.dialogData.base.graphicsThread = 17;
|
|
||||||
NETWORK.platform.dialogData.base.accessThread = 19;
|
|
||||||
NETWORK.platform.dialogData.base.fontThread = 18;
|
|
||||||
NETWORK.platform.dialogData.base.soundThread = 16;
|
|
||||||
NETWORK.platform.dialogData.action = PSP_NETCONF_ACTION_CONNECTAP;
|
|
||||||
NETWORK.platform.dialogData.adhocparam = (
|
|
||||||
&NETWORK.platform.dialogAdhoc
|
|
||||||
);
|
|
||||||
|
|
||||||
ret = sceUtilityNetconfInitStart(&NETWORK.platform.dialogData);
|
|
||||||
assertTrue(ret >= 0, "Failed to init netconf");
|
|
||||||
}
|
|
||||||
|
|
||||||
void networkPSPRequestDisconnection(
|
|
||||||
void (*onComplete)(void *user),
|
|
||||||
void *user
|
|
||||||
) {
|
|
||||||
assertTrue(
|
|
||||||
NETWORK.state == NETWORK_STATE_DISCONNECTING,
|
|
||||||
"Network host should be in a disconnecting state."
|
|
||||||
);
|
|
||||||
|
|
||||||
errorret_t err = networkPSPTerm();
|
|
||||||
if(err.code != ERROR_OK) {
|
|
||||||
errorCatch(errorPrint(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
NETWORK.state = NETWORK_STATE_DISCONNECTED;
|
|
||||||
onComplete(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t networkPSPTerm() {
|
|
||||||
int ret;
|
|
||||||
ret = sceNetApctlTerm();
|
|
||||||
if(ret < 0) {
|
|
||||||
errorThrow("Failed to terminate netctl: 0x%08X", ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = sceNetResolverTerm();
|
|
||||||
if(ret < 0) {
|
|
||||||
errorThrow("Failed to terminate net resolver: 0x%08X", ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = sceNetInetTerm();
|
|
||||||
if(ret < 0) {
|
|
||||||
errorThrow("Failed to terminate net inet: 0x%08X", ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = sceNetTerm();
|
|
||||||
if(ret < 0) {
|
|
||||||
errorThrow("Failed to terminate net: 0x%08X", ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
networkinfo_t networkPSPGetInfo() {
|
|
||||||
networkinfo_t netInfo;
|
|
||||||
memoryZero(&netInfo, sizeof(networkinfo_t));
|
|
||||||
|
|
||||||
// Get the IP address of the current connection.
|
|
||||||
union SceNetApctlInfo info;
|
|
||||||
int ret = sceNetApctlGetInfo(PSP_NET_APCTL_INFO_IP, &info);
|
|
||||||
assertTrue(ret >= 0, "Failed to get IP address");
|
|
||||||
|
|
||||||
// Parse the IP address string into octets.
|
|
||||||
netInfo.type = NETWORK_TYPE_IPV4;
|
|
||||||
ret = sscanf(
|
|
||||||
info.ip,
|
|
||||||
"%hhu.%hhu.%hhu.%hhu",
|
|
||||||
&netInfo.ipv4.ip[0],
|
|
||||||
&netInfo.ipv4.ip[1],
|
|
||||||
&netInfo.ipv4.ip[2],
|
|
||||||
&netInfo.ipv4.ip[3]
|
|
||||||
);
|
|
||||||
assertTrue(ret == 4, "Failed to parse IP address");
|
|
||||||
|
|
||||||
return netInfo;
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "error/error.h"
|
|
||||||
#include "network/networkinfo.h"
|
|
||||||
#include "system/systempsp.h"
|
|
||||||
#include <psphttp.h>
|
|
||||||
#include <pspnet.h>
|
|
||||||
#include <pspnet_inet.h>
|
|
||||||
#include <pspnet_apctl.h>
|
|
||||||
#include <pspssl.h>
|
|
||||||
#include <pspnet_resolver.h>
|
|
||||||
#include <psphttp.h>
|
|
||||||
|
|
||||||
// #define NETWORK_HTTP_PENDING_MAX 4
|
|
||||||
// #define NETWORK_HTTP_URL_MAX 512
|
|
||||||
// #define NETWORK_HTTP_BODY_MAX 2048
|
|
||||||
// #define NETWORK_HTTP_RESPONSE_MAX 16384
|
|
||||||
// #define NETWORK_HTTP_HEADER_MAX 8
|
|
||||||
// #define NETWORK_HTTP_HEADER_KEY_MAX 64
|
|
||||||
// #define NETWORK_HTTP_HEADER_VAL_MAX 256
|
|
||||||
// #define NETWORK_ERROR_MESSAGE_MAX 256
|
|
||||||
// #define NETWORK_PSP_AGENT "DuskEngine/1.0"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
pspUtilityNetconfData dialogData;
|
|
||||||
struct pspUtilityNetconfAdhoc dialogAdhoc;
|
|
||||||
|
|
||||||
// Used during establishing connection
|
|
||||||
void *onConnectedUser;
|
|
||||||
void (*onConnected)(void *user);
|
|
||||||
void (*onFailed)(errorret_t error, void *user);
|
|
||||||
} networkpsp_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the PSP Network manager. This will NOT do network connecting,
|
|
||||||
* only prep it for being able to connect in future.
|
|
||||||
*
|
|
||||||
* @return Error state (if any).
|
|
||||||
*/
|
|
||||||
errorret_t networkPSPInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called each frame for handling PSP requests, basically this is where all
|
|
||||||
* communication between the HTTP thread and the main thread happens.
|
|
||||||
*
|
|
||||||
* @return Error state (if any).
|
|
||||||
*/
|
|
||||||
errorret_t networkPSPUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes the PSP Network manager, this will clean all resources and, if the
|
|
||||||
* network is connected, it will disconnect it safely.
|
|
||||||
*
|
|
||||||
* @return Error state (if any).
|
|
||||||
*/
|
|
||||||
errorret_t networkPSPDispose();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the PSP network is connected.
|
|
||||||
*
|
|
||||||
* @return True if the PSP is connected to a network, false otherwise.
|
|
||||||
*/
|
|
||||||
bool_t networkPSPIsConnected();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests the PSP to connect to a network (Shows the Wi-Fi connected).
|
|
||||||
*
|
|
||||||
* @param onConnected Callback connected successfully.
|
|
||||||
* @param onFailed Callback if the connection failed.
|
|
||||||
* @param onDisconnect Callback when connection is lost.
|
|
||||||
* @param user User data to pass to the callbacks.
|
|
||||||
*/
|
|
||||||
void networkPSPRequestConnection(
|
|
||||||
void (*onConnected)(void *user),
|
|
||||||
void (*onFailed)(errorret_t error, void *user),
|
|
||||||
void (*onDisconnect)(errorret_t error, void *user),
|
|
||||||
void *user
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests the PSP to disconnect from the network (Shows the Wi-Fi disconnecting).
|
|
||||||
*
|
|
||||||
* @param onComplete Callback when disconnection is complete.
|
|
||||||
* @param user User data to pass to the callback.
|
|
||||||
*/
|
|
||||||
void networkPSPRequestDisconnection(
|
|
||||||
void (*onComplete)(void *user),
|
|
||||||
void *user
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes the PSP sce net libraries, doesn't unload the modules and won't
|
|
||||||
* term the dialog if it's active.
|
|
||||||
*
|
|
||||||
* @return Error state (if any).
|
|
||||||
*/
|
|
||||||
errorret_t networkPSPTerm();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the network information for the currently active network connection.
|
|
||||||
*
|
|
||||||
* @return Network information for the currently active network connection.
|
|
||||||
*/
|
|
||||||
networkinfo_t networkPSPGetInfo();
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
systempsp.c
|
|
||||||
)
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "system/systempsp.h"
|
|
||||||
|
|
||||||
#define systemInitPlatform systemInitPSP
|
|
||||||
#define systemGetActiveDialogTypePlatform systemGetActiveDialogTypePSP
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "systempsp.h"
|
|
||||||
#include "input/input.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
|
|
||||||
errorret_t systemInitPSP() {
|
|
||||||
// Bind ACCEPT and CANCEL binds.
|
|
||||||
inputbuttondata_t *buttonCross, *buttonCircle, *buttonAccept, *buttonCancel;
|
|
||||||
|
|
||||||
inputbuttondata_t *i = INPUT_BUTTON_DATA;
|
|
||||||
while(i->name) {
|
|
||||||
if(stringCompare(i->name, "cross") == 0) {
|
|
||||||
buttonCross = i;
|
|
||||||
} else if(stringCompare(i->name, "circle") == 0) {
|
|
||||||
buttonCircle = i;
|
|
||||||
} else if(stringCompare(i->name, "accept") == 0) {
|
|
||||||
buttonAccept = i;
|
|
||||||
} else if(stringCompare(i->name, "cancel") == 0) {
|
|
||||||
buttonCancel = i;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
assertNotNull(buttonCross, "Cross button not found!");
|
|
||||||
assertNotNull(buttonCircle, "Circle button not found!");
|
|
||||||
assertNotNull(buttonAccept, "Accept button not found!");
|
|
||||||
assertNotNull(buttonCancel, "Cancel button not found!");
|
|
||||||
|
|
||||||
if(systemPSPGetCrossButtonSetting() == PSP_UTILITY_ACCEPT_CROSS) {
|
|
||||||
buttonAccept->button.gpButton = buttonCross->button.gpButton;
|
|
||||||
buttonCancel->button.gpButton = buttonCircle->button.gpButton;
|
|
||||||
} else {
|
|
||||||
buttonAccept->button.gpButton = buttonCircle->button.gpButton;
|
|
||||||
buttonCancel->button.gpButton = buttonCross->button.gpButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
systemdialogtype_t systemGetActiveDialogTypePSP() {
|
|
||||||
return SYSTEM_DIALOG_TYPE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int systemPSPGetLanguage() {
|
|
||||||
int ret;
|
|
||||||
sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_LANGUAGE, &ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int systemPSPGetCrossButtonSetting() {
|
|
||||||
int ret;
|
|
||||||
// See: https://pspdev.github.io/pspsdk/psputility__sysparam_8h.html#ab588fd5a14adc025f065e09325ffe729
|
|
||||||
sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_UNKNOWN, &ret);
|
|
||||||
return (
|
|
||||||
ret == 1 ? PSP_UTILITY_ACCEPT_CROSS : PSP_UTILITY_ACCEPT_CIRCLE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "system/system.h"
|
|
||||||
#include <psputility.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the PSP system module.
|
|
||||||
*
|
|
||||||
* @return Error code indicating success or failure.
|
|
||||||
*/
|
|
||||||
errorret_t systemInitPSP(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns which PSP system dialog is currently open (if any).
|
|
||||||
*
|
|
||||||
* @return Currently open system dialog type.
|
|
||||||
*/
|
|
||||||
systemdialogtype_t systemGetActiveDialogTypePSP();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the PSP_SYSTEMPARAM language for the current system.
|
|
||||||
*
|
|
||||||
* @return PSP_SYSTEMPARAM language value.
|
|
||||||
*/
|
|
||||||
int systemPSPGetLanguage();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the user's setting for the PSP "Cross Button" configuration, which
|
|
||||||
* determines whether the "Cross" or "Circle" button is used for "Accept"
|
|
||||||
* actions in system dialogs.
|
|
||||||
*
|
|
||||||
* @return PSP_UTILITY_ACCEPT_CROSS or PSP_UTILITY_ACCEPT_CIRCLE.
|
|
||||||
*/
|
|
||||||
int systemPSPGetCrossButtonSetting();
|
|
||||||
@@ -73,11 +73,6 @@ float_t inputButtonGetValueSDL2(const inputbutton_t button) {
|
|||||||
|
|
||||||
#ifdef DUSK_INPUT_GAMEPAD
|
#ifdef DUSK_INPUT_GAMEPAD
|
||||||
case INPUT_BUTTON_TYPE_GAMEPAD: {
|
case INPUT_BUTTON_TYPE_GAMEPAD: {
|
||||||
assertTrue(
|
|
||||||
button.gpButton < SDL_CONTROLLER_BUTTON_MAX,
|
|
||||||
"Gamepad button out of range"
|
|
||||||
);
|
|
||||||
|
|
||||||
if(SDL_GameControllerGetButton(
|
if(SDL_GameControllerGetButton(
|
||||||
INPUT.platform.controller, button.gpButton
|
INPUT.platform.controller, button.gpButton
|
||||||
)) {
|
)) {
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
# Includes
|
|
||||||
target_include_directories(${DUSK_LIBRARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Sources
|
|
||||||
target_sources(${DUSK_BINARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
)
|
|
||||||
|
|
||||||
# Subdirs
|
|
||||||
add_subdirectory(asset)
|
|
||||||
add_subdirectory(input)
|
|
||||||
add_subdirectory(log)
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "assetvita.h"
|
|
||||||
|
|
||||||
typedef assetvita_t assetplatform_t;
|
|
||||||
#define assetInitPlatform assetInitVita
|
|
||||||
#define assetDisposePlatform assetDisposeVita
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "asset/asset.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
|
|
||||||
errorret_t assetInitVita(void) {
|
|
||||||
int32_t error;
|
|
||||||
ASSET.zip = zip_open(ASSET_VITA_DSK_PATH, ZIP_RDONLY, &error);
|
|
||||||
if(ASSET.zip == NULL) {
|
|
||||||
errorThrow("Failed to open asset file: " ASSET_VITA_DSK_PATH);
|
|
||||||
}
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t assetDisposeVita(void) {
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "error/error.h"
|
|
||||||
|
|
||||||
// dusk.dsk is packaged at the root of the VPK and accessible via app0:/
|
|
||||||
#define ASSET_VITA_DSK_PATH "app0:/" ASSET_FILE_NAME
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t _unused;
|
|
||||||
} assetvita_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the Vita asset system, opening dusk.dsk from the VPK mount.
|
|
||||||
*
|
|
||||||
* @returns An errorret_t indicating success or failure.
|
|
||||||
*/
|
|
||||||
errorret_t assetInitVita(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes the Vita asset system.
|
|
||||||
*
|
|
||||||
* @returns An errorret_t indicating success or failure.
|
|
||||||
*/
|
|
||||||
errorret_t assetDisposeVita(void);
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user