diff --git a/Editor/resources/Scenes/test.scene b/Editor/resources/Scenes/test.scene index e2584be9..53b30e83 100644 --- a/Editor/resources/Scenes/test.scene +++ b/Editor/resources/Scenes/test.scene @@ -1,5 +1,40 @@ { "Entities": [ + { + "CharacterControllerComponent": { + "Height": 1.2000000476837158, + "Mass": 2500.0, + "Radius": 0.20000000298023224 + }, + "NameComponent": { + "Name": "Player" + }, + "ParentComponent": { + "HasParent": false + }, + "TransformComponent": { + "Rotation": { + "x": 0.0, + "y": -0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.0, + "y": 1.0, + "z": 1.0 + }, + "Translation": { + "x": -15.681736946105957, + "y": 17.139999389648438, + "z": 10.975672721862793 + }, + "Type": "TransformComponent" + }, + "WrenScriptComponent": { + "Class": "PlayerScript", + "Script": "Scripts/Player.wren" + } + }, { "NameComponent": { "Name": "Trenchbroom map" @@ -8,7 +43,7 @@ "HasParent": false }, "QuakeMapComponent": { - "HasCollisions": false, + "HasCollisions": true, "Path": "C:\\Dev\\Nuake\\Editor\\resources\\Maps\\texture_test.map" }, "TransformComponent": { @@ -43,7 +78,7 @@ "y": 0.9591699838638306, "z": 0.20000000298023224 }, - "IsVolumetric": false, + "IsVolumetric": true, "Strength": 10.0, "SyncDirectionWithSky": true, "Type": 0 @@ -66,11 +101,54 @@ "z": 1.0 }, "Translation": { - "x": 7.035792350769043, - "y": 5.795107364654541, - "z": -0.9431453943252563 + "x": -359.2229919433594, + "y": -1.979316234588623, + "z": -322.51702880859375 }, "Type": "TransformComponent" + }, + "WrenScriptComponent": { + "Class": "TestScript", + "Script": "Scripts/entityScript.wren" + } + }, + { + "CameraComponent": { + "CameraInstance": { + "AspectRatio": 1.7106741666793823, + "Exposure": 1.0, + "Fov": 88.0, + "Speed": 1.0, + "m_Type": 1 + } + }, + "NameComponent": { + "Name": "Camera" + }, + "ParentComponent": { + "HasParent": false + }, + "TransformComponent": { + "Rotation": { + "x": 0.0, + "y": -0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.0, + "y": 1.0, + "z": 1.0 + }, + "Translation": { + "x": 0.0, + "y": 0.75, + "z": 0.0 + }, + "Type": "TransformComponent" + }, + "WrenScriptComponent": { + "Class": "CamScript", + "Script": "Scripts/Cam.wren" } } ], @@ -78,7 +156,7 @@ "m_Environement": { "AmbientColor": { "w": 0.0, - "x": null, + "x": 0.0, "y": 0.0, "z": 0.0 }, diff --git a/Editor/resources/Scripts/Cam.wren b/Editor/resources/Scripts/Cam.wren new file mode 100644 index 00000000..0997ee99 --- /dev/null +++ b/Editor/resources/Scripts/Cam.wren @@ -0,0 +1,60 @@ +import "Scripts/ScriptableEntity" for ScriptableEntity +import "Scripts/Engine" for Engine +import "Scripts/Scene" for Scene +import "Scripts/Math" for Vector3, Math +import "Scripts/Input" for Input + +class CamScript is ScriptableEntity { + + construct new() { + _Pitch = 0 + _Yaw = 0 + + _mouseLastX = 0 + _mouseLastY = 0 + Input.HideMouse() + } + + init() { + + } + + update(ts) { + var x = Input.GetMouseX() + var y = Input.GetMouseY() + + var diffx = x - _mouseLastX + var diffy = _mouseLastY - y + _mouseLastX = x + _mouseLastY = y + + var sens = 0.1 + + diffx = diffx * sens + diffy = diffy * sens + + _Yaw = _Yaw + diffx + _Pitch = _Pitch + diffy + if(_Pitch > 89) _Pitch = 89 + if(_Pitch < -89) _Pitch = -89 + + var cam = this.GetComponent("Camera") + + var rad_yaw = Math.Radians(_Yaw) + var rad_pitch = Math.Radians(_Pitch) + var camX = Math.Cos(rad_yaw) * Math.Cos(rad_pitch) + var camY = Math.Sin(rad_pitch) + var camZ = Math.Sin(rad_yaw) * Math.Cos(rad_pitch) + + var newDir = Vector3.new(camX, camY, camZ) + + cam.SetDirection(newDir) + } + + CheckInput() { + + } + + exit() { + } +} \ No newline at end of file diff --git a/Editor/resources/Scripts/Math.wren b/Editor/resources/Scripts/Math.wren index 533ebbb5..b97a7b04 100644 --- a/Editor/resources/Scripts/Math.wren +++ b/Editor/resources/Scripts/Math.wren @@ -1,5 +1,16 @@ class Math { foreign static Sqrt_(x, y, z) + foreign static Sin(s) + foreign static Cos(s) + foreign static Radians(s) + foreign static Degrees(s) + + static Cross(vec1, vec2) { + var result = this.Cross_(vec1.x, vec1.y, vec1.z, vec2.x, vec2.y, vec2.z) + return Vector3.new(result[0], result[1], result[2]) + } + + foreign static Cross_(x, y, z, x1, y2, z2) } class Vector3 { @@ -7,6 +18,7 @@ class Vector3 { x {_x} y {_y} z {_z} + x=(value) { _x = value } @@ -49,6 +61,18 @@ class Vector3 { } } + -(other) { + if(other is Vector3) { + return Vector3.new(_x - other.x, + _y - other.y, + _z - other.z) + } else if(other is Num) { + return Vector3.new(_x - other, + _y - other, + _z - other) + } + } + construct new(x, y, z) { _x = x _y = y @@ -59,6 +83,10 @@ class Vector3 { return Math.Sqrt_(_x, _y, _z) } + Cross(vec) { + Math.Cross(this, vec) + } + Normalize() { var length = this.Sqrt() var x = _x / length diff --git a/Editor/resources/Scripts/Physics.wren b/Editor/resources/Scripts/Physics.wren new file mode 100644 index 00000000..96464056 --- /dev/null +++ b/Editor/resources/Scripts/Physics.wren @@ -0,0 +1,28 @@ +import "Scripts/Math" for Vector3 + +class CollisionResult { + + LocalPosition { _Local} + WorldPosition { _World} + Normal { _Normal} + + construct new(l, w, n) { + _Local = l + _World = w + _Normal = n + } +} + +class Physics { + foreign static Raycast_(x, y, z, x2, y2, z2) + + static Raycast(v1, v2) { + var result = this.Raycast_(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z) + + var local = Vector3.new(result[0], result[1], result[2]) + var world = Vector3.new(result[3], result[4], result[5]) + var normal = Vector3.new(result[6], result[7], result[8]) + + return CollisionResult.new(local, world, normal) + } +} \ No newline at end of file diff --git a/Editor/resources/Scripts/Player.wren b/Editor/resources/Scripts/Player.wren new file mode 100644 index 00000000..57750e05 --- /dev/null +++ b/Editor/resources/Scripts/Player.wren @@ -0,0 +1,99 @@ +import "Scripts/ScriptableEntity" for ScriptableEntity +import "Scripts/Engine" for Engine +import "Scripts/Scene" for Scene +import "Scripts/Math" for Vector3 +import "Scripts/Input" for Input +import "Scripts/Physics" for Physics, CollisionResult + +class PlayerScript is ScriptableEntity { + + construct new() { + _InputDir = Vector3.new(0, 0, 0) + _Velocity = Vector3.new(0, 0, 0) + _Accel = 150 + _Deccel = 0.92 + _AirDeccel = 0.7 + _Gravity = 20 + + _MaxSpeed = 20 + _Jump = 800 + //Input.HideMouse() + } + + init() { + Engine.Log("Player init") + } + + update(ts) { + this.CheckInput() + + var camEntity = Scene.GetEntity("Camera") + var cam = camEntity.GetComponent("Camera") + + var dir = cam.GetDirection() + dir.y = 0 + dir = dir.Normalize() + + var right = cam.GetRight() + right.y = 0 + right = right.Normalize() + var new_Velocity = (dir * _InputDir.z) + (right * _InputDir.x) + + var controller = this.GetComponent("CharacterController") + var transform = this.GetComponent("Transform") + + + var from = transform.GetTranslation() + var to = from - Vector3.new(0, 1, 0) + + var normal = Physics.Raycast(from, to).Normal.Normalize() + + Engine.Log("Normal col: (%(normal.x), %(normal.y), %(normal.z))") + + if(!controller.IsOnGround()) { + _Velocity.y = _Velocity.y - _Gravity + //_Velocity.x = _Velocity.x * _AirDeccel + //_Velocity.z = _Velocity.z * _AirDeccel + } else { + _Velocity.y = -20 + + if(Input.IsKeyPressed(32)) _Velocity.y = _Jump + + + _Velocity.x = _Velocity.x + new_Velocity.x * _Accel + _Velocity.z = _Velocity.z + new_Velocity.z * _Accel + _Velocity.x = _Velocity.x * _Deccel + _Velocity.z = _Velocity.z * _Deccel + } + controller.MoveAndSlide(_Velocity * ts) + } + + CheckInput() { + /* + 87 = W + 65 = A + 83 = S + 68 = D + 32 = SPACE + */ + if(Input.IsKeyDown(87)) { + _InputDir.z = 1 + } else if(Input.IsKeyDown(83)) { + _InputDir.z = -1 + } else { + _InputDir.z = 0 + } + if(Input.IsKeyDown(65)) { + _InputDir.x = 1 + } else if(Input.IsKeyDown(68)) { + _InputDir.x = -1 + } else { + _InputDir.x = 0 + } + + } + + exit() { + Engine.Log("Player exit") + } +} \ No newline at end of file diff --git a/Editor/resources/Scripts/Scene.wren b/Editor/resources/Scripts/Scene.wren index 4f6b5f36..f82f1a94 100644 --- a/Editor/resources/Scripts/Scene.wren +++ b/Editor/resources/Scripts/Scene.wren @@ -24,6 +24,8 @@ class Scene { return CharacterController.new(id) } else if (component == "Camera") { return Camera.new(id) + } else if (component == "Transform") { + return TransformComponent.new(id) } } @@ -32,6 +34,7 @@ class Scene { // Components // // Transform + foreign static GetTranslation_(e) //foreign static SetTranslation_(e, x, y, z) //foreign static SetRotation_(e, x, y, z) //foreign static SetScale_(e, x, y, z) @@ -53,6 +56,7 @@ class Scene { // Character controller foreign static MoveAndSlide_(e, x, y, z) + foreign static IsCharacterControllerOnGround_(e) //foreign static IsOnGround_(e) @@ -97,6 +101,19 @@ class Entity { */ } +class TransformComponent { + construct new(id) { + _entityId = id + } + + GetTranslation() { + var result = Scene.GetTranslation_(_entityId) + return Vector3.new(result[0], result[1], result[2]) + } + + +} + class Light { construct new(id) { _entityId = id @@ -131,6 +148,10 @@ class CharacterController { MoveAndSlide(vel) { Scene.MoveAndSlide_(_entityId, vel.x, vel.y, vel.z) } + + IsOnGround() { + return Scene.IsCharacterControllerOnGround_(_entityId) + } } class Camera { diff --git a/Editor/resources/Scripts/entityScript.wren b/Editor/resources/Scripts/entityScript.wren new file mode 100644 index 00000000..a5fe55d4 --- /dev/null +++ b/Editor/resources/Scripts/entityScript.wren @@ -0,0 +1,23 @@ +import "Scripts/Engine" for Engine +import "Scripts/ScriptableEntity" for ScriptableEntity + + +class TestScript is ScriptableEntity { + construct new() { + _deltaTime = 0 + } + + init() { + Engine.Log("Hello init") + } + + update(ts) { + _deltaTime = _deltaTime + ts + + + } + + exit() { + Engine.Log("Hello exit") + } +} \ No newline at end of file diff --git a/Editor/resources/Scripts/test.wren b/Editor/resources/Scripts/test.wren index 67320b50..efea8ff9 100644 --- a/Editor/resources/Scripts/test.wren +++ b/Editor/resources/Scripts/test.wren @@ -1,27 +1,23 @@ import "Scripts/Engine" for Engine -import "Scripts/Input" for Input import "Scripts/Scene" for Scene, Entity class Test { + construct new() {} + init() { System.print("hello init") } - update(t) { - System.print("hello update %(t)") - } - - exit() { - System.print("hello exit ") - } - + // Gets called on the click event. static hello() { + // Get the entity named Light var entity = Scene.GetEntity("Light") - var light = entity.GetComponent("Light") - light.SetIntensity(1.0) - if(Input.IsMouseButtonPressed(2) == true) { - Engine.Log("RIGHT CLICK!!!!!!") - } + // Get the component light + var light = entity.GetComponent("Light") + //light.SetIntensity(222.0) // Change intensity + + var currentIntensity = light.GetIntensity() // Get new intensity + Engine.Log("Current intensity %(currentIntensity)") } -} \ No newline at end of file +} diff --git a/Editor/resources/test.project b/Editor/resources/test.project index b53f6d95..0f6fa6b9 100644 --- a/Editor/resources/test.project +++ b/Editor/resources/test.project @@ -1 +1 @@ -{"Description":"","Name":"", "DefaultScene":"Scenes/test.scene"} \ No newline at end of file +{"DefaultScene":"Scenes/test.scene","Description":"","Name":""} \ No newline at end of file diff --git a/Editor/src/EditorInterface.cpp b/Editor/src/EditorInterface.cpp index 275cd48e..bf1d8803 100644 --- a/Editor/src/EditorInterface.cpp +++ b/Editor/src/EditorInterface.cpp @@ -35,7 +35,7 @@ void EditorInterface::Init() ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); ImGui::DockSpaceOverViewport(viewport, dockspace_flags); - this->filesystem = FileSystemUI(); + //this->filesystem = FileSystemUI(); } @@ -854,7 +854,7 @@ void EditorInterface::DrawRessourceWindow() textureID = m_SelectedMaterial->m_Normal->GetID(); if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image3"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec2(2,2), ImVec4(0,0,0,1), ImVec4(1, 1, 1, 1))) { - std::string texture = FileDialog::OpenFile("*.png|*.jpg"); + std::string texture = FileDialog::OpenFile("*.png"); if (texture != "") { m_SelectedMaterial->SetNormal(TextureManager::Get()->GetTexture(texture)); @@ -1130,13 +1130,13 @@ void EditorInterface::Draw() DrawRessourceWindow(); DrawViewport(); DrawSceneTree(); - DrawFileSystem(); - DrawDirectoryExplorer(); + //DrawDirectoryExplorer(); DrawEntityPropreties(); DrawLogger(); // new stuff filesystem.Draw(); + filesystem.DrawDirectoryExplorer(); if(m_ShowImGuiDemo) ImGui::ShowDemoWindow(); diff --git a/Editor/src/EditorInterface.h b/Editor/src/EditorInterface.h index 4e3d5663..fafe0c1f 100644 --- a/Editor/src/EditorInterface.h +++ b/Editor/src/EditorInterface.h @@ -9,7 +9,7 @@ class Material; class EditorInterface { private: - FileSystemUI filesystem; + FileSystemUI filesystem = FileSystemUI(); Entity m_SelectedEntity; bool m_IsEntitySelected = false; bool m_DrawGrid = false; diff --git a/Editor/src/FileSystemUI.cpp b/Editor/src/FileSystemUI.cpp index 3772a1c6..9dba73df 100644 --- a/Editor/src/FileSystemUI.cpp +++ b/Editor/src/FileSystemUI.cpp @@ -34,7 +34,7 @@ void FileSystemUI::Draw() } if (open) { - //EditorInterfaceDrawFiletree(rootDirectory); + EditorInterfaceDrawFiletree(rootDirectory); ImGui::TreePop(); } } @@ -88,6 +88,12 @@ void FileSystemUI::DrawDirectory(Ref directory) std::string id = ICON_FA_FOLDER + std::string("##") + directory->name; if (ImGui::Button(id.c_str(), ImVec2(100, 100))) m_CurrentDirectory = directory; + if (ImGui::BeginPopupContextWindow()) + { + if (ImGui::MenuItem("Htest")); + + ImGui::EndPopup(); + } ImGui::Text(directory->name.c_str()); ImGui::PopFont(); } @@ -199,6 +205,54 @@ void FileSystemUI::DrawDirectoryExplorer() i++; } } + if (ImGui::BeginPopupContextItem("item context menu")) + { + float value; + if (ImGui::Selectable("Set to zero")) value = 0.0f; + if (ImGui::Selectable("Set to PI")) value = 3.1415f; + ImGui::SetNextItemWidth(-1); + ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f); + ImGui::EndPopup(); + } + if (ImGui::BeginPopupContextWindow()) + { + if (ImGui::Button("New Wren script")) + { + ImGui::OpenPopup("CreateNewFile"); + + } + if (ImGui::MenuItem("New interface script")) + { + } + if (ImGui::MenuItem("New Scene")) + { + } + if (ImGui::MenuItem("New folder")) + { + } + if (ImGui::MenuItem("New interface")) + { + } + if (ImGui::MenuItem("New stylesheet")) + { + } + if (ImGui::BeginPopup("CreateNewFile")) + { + static char name[32] = "Label1"; + char buf[64]; + sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label + + ImGui::Text("Edit name:"); + ImGui::InputText("##edit", name, IM_ARRAYSIZE(name)); + if (ImGui::Button("Close")) + ImGui::CloseCurrentPopup(); + if(ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter))) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + ImGui::EndPopup(); + } + ImGui::EndTable(); } diff --git a/Nuake/Engine.h b/Nuake/Engine.h index 27b54f0e..3ddc81cd 100644 --- a/Nuake/Engine.h +++ b/Nuake/Engine.h @@ -7,6 +7,22 @@ #include "src/Scripting/ScriptLoader.h" #include "src/Core/Logger.h" +/* TODOS: +* +* Engine: +* Trigger zones from trenchbroom +* Scripting API vectors operation +* Scripting API for all component +* Scripting API for editing UI maybe +* Launch game standalone +* Fix physics system +* trenchbroom physics element +* +* Editor: +* File browser refact +* +*/ + class Engine { private: static float m_LastFrameTime; diff --git a/Nuake/src/Core/FileSystem.cpp b/Nuake/src/Core/FileSystem.cpp index eadf4f07..76de6e25 100644 --- a/Nuake/src/Core/FileSystem.cpp +++ b/Nuake/src/Core/FileSystem.cpp @@ -99,7 +99,7 @@ void FileSystem::Scan() RootDirectory = CreateRef(); RootDirectory->Files = std::vector>(); RootDirectory->Directories = std::vector>(); - RootDirectory->name = Root; + RootDirectory->name = FileSystem::AbsoluteToRelative(Root); RootDirectory->fullPath = Root; ScanDirectory(RootDirectory); } diff --git a/Nuake/src/Core/Input.cpp b/Nuake/src/Core/Input.cpp index 043920e2..e09665dc 100644 --- a/Nuake/src/Core/Input.cpp +++ b/Nuake/src/Core/Input.cpp @@ -27,7 +27,7 @@ bool Input::IsKeyPressed(int keycode) bool result = state == GLFW_PRESS; // First time pressed? - if (m_Keys.find(keycode) == m_Keys.end() || m_Keys[keycode] == false) + if (m_Keys.find(keycode) == m_Keys.end() || m_Keys[keycode] == true) { if (result) m_Keys[keycode] = true; diff --git a/Nuake/src/Core/Physics/CharacterController.cpp b/Nuake/src/Core/Physics/CharacterController.cpp index 70c21a63..51000a5e 100644 --- a/Nuake/src/Core/Physics/CharacterController.cpp +++ b/Nuake/src/Core/Physics/CharacterController.cpp @@ -25,7 +25,7 @@ namespace Physics } }; - CharacterController::CharacterController(float height, float radius, float mass) + CharacterController::CharacterController(float height, float radius, float mass, Vector3 position) { m_surfaceHitNormals = std::vector(); @@ -35,12 +35,12 @@ namespace Physics btQuaternion quat = btQuaternion(0, 0, 0); m_Transform = new btTransform(); - m_Transform->setOrigin(btVector3(0.0f, 10.0f, 0.0f)); + m_Transform->setOrigin(btVector3(position.x, position.y, position.z)); m_Transform->setRotation(quat); m_MotionState = new btDefaultMotionState(*m_Transform); - + btVector3 inertia; - m_CollisionShape->calculateLocalInertia(mass, inertia); + //m_CollisionShape->calculateLocalInertia(mass, inertia); btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, m_MotionState, m_CollisionShape, inertia); @@ -52,7 +52,7 @@ namespace Physics rigidBodyCI.m_linearDamping = 0.0f; m_Rigidbody = new btRigidBody(rigidBodyCI); - + m_Rigidbody->setGravity(btVector3(0, 0, 0)); // Keep upright m_Rigidbody->setAngularFactor(0.0f); @@ -71,6 +71,7 @@ namespace Physics void CharacterController::MoveAndSlide(glm::vec3 velocity) { + m_Rigidbody->setGravity(btVector3(0, 0, 0)); m_manualVelocity = velocity; // Sync ghost with actually object m_GhostObject->setWorldTransform(m_Rigidbody->getWorldTransform()); @@ -162,7 +163,7 @@ namespace Physics m_Rigidbody->setLinearVelocity(vel); - m_onGround = true; + IsOnGround = true; } float testOffset = 0.07f; @@ -189,8 +190,8 @@ namespace Physics void CharacterController::UpdateVelocity() { - m_manualVelocity.y = m_Rigidbody->getLinearVelocity().getY(); - + //m_manualVelocity.y = m_Rigidbody->getLinearVelocity().getY(); + btVector3 grav = m_Rigidbody->getGravity(); btVector3 finalVel = btVector3(m_manualVelocity.x, m_manualVelocity.y, m_manualVelocity.z); m_Rigidbody->setLinearVelocity(finalVel); diff --git a/Nuake/src/Core/Physics/CharacterController.h b/Nuake/src/Core/Physics/CharacterController.h index ac886b80..7584d0b9 100644 --- a/Nuake/src/Core/Physics/CharacterController.h +++ b/Nuake/src/Core/Physics/CharacterController.h @@ -5,6 +5,7 @@ #include #include +#include "../Core/Maths.h" namespace Physics { class CharacterController @@ -12,14 +13,14 @@ namespace Physics public: bool IsOnGround = false; bool m_hittingWall; - float m_stepHeight = 0.05f; + float m_stepHeight = .1f; btTransform* m_Transform; btCollisionShape* m_CollisionShape; btRigidBody* m_Rigidbody; btPairCachingGhostObject* m_GhostObject; btMotionState* m_MotionState; - bool m_onGround; + //bool m_onJumpableGround; // A bit lower contact than just onGround float m_bottomYOffset; @@ -33,7 +34,7 @@ namespace Physics btVector3 m_previousPosition; float m_jumpRechargeTimer; - CharacterController(float height, float radius, float mass); + CharacterController(float height, float radius, float mass, Vector3 position); void MoveAndSlide(glm::vec3 velocity); private: diff --git a/Nuake/src/Core/Physics/DynamicWorld.cpp b/Nuake/src/Core/Physics/DynamicWorld.cpp index f1947c3c..d16825a4 100644 --- a/Nuake/src/Core/Physics/DynamicWorld.cpp +++ b/Nuake/src/Core/Physics/DynamicWorld.cpp @@ -21,6 +21,8 @@ namespace Physics dynamicsWorld->setDebugDrawer(new BulletDebugDrawer()); m_Bodies = std::map>(); + + SetGravity(Vector3(0, -10000, 0)); } @@ -58,12 +60,18 @@ namespace Physics btCollisionWorld::ClosestRayResultCallback res(btFrom, btTo); dynamicsWorld->rayTest(btFrom, btTo, res); - + btVector3 localNormal; + if(res.m_collisionObject) + { + // TODO: Fix the godammn fucked up normal + localNormal = res.m_collisionObject->getWorldTransform().getBasis().inverse() * res.m_hitNormalWorld; + } + // Map bullet result to dto. RaycastResult result{ glm::vec3(res.m_hitPointWorld.x(), res.m_hitPointWorld.y(), res.m_hitPointWorld.z()), glm::vec3(res.m_hitPointWorld.x(), res.m_hitPointWorld.y(), res.m_hitPointWorld.z()), - glm::vec3(res.m_hitNormalWorld.x(), res.m_hitNormalWorld.y(), res.m_hitNormalWorld.z()) + glm::vec3(localNormal.x(), localNormal.y(), localNormal.z()) }; return result; diff --git a/Nuake/src/Scene/Entities/Components/CharacterControllerComponent.h b/Nuake/src/Scene/Entities/Components/CharacterControllerComponent.h index 5892b073..dfd85b18 100644 --- a/Nuake/src/Scene/Entities/Components/CharacterControllerComponent.h +++ b/Nuake/src/Scene/Entities/Components/CharacterControllerComponent.h @@ -15,6 +15,21 @@ public: } + json Serialize() { + BEGIN_SERIALIZE(); + SERIALIZE_VAL(Height); + SERIALIZE_VAL(Radius); + SERIALIZE_VAL(Mass); + END_SERIALIZE(); + } + + bool Deserialize(const std::string str) { + BEGIN_DESERIALIZE(); + Height = j["Height"]; + Radius = j["Radius"]; + Mass = j["Mass"]; + return true; + } void SyncWithTransform(TransformComponent& tc) { btVector3 pos = CharacterController->m_motionTransform.getOrigin(); diff --git a/Nuake/src/Scene/Entities/Components/NameComponent.h b/Nuake/src/Scene/Entities/Components/NameComponent.h index cea42e9d..6a527c3c 100644 --- a/Nuake/src/Scene/Entities/Components/NameComponent.h +++ b/Nuake/src/Scene/Entities/Components/NameComponent.h @@ -4,7 +4,7 @@ class NameComponent { public: std::string Name = "Entity"; - + int Id; json Serialize() { BEGIN_SERIALIZE(); diff --git a/Nuake/src/Scene/Entities/Components/ParentComponent.h b/Nuake/src/Scene/Entities/Components/ParentComponent.h index a314d83f..45bbbf87 100644 --- a/Nuake/src/Scene/Entities/Components/ParentComponent.h +++ b/Nuake/src/Scene/Entities/Components/ParentComponent.h @@ -19,6 +19,7 @@ struct ParentComponent bool Deserialize(std::string str) { + return true; } diff --git a/Nuake/src/Scene/Entities/Components/QuakeMap.cpp b/Nuake/src/Scene/Entities/Components/QuakeMap.cpp index 497132da..8feb86ff 100644 --- a/Nuake/src/Scene/Entities/Components/QuakeMap.cpp +++ b/Nuake/src/Scene/Entities/Components/QuakeMap.cpp @@ -78,9 +78,9 @@ void QuakeMapComponent::Build() vertex_uv vertex_uv = get_standard_uv(vertex.vertex, face, texture->width, texture->height); vertices.push_back(Vertex{ glm::vec3(vertex.vertex.y * (1.0f / 64), vertex.vertex.z * (1.0f / 64), vertex.vertex.x * (1.0f / 64)), - glm::vec2(vertex_uv.u, vertex_uv.v), - glm::vec3(vertex.normal.x, vertex.normal.z, vertex.normal.y), - glm::vec3(vertex.tangent.x, vertex.tangent.z, vertex.tangent.y), glm::vec3(0.0, 1.0, 0.0), 0.0f + glm::vec2(vertex_uv.u, 1.0 -vertex_uv.v), + glm::vec3(vertex.normal.y, vertex.normal.z, vertex.normal.x), + glm::vec3(vertex.tangent.y, vertex.tangent.z, vertex.tangent.x), glm::vec3(0.0, 1.0, 0.0), 0.0f }); //printf("vertex: (%f %f %f), normal: (%f %f %f)\n", diff --git a/Nuake/src/Scene/Entities/Components/QuakeMap.h b/Nuake/src/Scene/Entities/Components/QuakeMap.h index f7345ba3..2d4d21c0 100644 --- a/Nuake/src/Scene/Entities/Components/QuakeMap.h +++ b/Nuake/src/Scene/Entities/Components/QuakeMap.h @@ -32,6 +32,7 @@ public: { BEGIN_DESERIALIZE(); this->Path = j["Path"]; + this->HasCollisions = j["HasCollisions"]; Build(); // Maybe have some kind of loading bar or something. return true; } diff --git a/Nuake/src/Scene/Entities/Entity.cpp b/Nuake/src/Scene/Entities/Entity.cpp index 895851ba..c93529a2 100644 --- a/Nuake/src/Scene/Entities/Entity.cpp +++ b/Nuake/src/Scene/Entities/Entity.cpp @@ -9,6 +9,7 @@ #include "Components/LightComponent.h" #include "Components/QuakeMap.h" #include +#include void Entity::AddChild(Entity ent) { if ((int)m_EntityHandle != ent.GetHandle()) @@ -34,6 +35,8 @@ json Entity::Serialize() SERIALIZE_OBJECT_REF_LBL("LightComponent", GetComponent()); if (HasComponent()) SERIALIZE_OBJECT_REF_LBL("WrenScriptComponent", GetComponent()); + if (HasComponent()) + SERIALIZE_OBJECT_REF_LBL("CharacterControllerComponent", GetComponent()); END_SERIALIZE(); } @@ -47,6 +50,7 @@ bool Entity::Deserialize(const std::string& str) DESERIALIZE_COMPONENT(QuakeMapComponent); DESERIALIZE_COMPONENT(LightComponent); DESERIALIZE_COMPONENT(WrenScriptComponent); + DESERIALIZE_COMPONENT(CharacterControllerComponent); return true; } diff --git a/Nuake/src/Scene/Scene.cpp b/Nuake/src/Scene/Scene.cpp index 1cfacf9d..990749de 100644 --- a/Nuake/src/Scene/Scene.cpp +++ b/Nuake/src/Scene/Scene.cpp @@ -76,7 +76,7 @@ void Scene::OnInit() { auto [transform, cc] = ccview.get(e); - cc.CharacterController = CreateRef(cc.Height, cc.Radius, cc.Mass); + cc.CharacterController = CreateRef(cc.Height, cc.Radius, cc.Mass, transform.Translation); Entity ent = Entity({ e, this }); PhysicsManager::Get()->RegisterCharacterController(cc.CharacterController); @@ -325,7 +325,7 @@ void Scene::Draw() } Renderer::m_Shader->Bind(); - + Renderer::m_Shader->SetUniform3f("u_EyePosition", cam->GetTranslation().x, cam->GetTranslation().y, cam->GetTranslation().z); Renderer::m_Shader->SetUniform1i("u_ShowNormal", 0); if (cam) { @@ -348,6 +348,8 @@ void Scene::Draw() copyT.Translation = globalOffset; } + + Renderer::m_Shader->SetUniformMat4f("u_View", cam->GetTransform()); Renderer::m_Shader->SetUniformMat4f("u_Projection", cam->GetPerspective()); Renderer::m_Shader->SetUniformMat4f("u_Model", copyT.GetTransform()); @@ -433,7 +435,7 @@ void Scene::EditorDraw() if (m_EditorCamera) { Renderer::m_Shader->SetUniform1f("u_Exposure", m_EditorCamera->Exposure); - + Renderer::m_Shader->SetUniform3f("u_EyePosition", m_EditorCamera->GetTranslation().x, m_EditorCamera->GetTranslation().y, m_EditorCamera->GetTranslation().z); auto view = m_Registry.view(); for (auto e : view) { auto [transform, model, parent] = view.get(e); diff --git a/Nuake/src/Scripting/Modules/MathModule.h b/Nuake/src/Scripting/Modules/MathModule.h index 2cd0d862..8fe284c1 100644 --- a/Nuake/src/Scripting/Modules/MathModule.h +++ b/Nuake/src/Scripting/Modules/MathModule.h @@ -22,7 +22,11 @@ namespace ScriptAPI void RegisterModule(WrenVM* vm) override { RegisterMethod("Sqrt_(_,_,_)", (void*)Sqrt); - + RegisterMethod("Sin(_)", (void*)Sin); + RegisterMethod("Cos(_)", (void*)Cos); + RegisterMethod("Radians(_)", (void*)Radians); + RegisterMethod("Degrees(_)", (void*)Degrees); + RegisterMethod("Cross_(_,_,_,_,_,_)", (void*)Cross); } static void Sqrt(WrenVM* vm) @@ -33,6 +37,55 @@ namespace ScriptAPI float result = glm::sqrt((x * x) + (y * y) + (z * z)); wrenSetSlotDouble(vm, 0, result); } + + static void Cos(WrenVM* vm) + { + float d = wrenGetSlotDouble(vm, 1); + float result = glm::cos(d); + wrenSetSlotDouble(vm, 0, result); + } + + static void Sin(WrenVM* vm) + { + float d = wrenGetSlotDouble(vm, 1); + float result = glm::sin(d); + wrenSetSlotDouble(vm, 0, result); + } + + static void Radians(WrenVM* vm) + { + float d = wrenGetSlotDouble(vm, 1); + float result = glm::radians(d); + wrenSetSlotDouble(vm, 0, result); + } + + static void Degrees(WrenVM* vm) + { + float d = wrenGetSlotDouble(vm, 1); + float result = glm::degrees(d); + wrenSetSlotDouble(vm, 0, result); + } + + static void Cross(WrenVM* vm) + { + Vector3 v1 = Vector3(wrenGetSlotDouble(vm, 1), + wrenGetSlotDouble(vm, 2), + wrenGetSlotDouble(vm, 3)); + Vector3 v2 = Vector3(wrenGetSlotDouble(vm, 4), + wrenGetSlotDouble(vm, 5), + wrenGetSlotDouble(vm, 6)); + Vector3 cross = glm::cross(v1, v2); + + + wrenSetSlotNewList(vm, 0); + wrenSetSlotDouble(vm, 1, cross.x); + wrenSetSlotDouble(vm, 2, cross.y); + wrenSetSlotDouble(vm, 3, cross.z); + + wrenInsertInList(vm, 0, -1, 1); + wrenInsertInList(vm, 0, -1, 2); + wrenInsertInList(vm, 0, -1, 3); + } }; diff --git a/Nuake/src/Scripting/Modules/PhysicsModule.h b/Nuake/src/Scripting/Modules/PhysicsModule.h new file mode 100644 index 00000000..7ebeae48 --- /dev/null +++ b/Nuake/src/Scripting/Modules/PhysicsModule.h @@ -0,0 +1,63 @@ +#pragma once +#include "wren.h" +#include +#include +#include "../Core/Maths.h" +#include "ScriptModule.h" +#include +#include +#include "../Core/Physics/PhysicsManager.h" +namespace ScriptAPI +{ + class PhysicsModule : public ScriptModule + { + std::string ModuleName = "Engine"; + + std::string GetModuleName() override + { + return "Physics"; + } + + void RegisterModule(WrenVM* vm) override + { + RegisterMethod("Raycast_(_,_,_,_,_,_)", (void*)Raycast); + } + + static void Raycast(WrenVM* vm) + { + Vector3 v1 = Vector3(wrenGetSlotDouble(vm, 1), + wrenGetSlotDouble(vm, 2), + wrenGetSlotDouble(vm, 3)); + Vector3 v2 = Vector3(wrenGetSlotDouble(vm, 4), + wrenGetSlotDouble(vm, 5), + wrenGetSlotDouble(vm, 6)); + + RaycastResult result = PhysicsManager::Get()->Raycast(v1, v2); + wrenSetSlotNewList(vm, 0); + + // Returns a list with 3 vectors placed sequentially + // should be reconstructed in the wren side. + wrenSetSlotDouble(vm, 1, result.LocalPoint.x); + wrenSetSlotDouble(vm, 2, result.LocalPoint.y); + wrenSetSlotDouble(vm, 3, result.LocalPoint.z); + + wrenSetSlotDouble(vm, 4, result.WorldPoint.x); + wrenSetSlotDouble(vm, 5, result.WorldPoint.y); + wrenSetSlotDouble(vm, 6, result.WorldPoint.z); + + wrenSetSlotDouble(vm, 7, result.Normal.x - result.WorldPoint.x); + wrenSetSlotDouble(vm, 8, result.Normal.y - result.WorldPoint.y); + wrenSetSlotDouble(vm, 9, result.Normal.z - result.WorldPoint.z); + + wrenInsertInList(vm, 0, -1, 1); + wrenInsertInList(vm, 0, -1, 2); + wrenInsertInList(vm, 0, -1, 3); + wrenInsertInList(vm, 0, -1, 4); + wrenInsertInList(vm, 0, -1, 5); + wrenInsertInList(vm, 0, -1, 6); + wrenInsertInList(vm, 0, -1, 7); + wrenInsertInList(vm, 0, -1, 8); + wrenInsertInList(vm, 0, -1, 9); + } + }; +} \ No newline at end of file diff --git a/Nuake/src/Scripting/Modules/SceneModule.h b/Nuake/src/Scripting/Modules/SceneModule.h index 2832f3d7..527b8712 100644 --- a/Nuake/src/Scripting/Modules/SceneModule.h +++ b/Nuake/src/Scripting/Modules/SceneModule.h @@ -29,12 +29,14 @@ namespace ScriptAPI { RegisterMethod("GetEntityID(_)", (void*)GetEntity); RegisterMethod("EntityHasComponent(_,_)", (void*)EntityHasComponent); + RegisterMethod("GetTranslation_(_)", (void*)GetTranslation); RegisterMethod("SetLightIntensity_(_,_)", (void*)SetLightIntensity); RegisterMethod("GetLightIntensity_(_)", (void*)GetLightIntensity); RegisterMethod("SetCameraDirection_(_,_,_,_)", (void*)SetCameraDirection); RegisterMethod("GetCameraDirection_(_)", (void*)GetCameraDirection); RegisterMethod("GetCameraRight_(_)", (void*)GetCameraRight); RegisterMethod("MoveAndSlide_(_,_,_,_)", (void*)MoveAndSlide); + RegisterMethod("IsCharacterControllerOnGround_(_)", (void*)IsCharacterControllerOnGround); } static void GetEntity(WrenVM* vm) @@ -158,7 +160,14 @@ namespace ScriptAPI wrenInsertInList(vm, 0, 2, 3); } - + static void IsCharacterControllerOnGround(WrenVM* vm) + { + int handle = wrenGetSlotDouble(vm, 1); + Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get()); + auto& characterController = ent.GetComponent(); + bool result = characterController.CharacterController->IsOnGround; + wrenSetSlotBool(vm, 0, result); + } static void MoveAndSlide(WrenVM* vm) { @@ -172,5 +181,22 @@ namespace ScriptAPI characterController.CharacterController->MoveAndSlide(Vector3(x, y, z)); } + static void GetTranslation(WrenVM* vm) + { + int handle = wrenGetSlotDouble(vm, 1); + Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get()); + auto& transform = ent.GetComponent(); + // set the slots + wrenSetSlotDouble(vm, 1, transform.Translation.x); + wrenSetSlotDouble(vm, 2, transform.Translation.y); + wrenSetSlotDouble(vm, 3, transform.Translation.z); + + // Fill the list + wrenSetSlotNewList(vm, 0); + wrenInsertInList(vm, 0, 0, 1); + wrenInsertInList(vm, 0, 1, 2); + wrenInsertInList(vm, 0, 2, 3); + } + }; } \ No newline at end of file diff --git a/Nuake/src/Scripting/ScriptingEngine.cpp b/Nuake/src/Scripting/ScriptingEngine.cpp index bac7d86d..7ae73ee0 100644 --- a/Nuake/src/Scripting/ScriptingEngine.cpp +++ b/Nuake/src/Scripting/ScriptingEngine.cpp @@ -6,6 +6,7 @@ #include #include #include +#include WrenVM* ScriptingEngine::m_WrenVM; @@ -112,6 +113,8 @@ void ScriptingEngine::Init() RegisterModule(mathModule); Ref inputModule = CreateRef (); RegisterModule(inputModule); + Ref physicsModule = CreateRef(); + RegisterModule(physicsModule); } diff --git a/Nuake/src/Window.cpp b/Nuake/src/Window.cpp index 510aee47..a8f0d58d 100644 --- a/Nuake/src/Window.cpp +++ b/Nuake/src/Window.cpp @@ -153,7 +153,8 @@ int Window::Init() // TODO: Style should move to editor ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; - io.Fonts->AddFontDefault(); + //io.Fonts->AddFontDefault(); + io.Fonts->AddFontFromFileTTF("resources/Fonts/OpenSans-Regular.ttf", 16.0); io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; ImGui::StyleColorsDark(); diff --git a/docs/Scripting/entity_scripts.rst b/docs/Scripting/entity_scripts.rst index e034648c..912e7c9f 100644 --- a/docs/Scripting/entity_scripts.rst +++ b/docs/Scripting/entity_scripts.rst @@ -7,7 +7,7 @@ After attaching the WrenScript component on an entity, you can select the script In addition to pointing to the script file, you need to specify which class in the script is considered as the entity script. -The class chosen must inherite from ScriptableEntity. +The class chosen must inherit from ScriptableEntity. Here is an example of a barebone entity scripts:: @@ -16,13 +16,15 @@ Here is an example of a barebone entity scripts:: class TestScript is ScriptableEntity { construct new() { } - + init() { } update(ts) { + + } exit() {