physics - sweep lua API; code editor improvements
This commit is contained in:
parent
958098cfc0
commit
24914869ae
|
@ -1,4 +1,9 @@
|
|||
local tpl = [[
|
||||
export type Vec2 = {number}
|
||||
export type Vec3 = {number}
|
||||
export type Color = {number}
|
||||
export type Quat = {number}
|
||||
export type DVec3 = {number}
|
||||
declare ImGui: {
|
||||
AlignTextToFramePadding : () -> (),
|
||||
Begin : (string, boolean?) -> (boolean, boolean?),
|
||||
|
@ -82,8 +87,8 @@ declare class Entity
|
|||
name : string
|
||||
parent : Entity?
|
||||
rotation : any
|
||||
position : any
|
||||
scale : any
|
||||
position : Vec3
|
||||
scale : Vec3
|
||||
hasComponent : (Entity, any) -> boolean
|
||||
getComponent : (Entity, any) -> any
|
||||
destroy : (Entity) -> ()
|
||||
|
@ -115,6 +120,7 @@ declare Editor: {
|
|||
}
|
||||
|
||||
declare LumixAPI: {
|
||||
%s
|
||||
INPUT_KEYCODE_SHIFT: number,
|
||||
INPUT_KEYCODE_LEFT : number,
|
||||
INPUT_KEYCODE_RIGHT : number,
|
||||
|
@ -133,6 +139,12 @@ end
|
|||
declare class FunctionBase
|
||||
end
|
||||
|
||||
declare class StructVarBase
|
||||
end
|
||||
|
||||
declare class StructBase
|
||||
end
|
||||
|
||||
declare class ModuleReflection
|
||||
end
|
||||
|
||||
|
@ -159,6 +171,13 @@ declare LumixReflection: {
|
|||
getFunction : (number) -> FunctionBase,
|
||||
getThisTypeName : (FunctionBase) -> string,
|
||||
getReturnTypeName : (FunctionBase) -> string,
|
||||
getNumStructs : () -> number,
|
||||
getStruct : (number) -> StructBase,
|
||||
getStructName : (StructBase) -> string,
|
||||
getNumStructMembers : (StructBase) -> number,
|
||||
getStructMember : (StructBase, number) -> StructVarBase,
|
||||
getStructMemberName : (StructVarBase) -> string,
|
||||
getStructMemberType : (StructVarBase) -> number
|
||||
}
|
||||
|
||||
type InputDevice = {
|
||||
|
@ -193,6 +212,7 @@ export type InputEvent = ButtonInputEvent | AxisInputEvent
|
|||
function typeToString(type : number) : string
|
||||
if type < 3 then return "number" end
|
||||
if type == 3 then return "Entity" end
|
||||
if type == 5 then return "Vec3" end
|
||||
if type == 8 then return "string" end
|
||||
if type == 9 then return "boolean" end
|
||||
if type == 10 then return "string" end
|
||||
|
@ -224,9 +244,21 @@ export type InputEvent = ButtonInputEvent | AxisInputEvent
|
|||
end
|
||||
|
||||
function toLuaType(ctype : string)
|
||||
if string.match(ctype, "^struct Lumix::") then
|
||||
ctype = string.sub(ctype, 15)
|
||||
end
|
||||
if ctype == "int" then return "number" end
|
||||
if ctype == "const char *" then return "string" end
|
||||
if ctype == "const char*" then return "string" end
|
||||
if ctype == "char const *" then return "string" end
|
||||
if ctype == "Vec3" then return "Vec3" end
|
||||
if ctype == "Quat" then return "Quat" end
|
||||
if ctype == "Vec2" then return "Vec2" end
|
||||
if ctype == "Color" then return "Color" end
|
||||
if ctype == "DVec3" then return "DVec3" end
|
||||
if ctype == "EntityPtr" then return "Entity?" end
|
||||
if ctype == "EntityRef" then return "Entity" end
|
||||
if ctype == "Path" then return "string" end
|
||||
if ctype == "i32" then return "number" end
|
||||
if ctype == "u32" then return "number" end
|
||||
if ctype == "float" then return "number" end
|
||||
|
@ -237,8 +269,36 @@ export type InputEvent = ButtonInputEvent | AxisInputEvent
|
|||
return `any --[[{ctype}]]`
|
||||
end
|
||||
|
||||
function memberTypeToString(type : number) : string
|
||||
if type == 2 then return "boolean" end
|
||||
if type == 3 then return "number" end
|
||||
if type == 4 then return "number" end
|
||||
if type == 5 then return "number" end
|
||||
if type == 6 then return "string" end
|
||||
if type == 7 then return "Entity" end
|
||||
if type == 9 then return "Vec3" end
|
||||
return "any"
|
||||
end
|
||||
|
||||
function refl()
|
||||
local out = ""
|
||||
local lumixAPI_src = ""
|
||||
local num_structs = LumixReflection.getNumStructs()
|
||||
for i = 0, num_structs - 1 do
|
||||
local struct = LumixReflection.getStruct(i)
|
||||
local name = LumixReflection.getStructName(struct)
|
||||
out = out .. `declare class {name}\n`
|
||||
local num_members = LumixReflection.getNumStructMembers(struct)
|
||||
lumixAPI_src = lumixAPI_src .. `\t{name} : \{ create : () -> {name}, destroy : ({name}) -> () \},\n`
|
||||
for j = 0, num_members - 1 do
|
||||
local member = LumixReflection.getStructMember(struct, j)
|
||||
local member_name = LumixReflection.getStructMemberName(member)
|
||||
local type = LumixReflection.getStructMemberType(member)
|
||||
out = out .. `\t{member_name} : {memberTypeToString(type)}\n`
|
||||
end
|
||||
out = out .. `end\n\n`
|
||||
end
|
||||
|
||||
local num_funcs = LumixReflection.getNumFunctions()
|
||||
for i = 1, num_funcs do
|
||||
local fn = LumixReflection.getFunction(i - 1)
|
||||
|
@ -295,12 +355,12 @@ export type InputEvent = ButtonInputEvent | AxisInputEvent
|
|||
out = out .. "end\n\n"
|
||||
end
|
||||
|
||||
return string.format(tpl, world_src, out, entity_src)
|
||||
return string.format(tpl, world_src, out, entity_src, lumixAPI_src)
|
||||
end
|
||||
|
||||
local type_defs = refl()
|
||||
|
||||
if false then
|
||||
if true then
|
||||
return {
|
||||
name = "Lua type defs",
|
||||
gui = function()
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
export type Vec2 = {number}
|
||||
export type Vec3 = {number}
|
||||
export type Color = {number}
|
||||
export type Quat = {number}
|
||||
export type DVec3 = {number}
|
||||
declare ImGui: {
|
||||
AlignTextToFramePadding : () -> (),
|
||||
Begin : (string, boolean?) -> (boolean, boolean?),
|
||||
|
@ -82,19 +87,31 @@ declare class World
|
|||
|
||||
end
|
||||
|
||||
declare class RaycastHit
|
||||
position : Vec3
|
||||
normal : Vec3
|
||||
entity : Entity
|
||||
end
|
||||
|
||||
declare class SweepHit
|
||||
position : Vec3
|
||||
normal : Vec3
|
||||
entity : Entity
|
||||
end
|
||||
|
||||
declare class GUISystem
|
||||
enableCursor : (GUISystem, boolean) -> ()
|
||||
end
|
||||
|
||||
declare class AssetBrowser
|
||||
openEditor : (AssetBrowser, any --[[const char*]]) -> ()
|
||||
openEditor : (AssetBrowser, string) -> ()
|
||||
end
|
||||
|
||||
declare class SceneView
|
||||
getViewportRotation : (SceneView) -> any --[[struct Lumix::Quat]]
|
||||
setViewportRotation : (SceneView, any --[[Quat]]) -> ()
|
||||
getViewportPosition : (SceneView) -> any --[[struct Lumix::DVec3]]
|
||||
setViewportPosition : (SceneView, any --[[DVec3]]) -> ()
|
||||
getViewportRotation : (SceneView) -> Quat
|
||||
setViewportRotation : (SceneView, Quat) -> ()
|
||||
getViewportPosition : (SceneView) -> DVec3
|
||||
setViewportPosition : (SceneView, DVec3) -> ()
|
||||
end
|
||||
|
||||
declare class Model
|
||||
|
@ -113,9 +130,9 @@ declare class animation_module
|
|||
end
|
||||
|
||||
declare class gui_module
|
||||
getRectAt : (gui_module, any --[[Vec2]]) -> any --[[struct Lumix::EntityPtr]]
|
||||
isOver : (gui_module, any --[[Vec2]], any --[[EntityPtr]]) -> boolean
|
||||
getSystem : (gui_module) -> GUISystem
|
||||
getRectAt : (gui_module, Vec2) -> Entity?
|
||||
isOver : (gui_module, Vec2, Entity?) -> boolean
|
||||
getSystem : (gui_module) -> any --[[GUISystem *]]
|
||||
end
|
||||
|
||||
declare class lua_script_module
|
||||
|
@ -123,7 +140,7 @@ end
|
|||
|
||||
declare class audio_module
|
||||
setMasterVolume : (audio_module, number) -> ()
|
||||
play : (audio_module, any --[[EntityPtr]], any --[[const char*]], boolean) -> number
|
||||
play : (audio_module, Entity?, string, boolean) -> number
|
||||
stop : (audio_module, number) -> ()
|
||||
isEnd : (audio_module, number) -> boolean
|
||||
setFrequency : (audio_module, number, number) -> ()
|
||||
|
@ -132,16 +149,17 @@ declare class audio_module
|
|||
end
|
||||
|
||||
declare class renderer_module
|
||||
addDebugCross : (renderer_module, any --[[DVec3]], number, any --[[Color]]) -> ()
|
||||
addDebugLine : (renderer_module, any --[[DVec3]], any --[[DVec3]], any --[[Color]]) -> ()
|
||||
addDebugTriangle : (renderer_module, any --[[DVec3]], any --[[DVec3]], any --[[DVec3]], any --[[Color]]) -> ()
|
||||
setActiveCamera : (renderer_module, any --[[EntityPtr]]) -> ()
|
||||
addDebugCross : (renderer_module, DVec3, number, Color) -> ()
|
||||
addDebugLine : (renderer_module, DVec3, DVec3, Color) -> ()
|
||||
addDebugTriangle : (renderer_module, DVec3, DVec3, DVec3, Color) -> ()
|
||||
setActiveCamera : (renderer_module, Entity?) -> ()
|
||||
end
|
||||
|
||||
declare class physics_module
|
||||
raycast : (physics_module, any --[[Vec3]], any --[[Vec3]], number, any --[[EntityPtr]]) -> any --[[struct Lumix::EntityPtr]]
|
||||
sweepSphere : (physics_module, any --[[DVec3]], number, any --[[Vec3]], number, any --[[EntityPtr]], number) -> any --[[struct Lumix::EntityPtr]]
|
||||
setGravity : (physics_module, any --[[Vec3]]) -> ()
|
||||
raycast : (physics_module, Vec3, Vec3, number, Entity?) -> Entity?
|
||||
raycastEx : (physics_module, Vec3, Vec3, number, any --[[void*]], Entity?, number) -> boolean
|
||||
sweepSphere : (physics_module, DVec3, number, Vec3, number, any --[[void*]], Entity?, number) -> boolean
|
||||
setGravity : (physics_module, Vec3) -> ()
|
||||
end
|
||||
|
||||
declare class spline_component
|
||||
|
@ -177,7 +195,7 @@ declare class terrain_component
|
|||
tesselation: number
|
||||
grid_resolution: number
|
||||
grass: any
|
||||
getTerrainNormalAt : (terrain_component, number, number) -> any --[[struct Lumix::Vec3]]
|
||||
getTerrainNormalAt : (terrain_component, number, number) -> Vec3
|
||||
getTerrainHeightAt : (terrain_component, number, number) -> number
|
||||
end
|
||||
|
||||
|
@ -191,7 +209,7 @@ end
|
|||
|
||||
declare class decal_component
|
||||
material: string
|
||||
half_extents: any
|
||||
half_extents: Vec3
|
||||
uv_scale: any
|
||||
end
|
||||
|
||||
|
@ -207,12 +225,12 @@ declare class point_light_component
|
|||
intensity: number
|
||||
fov: number
|
||||
attenuation: number
|
||||
color: any
|
||||
color: Vec3
|
||||
range: number
|
||||
end
|
||||
|
||||
declare class environment_component
|
||||
color: any
|
||||
color: Vec3
|
||||
intensity: number
|
||||
indirect_intensity: number
|
||||
shadow_cascades: any
|
||||
|
@ -228,19 +246,19 @@ declare class model_instance_component
|
|||
enabled: boolean
|
||||
material: string
|
||||
source: string
|
||||
getModel : (model_instance_component) -> Model
|
||||
getModel : (model_instance_component) -> any --[[Model *]]
|
||||
end
|
||||
|
||||
declare class environment_probe_component
|
||||
enabled: boolean
|
||||
inner_range: any
|
||||
outer_range: any
|
||||
inner_range: Vec3
|
||||
outer_range: Vec3
|
||||
end
|
||||
|
||||
declare class reflection_probe_component
|
||||
enabled: boolean
|
||||
size: number
|
||||
half_extents: any
|
||||
half_extents: Vec3
|
||||
end
|
||||
|
||||
declare class fur_component
|
||||
|
@ -256,8 +274,8 @@ end
|
|||
|
||||
declare class bone_attachment_component
|
||||
parent: Entity
|
||||
relative_position: any
|
||||
relative_rotation: any
|
||||
relative_position: Vec3
|
||||
relative_rotation: Vec3
|
||||
bone: number
|
||||
end
|
||||
|
||||
|
@ -272,10 +290,10 @@ declare class rigid_actor_component
|
|||
material: string
|
||||
putToSleep : (rigid_actor_component) -> ()
|
||||
getSpeed : (rigid_actor_component) -> number
|
||||
getVelocity : (rigid_actor_component) -> any --[[struct Lumix::Vec3]]
|
||||
applyForce : (rigid_actor_component, any --[[Vec3]]) -> ()
|
||||
applyImpulse : (rigid_actor_component, any --[[Vec3]]) -> ()
|
||||
addForceAtPos : (rigid_actor_component, any --[[Vec3]], any --[[Vec3]]) -> ()
|
||||
getVelocity : (rigid_actor_component) -> Vec3
|
||||
applyForce : (rigid_actor_component, Vec3) -> ()
|
||||
applyImpulse : (rigid_actor_component, Vec3) -> ()
|
||||
addForceAtPos : (rigid_actor_component, Vec3, Vec3) -> ()
|
||||
end
|
||||
|
||||
declare class physical_heightfield_component
|
||||
|
@ -292,14 +310,14 @@ declare class physical_controller_component
|
|||
use_root_motion: boolean
|
||||
use_custom_gravity: boolean
|
||||
custom_gravity_acceleration: number
|
||||
move : (physical_controller_component, any --[[Vec3]]) -> ()
|
||||
move : (physical_controller_component, Vec3) -> ()
|
||||
isCollisionDown : (physical_controller_component) -> boolean
|
||||
getGravitySpeed : (physical_controller_component) -> number
|
||||
end
|
||||
|
||||
declare class lua_script_component
|
||||
scripts: any
|
||||
getScriptPath : (lua_script_component, number) -> any --[[struct Lumix::Path]]
|
||||
getScriptPath : (lua_script_component, number) -> string
|
||||
end
|
||||
|
||||
declare class gui_image_component
|
||||
|
@ -331,7 +349,7 @@ end
|
|||
|
||||
declare class distance_joint_component
|
||||
connected_body: Entity
|
||||
axis_position: any
|
||||
axis_position: Vec3
|
||||
damping: number
|
||||
stiffness: number
|
||||
tolerance: number
|
||||
|
@ -340,8 +358,8 @@ end
|
|||
|
||||
declare class hinge_joint_component
|
||||
connected_body: Entity
|
||||
axis_position: any
|
||||
axis_direction: any
|
||||
axis_position: Vec3
|
||||
axis_direction: Vec3
|
||||
damping: number
|
||||
stiffness: number
|
||||
use_limit: boolean
|
||||
|
@ -350,16 +368,16 @@ end
|
|||
|
||||
declare class spherical_joint_component
|
||||
connected_body: Entity
|
||||
axis_position: any
|
||||
axis_direction: any
|
||||
axis_position: Vec3
|
||||
axis_direction: Vec3
|
||||
use_limit: boolean
|
||||
limit: any
|
||||
end
|
||||
|
||||
declare class d6_joint_component
|
||||
connected_body: Entity
|
||||
axis_position: any
|
||||
axis_direction: any
|
||||
axis_position: Vec3
|
||||
axis_direction: Vec3
|
||||
x_motion: number
|
||||
y_motion: number
|
||||
z_motion: number
|
||||
|
@ -377,7 +395,7 @@ declare class vehicle_component
|
|||
current_gear: number
|
||||
rpm: number
|
||||
mass: number
|
||||
center_of_mass: any
|
||||
center_of_mass: Vec3
|
||||
moi_multiplier: number
|
||||
chassis: string
|
||||
chassis_layer: number
|
||||
|
@ -406,13 +424,13 @@ declare class navmesh_agent_component
|
|||
move_entity: boolean
|
||||
speed: number
|
||||
setActive : (navmesh_agent_component, boolean) -> ()
|
||||
navigate : (navmesh_agent_component, any --[[DVec3]], number, number) -> boolean
|
||||
navigate : (navmesh_agent_component, DVec3, number, number) -> boolean
|
||||
cancelNavigation : (navmesh_agent_component) -> ()
|
||||
drawPath : (navmesh_agent_component) -> ()
|
||||
end
|
||||
|
||||
declare class navmesh_zone_component
|
||||
extents: any
|
||||
extents: Vec3
|
||||
agent_height: number
|
||||
agent_radius: number
|
||||
cell_size: number
|
||||
|
@ -423,10 +441,10 @@ declare class navmesh_zone_component
|
|||
detailed: boolean
|
||||
load : (navmesh_zone_component) -> boolean
|
||||
drawContours : (navmesh_zone_component) -> ()
|
||||
drawNavmesh : (navmesh_zone_component, any --[[DVec3]], boolean, boolean, boolean) -> ()
|
||||
drawNavmesh : (navmesh_zone_component, DVec3, boolean, boolean, boolean) -> ()
|
||||
drawCompactHeightfield : (navmesh_zone_component) -> ()
|
||||
drawHeightfield : (navmesh_zone_component) -> ()
|
||||
generateNavmesh : (navmesh_zone_component) -> any --[[struct Lumix::NavmeshBuildJob *]]
|
||||
generateNavmesh : (navmesh_zone_component) -> any --[[NavmeshBuildJob *]]
|
||||
end
|
||||
|
||||
declare class lua_script_inline_component
|
||||
|
@ -447,11 +465,11 @@ declare class animator_component
|
|||
use_root_motion: boolean
|
||||
setFloatInput : (animator_component, number, number) -> ()
|
||||
setBoolInput : (animator_component, number, boolean) -> ()
|
||||
getInputIndex : (animator_component, any --[[const char*]]) -> number
|
||||
getInputIndex : (animator_component, string) -> number
|
||||
end
|
||||
|
||||
declare class physical_instanced_cube_component
|
||||
half_extents: any
|
||||
half_extents: Vec3
|
||||
layer: number
|
||||
end
|
||||
|
||||
|
@ -486,8 +504,8 @@ declare class Entity
|
|||
name : string
|
||||
parent : Entity?
|
||||
rotation : any
|
||||
position : any
|
||||
scale : any
|
||||
position : Vec3
|
||||
scale : Vec3
|
||||
hasComponent : (Entity, any) -> boolean
|
||||
getComponent : (Entity, any) -> any
|
||||
destroy : (Entity) -> ()
|
||||
|
@ -563,6 +581,9 @@ declare Editor: {
|
|||
}
|
||||
|
||||
declare LumixAPI: {
|
||||
RaycastHit : { create : () -> RaycastHit, destroy : (RaycastHit) -> () },
|
||||
SweepHit : { create : () -> SweepHit, destroy : (SweepHit) -> () },
|
||||
|
||||
INPUT_KEYCODE_SHIFT: number,
|
||||
INPUT_KEYCODE_LEFT : number,
|
||||
INPUT_KEYCODE_RIGHT : number,
|
||||
|
@ -581,6 +602,12 @@ end
|
|||
declare class FunctionBase
|
||||
end
|
||||
|
||||
declare class StructVarBase
|
||||
end
|
||||
|
||||
declare class StructBase
|
||||
end
|
||||
|
||||
declare class ModuleReflection
|
||||
end
|
||||
|
||||
|
@ -607,6 +634,13 @@ declare LumixReflection: {
|
|||
getFunction : (number) -> FunctionBase,
|
||||
getThisTypeName : (FunctionBase) -> string,
|
||||
getReturnTypeName : (FunctionBase) -> string,
|
||||
getNumStructs : () -> number,
|
||||
getStruct : (number) -> StructBase,
|
||||
getStructName : (StructBase) -> string,
|
||||
getNumStructMembers : (StructBase) -> number,
|
||||
getStructMember : (StructBase, number) -> StructVarBase,
|
||||
getStructMemberName : (StructVarBase) -> string,
|
||||
getStructMemberType : (StructVarBase) -> number
|
||||
}
|
||||
|
||||
type InputDevice = {
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
return {
|
||||
dot = function(a, b)
|
||||
return a[1] * b[1] + a[2] * b[2] + a[3] * b[3]
|
||||
end,
|
||||
|
||||
mulQuat = function(a, b)
|
||||
return {
|
||||
a[4] * b[1] + b[4] * a[1] + a[2] * b[3] - b[2] * a[3],
|
||||
a[4] * b[2] + b[4] * a[2] + a[3] * b[1] - b[3] * a[1],
|
||||
a[4] * b[3] + b[4] * a[3] + a[1] * b[2] - b[1] * a[2],
|
||||
a[4] * b[4] - a[1] * b[1] - a[2] * b[2] - a[3] * b[3]
|
||||
}
|
||||
end,
|
||||
|
||||
makeQuatFromYaw = function(yaw)
|
||||
local syaw = math.sin(yaw * 0.5)
|
||||
local cyaw = math.cos(yaw * 0.5)
|
||||
return {0, syaw, 0, cyaw }
|
||||
end,
|
||||
|
||||
makeQuatFromPitch = function(pitch)
|
||||
local spitch = math.sin(pitch * 0.5)
|
||||
local cpitch = math.cos(pitch * 0.5)
|
||||
return {-spitch, 0, 0, cpitch}
|
||||
end,
|
||||
|
||||
yawToDir = function(yaw)
|
||||
return {math.sin(yaw), 0, math.cos(yaw)}
|
||||
end,
|
||||
|
||||
mulVec3Num = function(v, f)
|
||||
return {v[1] * f, v[2] * f, v[3] * f}
|
||||
end,
|
||||
|
||||
addVec3 = function(a, b)
|
||||
return {a[1] + b[1], a[2] + b[2], a[3] + b[3]}
|
||||
end,
|
||||
|
||||
subVec3 = function(a, b)
|
||||
return {a[1] - b[1], a[2] - b[2], a[3] - b[3]}
|
||||
end,
|
||||
|
||||
mulVec3 = function(a, f)
|
||||
return {a[1] * f, a[2] * f, a[3] * f}
|
||||
end,
|
||||
dot = function(a, b)
|
||||
return a[1] * b[1] + a[2] * b[2] + a[3] * b[3]
|
||||
end,
|
||||
|
||||
mulQuat = function(a, b)
|
||||
return {
|
||||
a[4] * b[1] + b[4] * a[1] + a[2] * b[3] - b[2] * a[3],
|
||||
a[4] * b[2] + b[4] * a[2] + a[3] * b[1] - b[3] * a[1],
|
||||
a[4] * b[3] + b[4] * a[3] + a[1] * b[2] - b[1] * a[2],
|
||||
a[4] * b[4] - a[1] * b[1] - a[2] * b[2] - a[3] * b[3]
|
||||
}
|
||||
end,
|
||||
|
||||
makeQuatFromYaw = function(yaw)
|
||||
local syaw = math.sin(yaw * 0.5)
|
||||
local cyaw = math.cos(yaw * 0.5)
|
||||
return {0, syaw, 0, cyaw }
|
||||
end,
|
||||
|
||||
makeQuatFromPitch = function(pitch)
|
||||
local spitch = math.sin(pitch * 0.5)
|
||||
local cpitch = math.cos(pitch * 0.5)
|
||||
return {-spitch, 0, 0, cpitch}
|
||||
end,
|
||||
|
||||
yawToDir = function(yaw)
|
||||
return {math.sin(yaw), 0, math.cos(yaw)}
|
||||
end,
|
||||
|
||||
mulVec3Num = function(v, f)
|
||||
return {v[1] * f, v[2] * f, v[3] * f}
|
||||
end,
|
||||
|
||||
addVec3 = function(a, b)
|
||||
return {a[1] + b[1], a[2] + b[2], a[3] + b[3]}
|
||||
end,
|
||||
|
||||
subVec3 = function(a, b)
|
||||
return {a[1] - b[1], a[2] - b[2], a[3] - b[3]}
|
||||
end,
|
||||
|
||||
mulVec3 = function(a, f)
|
||||
return {a[1] * f, a[2] * f, a[3] * f}
|
||||
end,
|
||||
|
||||
}
|
||||
|
|
|
@ -591,7 +591,7 @@ struct GridUIVisitor final : reflection::IPropertyVisitor
|
|||
void visit(const reflection::ArrayProperty& prop) override
|
||||
{
|
||||
ImGui::Unindent();
|
||||
bool is_root_open = ImGui::TreeNodeEx(prop.name, ImGuiTreeNodeFlags_AllowItemOverlap);
|
||||
bool is_root_open = ImGui::TreeNodeEx(prop.name, ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen);
|
||||
if (m_entities.size() > 1)
|
||||
{
|
||||
ImGui::Text("Multi-object editing not supported.");
|
||||
|
|
|
@ -436,7 +436,7 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
struct Token {
|
||||
enum Flags {
|
||||
NONE = 0,
|
||||
UNDERLINE = 1 << 0
|
||||
UNDERLINE = 1 << 0,
|
||||
};
|
||||
u32 from;
|
||||
u32 len;
|
||||
|
@ -469,7 +469,8 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
END_GROUP,
|
||||
REMOVE,
|
||||
INSERT,
|
||||
NEW_LINE
|
||||
NEW_LINE,
|
||||
MOVE_LINE
|
||||
};
|
||||
|
||||
UndoRecord(IAllocator& allocator) : text(allocator), cursors(allocator) {}
|
||||
|
@ -486,6 +487,21 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
void execute(CodeEditorImpl& editor, bool is_redo) {
|
||||
++editor.m_version;
|
||||
switch(type) {
|
||||
case MOVE_LINE: {
|
||||
if (from.line < to.line) {
|
||||
for (i32 line = from.line; line < to.line; ++line) {
|
||||
swap(editor.m_lines[line], editor.m_lines[line + 1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i32 line = from.line; line > to.line; --line) {
|
||||
swap(editor.m_lines[line], editor.m_lines[line - 1]);
|
||||
}
|
||||
}
|
||||
editor.invalidateTokens(from.line);
|
||||
editor.invalidateTokens(to.line);
|
||||
break;
|
||||
}
|
||||
case BEGIN_GROUP:
|
||||
if (!is_redo) editor.m_cursors.copyTo(cursors);
|
||||
break;
|
||||
|
@ -526,6 +542,21 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
void undo(CodeEditorImpl& editor) {
|
||||
++editor.m_version;
|
||||
switch(type) {
|
||||
case MOVE_LINE: {
|
||||
if (to.line < from.line) {
|
||||
for (i32 line = to.line; line < from.line; ++line) {
|
||||
swap(editor.m_lines[line], editor.m_lines[line + 1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i32 line = to.line; line > from.line; --line) {
|
||||
swap(editor.m_lines[line], editor.m_lines[line - 1]);
|
||||
}
|
||||
}
|
||||
editor.invalidateTokens(from.line);
|
||||
editor.invalidateTokens(to.line);
|
||||
break;
|
||||
}
|
||||
case BEGIN_GROUP:
|
||||
cursors.copyTo(editor.m_cursors);
|
||||
editor.ensurePointVisible(editor.m_cursors[0]);
|
||||
|
@ -659,6 +690,23 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
return (u32)ImGui::CalcTextSize(str, str + cursor.col).x;
|
||||
}
|
||||
|
||||
Token getToken(TextPoint p) {
|
||||
const Line& line = m_lines[p.line];
|
||||
for (Token token : line.tokens) {
|
||||
if (p.col >= (i32)token.from && p.col < i32(token.from + token.len)) return token;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
StringView toStringView(const Token& token, u32 line) {
|
||||
const char* str = m_lines[line].value.c_str();
|
||||
StringView res;
|
||||
res.begin = str + token.from;
|
||||
res.end = res.begin + token.len;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void cursorMoved(Cursor& cursor, bool update_virtual) {
|
||||
cursor.line = clamp(cursor.line, 0, m_lines.size() - 1);
|
||||
cursor.col = clamp(cursor.col, 0, m_lines[cursor.line].length());
|
||||
|
@ -668,6 +716,8 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
}
|
||||
if (update_virtual) cursor.virtual_x = computeCursorX(cursor);
|
||||
m_blink_timer = 0;
|
||||
m_time_since_cursor_moved = 0;
|
||||
m_highlighted_str = {};
|
||||
}
|
||||
|
||||
void moveCursorLeft(Cursor& cursor, bool word) {
|
||||
|
@ -686,7 +736,7 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
|
||||
void ensurePointVisible(TextPoint& cursor, bool center = false) {
|
||||
if (center) {
|
||||
m_scroll_y = (cursor.line - (m_last_visible_line - m_first_visible_line) / 2) * ImGui::GetTextLineHeight();
|
||||
m_scroll_y += (cursor.line - (m_first_visible_line + m_max_visible_lines / 2)) * ImGui::GetTextLineHeight();
|
||||
m_scroll_y = maximum(m_scroll_y, 0.f);
|
||||
return;
|
||||
}
|
||||
|
@ -700,6 +750,47 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
}
|
||||
}
|
||||
|
||||
void moveLinesUp() {
|
||||
TextPoint from = m_cursors[0];
|
||||
TextPoint to = m_cursors[0].sel;
|
||||
if (from > to) swap(from, to);
|
||||
if (to.col == 0 && to.line > from.line) --to.line;
|
||||
if (from.line == 0) return;
|
||||
|
||||
beginUndoGroup();
|
||||
m_cursors.resize(1);
|
||||
UndoRecord& r = pushUndo();
|
||||
r.type = UndoRecord::MOVE_LINE;
|
||||
r.from = from;
|
||||
r.to = to;
|
||||
--r.from.line;
|
||||
r.execute(*this, false);
|
||||
--m_cursors[0].line;
|
||||
--m_cursors[0].sel.line;
|
||||
endUndoGroup();
|
||||
}
|
||||
|
||||
void moveLinesDown() {
|
||||
m_cursors.resize(1);
|
||||
TextPoint from = m_cursors[0];
|
||||
TextPoint to = m_cursors[0].sel;
|
||||
if (from > to) swap(from, to);
|
||||
if (to.col == 0 && to.line > from.line) --to.line;
|
||||
if (to.line == m_lines.size() - 1) return;
|
||||
|
||||
beginUndoGroup();
|
||||
m_cursors.resize(1);
|
||||
UndoRecord& r = pushUndo();
|
||||
r.type = UndoRecord::MOVE_LINE;
|
||||
r.from = to;
|
||||
r.to = from;
|
||||
++r.from.line;
|
||||
r.execute(*this, false);
|
||||
++m_cursors[0].line;
|
||||
++m_cursors[0].sel.line;
|
||||
endUndoGroup();
|
||||
}
|
||||
|
||||
void moveCursorUp(Cursor& cursor, u32 line_count = 1) {
|
||||
const char* line_str = m_lines[cursor.line].value.c_str();
|
||||
cursor.line = maximum(0, cursor.line - line_count);
|
||||
|
@ -755,15 +846,13 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
|
||||
void moveCursorBegin(Cursor& cursor, bool doc) {
|
||||
if (doc) cursor.line = 0;
|
||||
if (cursor.col == 0) {
|
||||
const String& line = m_lines[cursor.line].value;
|
||||
while (cursor.col < (i32)line.length() && !isWordChar(line[cursor.col])) {
|
||||
++cursor.col;
|
||||
}
|
||||
}
|
||||
else {
|
||||
cursor.col = 0;
|
||||
const i32 prev_col = cursor.col;
|
||||
const String& line = m_lines[cursor.line].value;
|
||||
cursor.col = 0;
|
||||
while (cursor.col < (i32)line.length() && !isWordChar(line[cursor.col])) {
|
||||
++cursor.col;
|
||||
}
|
||||
if (cursor.col >= prev_col && prev_col != 0) cursor.col = 0;
|
||||
cursorMoved(cursor, true);
|
||||
if (&cursor == &m_cursors[0]) ensurePointVisible(cursor);
|
||||
}
|
||||
|
@ -1026,7 +1115,7 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
new_cursor.sel.col = i32(found - m_lines[line].value.c_str());
|
||||
new_cursor.col = new_cursor.sel.col + sel_view.size();
|
||||
new_cursor.virtual_x = computeCursorX(new_cursor);
|
||||
ensurePointVisible(new_cursor, true);
|
||||
ensurePointVisible(new_cursor);
|
||||
return;
|
||||
}
|
||||
++line;
|
||||
|
@ -1097,25 +1186,30 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
|
||||
TextPoint getLeftWord(TextPoint point) {
|
||||
TextPoint p = getLeft(point);
|
||||
bool is_word = isWordChar(getChar(p));
|
||||
p = getLeft(p);
|
||||
|
||||
while (isWordChar(getChar(p)) == is_word) {
|
||||
if (p.col == 0) return p;
|
||||
const bool is_word = isWordChar(getChar(p));
|
||||
for (;;) {
|
||||
p = getLeft(p);
|
||||
if (p.line == 0 && p.col == 0) return p;
|
||||
char c = getChar(p);
|
||||
if (isWordChar(c) != is_word) {
|
||||
p = getRight(p);
|
||||
return p;
|
||||
}
|
||||
if (p.col == 0) return p;
|
||||
}
|
||||
return getRight(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
TextPoint getRightWord(TextPoint point) {
|
||||
TextPoint p = getRight(point);
|
||||
bool is_word = isWordChar(getChar(p));
|
||||
p = getRight(p);
|
||||
|
||||
while (isWordChar(getChar(p)) == is_word) {
|
||||
TextPoint p = point;
|
||||
const bool is_word = isWordChar(getChar(p));
|
||||
char c;
|
||||
do {
|
||||
p = getRight(p);
|
||||
c = getChar(p);
|
||||
if (c == '\n') return p;
|
||||
if (p.line == m_lines.size() - 1 && p.col == m_lines.back().length()) return p;
|
||||
}
|
||||
} while (isWordChar(c) == is_word);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -1450,9 +1544,9 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
|
||||
// text
|
||||
m_first_visible_line = i32(m_scroll_y / line_height);
|
||||
float visible_lines = content_size.y / line_height;
|
||||
m_max_visible_lines = i32(content_size.y / line_height);
|
||||
m_first_visible_line = clamp(m_first_visible_line, 0, m_lines.size() - 1);
|
||||
m_last_visible_line = minimum(m_first_visible_line + i32(visible_lines), m_lines.size() - 1);
|
||||
m_last_visible_line = minimum(m_first_visible_line + i32(m_max_visible_lines), m_lines.size() - 1);
|
||||
|
||||
{
|
||||
PROFILE_BLOCK("tokenize");
|
||||
|
@ -1468,10 +1562,16 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
const char* str = m_lines[j].value.c_str();
|
||||
ImVec2 p = text_area_pos + ImVec2(0, line_offset_y);
|
||||
for (const Token& t : m_lines[j].tokens) {
|
||||
dl->AddText(p, m_token_colors[t.type], str + t.from, str + t.from + t.len);
|
||||
|
||||
ImVec2 start_p = p;
|
||||
p.x += ImGui::CalcTextSize(str + t.from, str + t.from + t.len).x;
|
||||
|
||||
if (equalStrings(toStringView(t, j), m_highlighted_str)) {
|
||||
dl->AddRectFilled(start_p, p + ImVec2(0, line_height), IM_COL32(0x50, 0x50, 0x50, 0x7f));
|
||||
}
|
||||
|
||||
dl->AddText(start_p, m_token_colors[t.type], str + t.from, str + t.from + t.len);
|
||||
|
||||
if (t.flags & Token::UNDERLINE) {
|
||||
if (m_handle_input && ImGui::IsMouseHoveringRect(start_p, p + ImVec2(0, line_height))) {
|
||||
const Underline* underline = getUnderline(j, t);
|
||||
|
@ -1485,6 +1585,19 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
profiler::pushInt("Num tokens", visible_tokens);
|
||||
|
||||
// cursors
|
||||
float prev_since_cursor_moved = m_time_since_cursor_moved;
|
||||
m_time_since_cursor_moved += io.DeltaTime;
|
||||
if (m_time_since_cursor_moved > 0.5f && prev_since_cursor_moved <= 0.5f) {
|
||||
m_highlighted_str = toStringView(getToken(m_cursors[0]), m_cursors[0].line);
|
||||
bool empty = true;
|
||||
for (const char* c = m_highlighted_str.begin; c != m_highlighted_str.end; ++c) {
|
||||
if (isWordChar(*c)) {
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (empty) m_highlighted_str = {};
|
||||
}
|
||||
m_blink_timer += io.DeltaTime;
|
||||
m_blink_timer = fmodf(m_blink_timer, 1.f);
|
||||
bool draw_cursors = m_blink_timer < 0.6f;
|
||||
|
@ -1495,8 +1608,8 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
if (draw_cursors) dl->AddRectFilled(cursor_pos, cursor_pos + ImVec2(1, line_height), code_color);
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_LeftArrow)) moveCursorLeft(c, io.KeyCtrl);
|
||||
else if (ImGui::IsKeyPressed(ImGuiKey_RightArrow)) moveCursorRight(c, io.KeyCtrl);
|
||||
else if (ImGui::IsKeyPressed(ImGuiKey_UpArrow)) moveCursorUp(c);
|
||||
else if (ImGui::IsKeyPressed(ImGuiKey_DownArrow)) moveCursorDown(c);
|
||||
else if (ImGui::IsKeyPressed(ImGuiKey_UpArrow)) io.KeyAlt ? moveLinesUp() : moveCursorUp(c);
|
||||
else if (ImGui::IsKeyPressed(ImGuiKey_DownArrow)) io.KeyAlt ? moveLinesDown() : moveCursorDown(c);
|
||||
else if (ImGui::IsKeyPressed(ImGuiKey_End)) moveCursorEnd(c, io.KeyCtrl);
|
||||
else if (ImGui::IsKeyPressed(ImGuiKey_Home)) moveCursorBegin(c, io.KeyCtrl);
|
||||
}
|
||||
|
@ -1658,6 +1771,8 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
i32 m_first_untokenized_line = 0;
|
||||
TagAllocator m_allocator;
|
||||
float m_blink_timer = 0;
|
||||
float m_time_since_cursor_moved = 0;
|
||||
StringView m_highlighted_str;
|
||||
StudioApp& m_app;
|
||||
Array<Line> m_lines;
|
||||
Array<Underline> m_underlines;
|
||||
|
@ -1665,6 +1780,7 @@ struct CodeEditorImpl final : CodeEditor {
|
|||
Array<Cursor> m_cursors;
|
||||
i32 m_first_visible_line = 0;
|
||||
i32 m_last_visible_line = 0;
|
||||
i32 m_max_visible_lines = 0;
|
||||
Tokenizer m_tokenizer = nullptr;
|
||||
Span<const u32> m_token_colors;
|
||||
u32 m_version = 0;
|
||||
|
|
|
@ -410,10 +410,38 @@ static i32 LUA_getNumFunctions() {
|
|||
return reflection::allFunctions().size();
|
||||
}
|
||||
|
||||
static i32 LUA_getNumStructs() {
|
||||
return reflection::allStructs().size();
|
||||
}
|
||||
|
||||
static reflection::FunctionBase* LUA_getFunction(i32 idx) {
|
||||
return reflection::allFunctions()[idx];
|
||||
}
|
||||
|
||||
static reflection::StructBase* LUA_getStruct(i32 idx) {
|
||||
return reflection::allStructs()[idx];
|
||||
}
|
||||
|
||||
static const char* LUA_getStructName(reflection::StructBase* str) {
|
||||
return str->name;
|
||||
}
|
||||
|
||||
static i32 LUA_getNumStructMembers(reflection::StructBase* str) {
|
||||
return str->members.size();
|
||||
}
|
||||
|
||||
static reflection::StructVarBase* LUA_getStructMember(reflection::StructBase* str, u32 idx) {
|
||||
return str->members[idx];
|
||||
}
|
||||
|
||||
static u32 LUA_getStructMemberType(reflection::StructVarBase* var) {
|
||||
return (u32)var->getType().type;
|
||||
}
|
||||
|
||||
static const char* LUA_getStructMemberName(reflection::StructVarBase* var) {
|
||||
return var->name;
|
||||
}
|
||||
|
||||
static i32 LUA_getNextModule(lua_State* L) {
|
||||
reflection::Module* module = LuaWrapper::checkArg<reflection::Module*>(L, 1);
|
||||
if (module->next) lua_pushlightuserdata(L, module->next);
|
||||
|
@ -953,6 +981,14 @@ void registerEngineAPI(lua_State* L, Engine* engine)
|
|||
LuaWrapper::createSystemFunction(L, "LumixReflection", "getNumFunctions", &LuaWrapper::wrap<LUA_getNumFunctions>);
|
||||
LuaWrapper::createSystemFunction(L, "LumixReflection", "getFunction", &LuaWrapper::wrap<LUA_getFunction>);
|
||||
|
||||
LuaWrapper::createSystemFunction(L, "LumixReflection", "getNumStructs", &LuaWrapper::wrap<LUA_getNumStructs>);
|
||||
LuaWrapper::createSystemFunction(L, "LumixReflection", "getStruct", &LuaWrapper::wrap<LUA_getStruct>);
|
||||
LuaWrapper::createSystemFunction(L, "LumixReflection", "getStructName", &LuaWrapper::wrap<LUA_getStructName>);
|
||||
LuaWrapper::createSystemFunction(L, "LumixReflection", "getNumStructMembers", &LuaWrapper::wrap<LUA_getNumStructMembers>);
|
||||
LuaWrapper::createSystemFunction(L, "LumixReflection", "getStructMember", &LuaWrapper::wrap<LUA_getStructMember>);
|
||||
LuaWrapper::createSystemFunction(L, "LumixReflection", "getStructMemberName", &LuaWrapper::wrap<LUA_getStructMemberName>);
|
||||
LuaWrapper::createSystemFunction(L, "LumixReflection", "getStructMemberType", &LuaWrapper::wrap<LUA_getStructMemberType>);
|
||||
|
||||
LuaWrapper::createSystemFunction(L, "LumixAPI", "networkRead", &LUA_networkRead);
|
||||
LuaWrapper::createSystemFunction(L, "LumixAPI", "packU32", &LUA_packU32);
|
||||
LuaWrapper::createSystemFunction(L, "LumixAPI", "unpackU32", &LUA_unpackU32);
|
||||
|
|
|
@ -38,6 +38,11 @@ Array<FunctionBase*>& allFunctions() {
|
|||
return fncs;
|
||||
}
|
||||
|
||||
Array<StructBase*>& allStructs() {
|
||||
static Array<StructBase*> structs(getGlobalAllocator());
|
||||
return structs;
|
||||
}
|
||||
|
||||
ComponentBase::ComponentBase(IAllocator& allocator)
|
||||
: props(allocator)
|
||||
, functions(allocator)
|
||||
|
|
|
@ -326,7 +326,7 @@ StringView getTypeName()
|
|||
|
||||
struct Variant {
|
||||
Variant() { type = I32; i = 0; }
|
||||
enum Type {
|
||||
enum Type : u32 {
|
||||
VOID,
|
||||
PTR,
|
||||
BOOL,
|
||||
|
@ -380,6 +380,7 @@ struct TypeDescriptor {
|
|||
template <typename T> struct VariantTag {};
|
||||
|
||||
template <typename T> inline Variant::Type _getVariantType(VariantTag<T*>) { return Variant::PTR; }
|
||||
template <typename T> inline Variant::Type _getVariantType(VariantTag<T>) { return Variant::PTR; }
|
||||
inline Variant::Type _getVariantType(VariantTag<void>) { return Variant::VOID; }
|
||||
inline Variant::Type _getVariantType(VariantTag<bool>) { return Variant::BOOL; }
|
||||
inline Variant::Type _getVariantType(VariantTag<i32>) { return Variant::I32; }
|
||||
|
@ -435,6 +436,7 @@ inline EntityPtr fromVariant(int i, Span<Variant> args, VariantTag<EntityPtr>) {
|
|||
inline EntityRef fromVariant(int i, Span<Variant> args, VariantTag<EntityRef>) { return (EntityRef)args[i].e; }
|
||||
inline void* fromVariant(int i, Span<Variant> args, VariantTag<void*>) { return args[i].ptr; }
|
||||
template <typename T> inline T* fromVariant(int i, Span<Variant> args, VariantTag<T*>) { return (T*)args[i].ptr; }
|
||||
template <typename T> inline T& fromVariant(int i, Span<Variant> args, VariantTag<T>) { return *(T*)args[i].ptr; }
|
||||
|
||||
template <typename... Args>
|
||||
struct VariantCaller {
|
||||
|
@ -566,7 +568,75 @@ struct Function<R (C::*)(Args...) const> : FunctionBase
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
struct StructVarBase {
|
||||
virtual ~StructVarBase() {}
|
||||
virtual bool set(void* obj, Span<const u8> mem) = 0;
|
||||
virtual bool get(const void* obj, Span<u8> mem) = 0;
|
||||
|
||||
template <typename T> T get(void* obj) {
|
||||
T res;
|
||||
get(obj, Span((u8*)&res, sizeof(res)));
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T> void set(void* obj, T val) {
|
||||
set(obj, Span((const u8*)&val, sizeof(val)));
|
||||
}
|
||||
|
||||
virtual TypeDescriptor getType() const = 0;
|
||||
|
||||
const char* name;
|
||||
};
|
||||
|
||||
template <auto Getter>
|
||||
struct StructVar : StructVarBase {
|
||||
using T = typename ResultOf<decltype(Getter)>::Type;
|
||||
using C = typename ClassOf<decltype(Getter)>::Type;
|
||||
|
||||
TypeDescriptor getType() const override {
|
||||
return toTypeDescriptor<T>();
|
||||
}
|
||||
|
||||
bool set(void* obj, Span<const u8> mem) override {
|
||||
C* inst = (C*)obj;
|
||||
auto& v = inst->*Getter;
|
||||
if (sizeof(v) != mem.length()) return false;
|
||||
memcpy(&v, mem.begin(), sizeof(v));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get(const void* obj, Span<u8> mem) override {
|
||||
C* inst = (C*)obj;
|
||||
auto& v = inst->*Getter;
|
||||
if (sizeof(v) != mem.length()) return false;
|
||||
memcpy(mem.begin(), &v, sizeof(v));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct StructBase {
|
||||
StructBase() : allocator(getGlobalAllocator()), members(getGlobalAllocator()) {}
|
||||
|
||||
virtual ~StructBase() {}
|
||||
virtual void* createInstance(IAllocator& allocator) = 0;
|
||||
virtual void destroyInstance(void* obj, IAllocator& allocator) = 0;
|
||||
|
||||
template <auto Getter>
|
||||
StructBase& member(const char* name) {
|
||||
StructVar<Getter>* member = LUMIX_NEW(allocator, StructVar<Getter>);
|
||||
member->name = name;
|
||||
members.push(member);
|
||||
return *this;
|
||||
}
|
||||
|
||||
IAllocator& allocator;
|
||||
const char* name;
|
||||
Array<StructVarBase*> members;
|
||||
};
|
||||
|
||||
LUMIX_ENGINE_API Array<FunctionBase*>& allFunctions();
|
||||
LUMIX_ENGINE_API Array<StructBase*>& allStructs();
|
||||
|
||||
template <typename F>
|
||||
auto& function(F func, const char* decl_code, const char* name)
|
||||
|
@ -579,6 +649,18 @@ auto& function(F func, const char* decl_code, const char* name)
|
|||
return ret;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
auto& structure(const char* name)
|
||||
{
|
||||
static struct : StructBase {
|
||||
void* createInstance(IAllocator& allocator) override { return LUMIX_NEW(allocator, S); }
|
||||
void destroyInstance(void* obj, IAllocator& allocator) override { LUMIX_DELETE(allocator, (S*)obj); }
|
||||
} ret;
|
||||
ret.name = name;
|
||||
allStructs().push(&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct LUMIX_ENGINE_API ComponentBase {
|
||||
ComponentBase(IAllocator& allocator);
|
||||
|
||||
|
|
|
@ -39,9 +39,10 @@ void EntityMap::set(EntityRef src, EntityRef dst) {
|
|||
m_map[src.index] = dst;
|
||||
}
|
||||
|
||||
|
||||
World::~World() = default;
|
||||
|
||||
World::~World() {
|
||||
// release modules first, since they can access world
|
||||
m_modules.clear();
|
||||
}
|
||||
|
||||
World::World(Engine& engine)
|
||||
: m_allocator(engine.getAllocator(), "world")
|
||||
|
|
|
@ -124,7 +124,16 @@ static void toVariant(reflection::Variant::Type type, lua_State* L, int idx, ref
|
|||
case reflection::Variant::FLOAT: val = LuaWrapper::checkArg<float>(L, idx); break;
|
||||
case reflection::Variant::ENTITY: val = LuaWrapper::checkArg<EntityPtr>(L, idx); break;
|
||||
case reflection::Variant::VEC2: val = LuaWrapper::checkArg<Vec2>(L, idx); break;
|
||||
case reflection::Variant::COLOR:
|
||||
case reflection::Variant::COLOR: {
|
||||
if (LuaWrapper::isType<Vec4>(L, idx)) {
|
||||
Vec4 c = LuaWrapper::toType<Vec4>(L, idx);
|
||||
val = Color(u8(c.r * 255), u8(c.g * 255), u8(c.b * 255), u8(c.a * 255));
|
||||
break;
|
||||
}
|
||||
Vec3 c = LuaWrapper::checkArg<Vec3>(L, idx);
|
||||
val = Color(u8(c.r * 255), u8(c.g * 255), u8(c.b * 255), 0xff);
|
||||
break;
|
||||
}
|
||||
case reflection::Variant::VEC3: val = LuaWrapper::checkArg<Vec3>(L, idx); break;
|
||||
case reflection::Variant::DVEC3: val = LuaWrapper::checkArg<DVec3>(L, idx); break;
|
||||
case reflection::Variant::QUAT: val = LuaWrapper::checkArg<Quat>(L, idx); break;
|
||||
|
@ -241,9 +250,129 @@ static int luaCmpMethodClosure(lua_State* L) {
|
|||
return push(L, res, f->getReturnTypeName());
|
||||
}
|
||||
|
||||
static int lua_struct_var_setter(lua_State* L) {
|
||||
LuaWrapper::checkTableArg(L, 1); // self
|
||||
const char* prop_name = LuaWrapper::checkArg<const char*>(L, 2);
|
||||
int type = lua_getfield(L, 1, "_value");
|
||||
if (type != LUA_TLIGHTUSERDATA) luaL_argerror(L, 1, "invalid object");
|
||||
void* inst = lua_tolightuserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
reflection::StructBase* s = LuaWrapper::toType<reflection::StructBase*>(L, lua_upvalueindex(1));
|
||||
|
||||
for (reflection::StructVarBase* var : s->members) {
|
||||
if (equalStrings(var->name, prop_name)) {
|
||||
reflection::TypeDescriptor td = var->getType();
|
||||
switch (td.type) {
|
||||
case reflection::Variant::DVEC3: {
|
||||
const DVec3& v = LuaWrapper::checkArg<DVec3>(L, 2);
|
||||
var->set(inst, v);
|
||||
return 0;
|
||||
}
|
||||
case reflection::Variant::VEC3: {
|
||||
const Vec3& v = LuaWrapper::checkArg<Vec3>(L, 2);
|
||||
var->set(inst, v);
|
||||
return 0;
|
||||
}
|
||||
case reflection::Variant::FLOAT: {
|
||||
const float v = LuaWrapper::checkArg<float>(L, 2);
|
||||
var->set(inst, v);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
ASSERT(false);
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_struct_var_getter(lua_State* L) {
|
||||
LuaWrapper::checkTableArg(L, 1); // self
|
||||
const char* prop_name = LuaWrapper::checkArg<const char*>(L, 2);
|
||||
int type = lua_getfield(L, 1, "_value");
|
||||
if (type != LUA_TLIGHTUSERDATA) luaL_argerror(L, 1, "invalid object");
|
||||
void* inst = lua_tolightuserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
reflection::StructBase* s = LuaWrapper::toType<reflection::StructBase*>(L, lua_upvalueindex(1));
|
||||
|
||||
for (reflection::StructVarBase* var : s->members) {
|
||||
if (equalStrings(var->name, prop_name)) {
|
||||
reflection::TypeDescriptor td = var->getType();
|
||||
switch (td.type) {
|
||||
case reflection::Variant::DVEC3: {
|
||||
LuaWrapper::push(L, var->get<DVec3>(inst));
|
||||
return 1;
|
||||
}
|
||||
case reflection::Variant::VEC3: {
|
||||
LuaWrapper::push(L, var->get<Vec3>(inst));
|
||||
return 1;
|
||||
}
|
||||
case reflection::Variant::FLOAT: {
|
||||
LuaWrapper::push(L, var->get<float>(inst));
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
ASSERT(false);
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void createClasses(lua_State* L) {
|
||||
LuaWrapper::DebugGuard guard(L);
|
||||
lua_getglobal(L, "LumixAPI");
|
||||
for (auto* s : reflection::allStructs()) {
|
||||
if (LuaWrapper::getField(L, -1, s->name) != LUA_TTABLE) { // [LumixAPI, obj|nil ]
|
||||
lua_pop(L, 1); // [LumixAPI]
|
||||
lua_newtable(L); // [LumixAPI, obj]
|
||||
lua_pushvalue(L, -1); // [LumixAPI, obj, obj]
|
||||
lua_setfield(L, -3, s->name); // [LumixAPI, obj]
|
||||
|
||||
lua_pushlightuserdata(L, s); // [LumixAPI, obj, refl::struct]
|
||||
lua_pushcclosure(L, lua_struct_var_getter, "struct_var_getter", 1); // [LumixAPI, obj, var_getter]
|
||||
lua_setfield(L, -2, "__index"); // [LumixAPI, obj]
|
||||
|
||||
lua_pushlightuserdata(L, s); // [LumixAPI, obj, refl::struct]
|
||||
lua_pushcclosure(L, lua_struct_var_setter, "struct_var_setter", 1); // [LumixAPI, obj, var_setter]
|
||||
lua_setfield(L, -2, "__newindex"); // [LumixAPI, obj]
|
||||
|
||||
lua_pushvalue(L, -1); // [LumixAPI, obj, obj]
|
||||
auto creator = [](lua_State* L) -> int {
|
||||
auto* s = LuaWrapper::getClosureObject<reflection::StructBase>(L);
|
||||
void* obj = s->createInstance(getGlobalAllocator());
|
||||
LuaWrapper::pushObject(L, obj, s->name);
|
||||
return 1;
|
||||
};
|
||||
|
||||
auto destroyer = [](lua_State* L) -> int {
|
||||
auto* s = LuaWrapper::getClosureObject<reflection::StructBase>(L);
|
||||
LuaWrapper::checkTableArg(L, 1);
|
||||
void* obj;
|
||||
if (!LuaWrapper::checkField(L, 1, "_value", &obj)) {
|
||||
luaL_argerror(L, 1, "expected object");
|
||||
}
|
||||
s->destroyInstance(obj, getGlobalAllocator());
|
||||
return 0;
|
||||
};
|
||||
|
||||
lua_pushlightuserdata(L, s); // [LumixAPI, obj, obj, refl::struct]
|
||||
lua_pushcclosure(L, creator, "create", 1); // [LumixAPI, obj, obj, closure]
|
||||
lua_setfield(L, -2, "create"); // [LumixAPI, obj, obj]
|
||||
|
||||
lua_pushlightuserdata(L, s); // [LumixAPI, obj, obj, refl::struct]
|
||||
lua_pushcclosure(L, destroyer, "destroy", 1); // [LumixAPI, obj, obj, closure]
|
||||
lua_setfield(L, -2, "destroy"); // [LumixAPI, obj, obj]
|
||||
lua_pop(L, 1); // [LumixAPI, obj ]
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
for (auto* f : reflection::allFunctions()) {
|
||||
char tmp_obj_type_name[128];
|
||||
copyString(Span(tmp_obj_type_name), f->getThisTypeName());
|
||||
|
|
|
@ -2392,7 +2392,7 @@ struct PhysicsModuleImpl final : PhysicsModule
|
|||
PhysicsModuleImpl* module;
|
||||
};
|
||||
|
||||
EntityPtr sweepSphere(const DVec3& pos, float radius, const Vec3& dir, float distance, EntityPtr ignored, i32 layer) override {
|
||||
bool sweepSphere(const DVec3& pos, float radius, const Vec3& dir, float distance, SweepHit& result, EntityPtr ignored, i32 layer) override {
|
||||
PxSweepBuffer hit;
|
||||
physx::PxSphereGeometry sphere(radius);
|
||||
physx::PxTransform transform(toPhysx(pos), physx::PxIdentity);
|
||||
|
@ -2403,9 +2403,11 @@ struct PhysicsModuleImpl final : PhysicsModule
|
|||
PxQueryFilterData filter_data;
|
||||
filter_data.flags = PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER;
|
||||
if (!m_scene->sweep(sphere, transform, toPhysx(dir), distance, hit, physx::PxHitFlag::eDEFAULT, filter_data, &filter)) return INVALID_ENTITY;
|
||||
if (!hit.hasBlock) return INVALID_ENTITY;
|
||||
const EntityRef hit_entity = {(int)(intptr_t)hit.block.actor->userData};
|
||||
return hit_entity;
|
||||
if (!hit.hasBlock) return false;
|
||||
result.entity = EntityPtr{(int)(intptr_t)hit.block.actor->userData};
|
||||
result.position = fromPhysx(hit.block.position);
|
||||
result.normal = fromPhysx(hit.block.normal);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool raycastEx(const Vec3& origin,
|
||||
|
@ -3961,9 +3963,20 @@ void PhysicsModule::reflect() {
|
|||
return "N/A";
|
||||
}
|
||||
};
|
||||
|
||||
reflection::structure<RaycastHit>("RaycastHit")
|
||||
.member<&RaycastHit::position>("position")
|
||||
.member<&RaycastHit::normal>("normal")
|
||||
.member<&RaycastHit::entity>("entity");
|
||||
|
||||
reflection::structure<SweepHit>("SweepHit")
|
||||
.member<&SweepHit::position>("position")
|
||||
.member<&SweepHit::normal>("normal")
|
||||
.member<&SweepHit::entity>("entity");
|
||||
|
||||
LUMIX_MODULE(PhysicsModuleImpl, "physics")
|
||||
.LUMIX_FUNC(raycast)
|
||||
.LUMIX_FUNC(raycastEx)
|
||||
.LUMIX_FUNC(sweepSphere)
|
||||
.LUMIX_FUNC(setGravity)
|
||||
.LUMIX_CMP(D6Joint, "d6_joint", "Physics / Joint / D6")
|
||||
|
|
|
@ -40,13 +40,17 @@ struct World;
|
|||
template <typename T> struct DelegateList;
|
||||
|
||||
|
||||
struct RaycastHit
|
||||
{
|
||||
struct RaycastHit {
|
||||
Vec3 position;
|
||||
Vec3 normal;
|
||||
EntityPtr entity;
|
||||
};
|
||||
|
||||
struct SweepHit {
|
||||
Vec3 position;
|
||||
Vec3 normal;
|
||||
EntityPtr entity;
|
||||
};
|
||||
|
||||
struct LUMIX_PHYSICS_API PhysicsModule : IModule
|
||||
{
|
||||
|
@ -91,7 +95,7 @@ struct LUMIX_PHYSICS_API PhysicsModule : IModule
|
|||
virtual void forceUpdateDynamicActors(float time_delta) = 0;
|
||||
virtual const Array<EntityRef>& getDynamicActors() = 0;
|
||||
virtual void render() = 0;
|
||||
virtual EntityPtr sweepSphere(const DVec3& pos, float radius, const Vec3& dir, float distance, EntityPtr ignored, i32 layer) = 0;
|
||||
virtual bool sweepSphere(const DVec3& pos, float radius, const Vec3& dir, float distance, SweepHit& result, EntityPtr ignored, i32 layer) = 0;
|
||||
virtual EntityPtr raycast(const Vec3& origin, const Vec3& dir, float distance, EntityPtr ignore_entity) = 0;
|
||||
virtual bool raycastEx(const Vec3& origin, const Vec3& dir, float distance, RaycastHit& result, EntityPtr ignored, int layer) = 0;
|
||||
virtual void setGravity(const Vec3& gravity) = 0;
|
||||
|
|
Loading…
Reference in New Issue