Jump to content

reepblue

Developers
  • Posts

    2,493
  • Joined

  • Last visited

Everything posted by reepblue

  1. Still no dice. I got my custom Actor Class to work tho. There seems to be an issue with Detach. When CUSTOM_ACTOR is defined, everything works like expected. (Fully custom class based on hooks) vs the class derived from the stock Actor Class. Header: // Temp Actor class until the offical one gets improved. #if !defined(BASEACTOR_H) #define BASEACTOR_H #pragma once #include "Leadwerks.h" #define CUSTOM_ACTOR namespace Leadwerks { #ifdef CUSTOM_ACTOR class BaseActor : public Object { public: Entity* entity; BaseActor() {}; virtual ~BaseActor(); virtual void Attach(); void RemoveHooks(); virtual void Detach(); void Shutdown() { Detach(); }; virtual void Collision(Entity* pEntity, float* position, float* normal, float speed) {}; virtual void UpdateWorld() {}; virtual void UpdatePhysics() {}; virtual void UpdateMatrix() {}; virtual void PostRender(Context* context) {}; virtual void Draw() {}; virtual void DrawEach(Camera* camera) {}; protected: static void CollisionHook(Entity* entity0, Entity* entity1, float* position, float* normal, float speed); static void DrawHook(Entity* entity); static void DrawEachHook(Entity* entity); static void PostRenderHook(Entity* entity); static void UpdateMatrixHook(Entity* entity); static void UpdatePhysicsHook(Entity* entity); static void UpdateWorldHook(Entity* entity); }; inline void AttachEntityToActor(Entity* entity, BaseActor* actor) { actor->entity = entity; actor->Attach(); } inline void DetachEntityFromActor(Entity* entity) { if (entity->GetUserData() != NULL) { BaseActor* actor = (BaseActor*)entity->GetUserData(); actor->RemoveHooks(); delete actor; } } bool DetachAllActors(); #else class BaseActor : public Actor { public: BaseActor(); virtual ~BaseActor(); virtual void Attach(); virtual void Detach(); void AddHooks(); void RemoveHooks(); // Hooks that are not working with actors in 4.2 virtual void UpdateWorld() {}; virtual void UpdatePhysics() {}; virtual void PostRender(Leadwerks::Context* context) {}; protected: static void PostRenderHook(Entity* entity); static void UpdatePhysicsHook(Entity* entity); static void UpdateWorldHook(Entity* entity); }; #endif } #endif CPP: // Temp Actor class until the offical one gets improved. #include "BaseActor.h" std::vector<Leadwerks::BaseActor*> vActors; namespace Leadwerks { #ifdef CUSTOM_ACTOR bool DetachAllActors() { if (vActors.size() <= 0) return false; // Come back to this later... for (auto actor : vActors) { actor->Shutdown(); } vActors.clear(); return true; } void BaseActor::Attach() { if (entity == nullptr) { return; } entity->SetUserData((void*)this); entity->AddHook(Entity::CollisionHook, (void*)CollisionHook); entity->AddHook(Entity::DrawHook, (void*)DrawHook); entity->AddHook(Entity::DrawEachHook, (void*)DrawEachHook); entity->AddHook(Entity::PostRenderHook, (void*)PostRenderHook); entity->AddHook(Entity::UpdateMatrixHook, (void*)UpdateMatrixHook); entity->AddHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook); entity->AddHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook); vActors.push_back((BaseActor*)this); } void BaseActor::RemoveHooks() { if (entity == nullptr) { return; } entity->RemoveHook(Entity::CollisionHook, (void*)CollisionHook); entity->RemoveHook(Entity::DrawHook, (void*)DrawHook); entity->RemoveHook(Entity::DrawEachHook, (void*)DrawEachHook); entity->RemoveHook(Entity::PostRenderHook, (void*)PostRenderHook); entity->RemoveHook(Entity::UpdateMatrixHook, (void*)UpdateMatrixHook); entity->RemoveHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook); entity->RemoveHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook); entity->SetUserData(NULL); } BaseActor::~BaseActor() { //RemoveHooks(); } void BaseActor::Detach() { System::Print("Puppeteer: Detach() was called."); RemoveHooks(); delete this; } void BaseActor::CollisionHook(Entity* entity0, Entity* entity1, float* position, float* normal, float speed) { BaseActor* actor = (BaseActor*)entity0->GetUserData(); if (actor->entity == nullptr) { return; } if (actor != NULL) { actor->Collision(entity1, position, normal, speed); } } void BaseActor::DrawHook(Entity* entity) { BaseActor* actor = (BaseActor*)entity->GetUserData(); if (actor->entity == nullptr) { return; } if (actor != NULL) { //actor->Draw(WORLD->); } } void BaseActor::DrawEachHook(Entity* entity) { BaseActor* actor = (BaseActor*)entity->GetUserData(); if (actor->entity == nullptr) { return; } if (actor != NULL) { //actor->DrawEach(); } } void BaseActor::PostRenderHook(Entity* entity) { BaseActor* actor = (BaseActor*)entity->GetUserData(); if (actor->entity == nullptr) { return; } if (actor != NULL) { actor->PostRender(Leadwerks::Context::GetCurrent()); } } void BaseActor::UpdateMatrixHook(Entity* entity) { BaseActor* actor = (BaseActor*)entity->GetUserData(); if (actor->entity == nullptr) { return; } if (actor != NULL) { actor->UpdateMatrix(); } } void BaseActor::UpdatePhysicsHook(Entity* entity) { BaseActor* actor = (BaseActor*)entity->GetUserData(); if (actor->entity == nullptr) { return; } if (actor != NULL) { actor->UpdatePhysics(); } } void BaseActor::UpdateWorldHook(Entity* entity) { BaseActor* actor = (BaseActor*)entity->GetUserData(); if (actor->entity == nullptr) { return; } if (actor != NULL) { actor->UpdateWorld(); } } #else BaseActor::BaseActor() : Actor() {}; BaseActor::~BaseActor() {}; void BaseActor::Attach() { AddHooks(); } void BaseActor::Detach() { RemoveHooks(); } void BaseActor::AddHooks() { entity->AddHook(Entity::PostRenderHook, (void*)PostRenderHook); entity->AddHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook); entity->AddHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook); } void BaseActor::RemoveHooks() { entity->RemoveHook(Entity::PostRenderHook, (void*)PostRenderHook); entity->RemoveHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook); entity->RemoveHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook); } void BaseActor::PostRenderHook(Entity* entity) { BaseActor* script = (BaseActor*)entity->GetUserData(); Leadwerks::Context* context = Leadwerks::Context::GetCurrent(); if (script != nullptr) { script->PostRender(context); } } void BaseActor::UpdatePhysicsHook(Entity* entity) { BaseActor* script = (BaseActor*)entity->GetActor(); if (script != nullptr) { script->UpdatePhysics(); } } void BaseActor::UpdateWorldHook(Entity* entity) { BaseActor* script = (BaseActor*)entity->GetActor(); if (script != nullptr) { script->UpdateWorld(); } } #endif } Only gotcha with mine is that I need to call this command before clearing/releasing the world. Leadwerks::DetachAllActors();
  2. Seem to be getting crashes when I clear the world. I thought it was because the hooks were not being detached before the actor was, but I disabled my additional hooks and I'm getting the same crash.
  3. I just put it together; can't say I tested it, but this chunk of code is how my Puppeteer class worked. This class derives from the actor class so that the update and post render functions update. BaseActor.h // Temp Actor class until the offical one gets improved. #if !defined(BASEACTOR_H) #define BASEACTOR_H #pragma once #include "Leadwerks.h" namespace Leadwerks { class BaseActor : public Actor { BaseActor(); virtual ~BaseActor(); virtual void Attach(); virtual void Detach(); // Hooks that are not working with actors in 4.2 virtual void UpdateWorld() {}; virtual void UpdatePhysics() {}; virtual void PostRender(Leadwerks::Context* context) {}; protected: static void PostRenderHook(Entity* entity); static void UpdatePhysicsHook(Entity* entity); static void UpdateWorldHook(Entity* entity); }; } #endif BaseActor.cpp // Temp Actor class until the offical one gets improved. #include "BaseActor.h" namespace Leadwerks { BaseActor::BaseActor() : Actor() {}; BaseActor::~BaseActor(){}; void BaseActor::Attach() { Actor::Attach(); entity->AddHook(Entity::PostRenderHook, (void*)PostRenderHook); entity->AddHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook); entity->AddHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook); } void BaseActor::Detach() { entity->RemoveHook(Entity::PostRenderHook, (void*)PostRenderHook); entity->RemoveHook(Entity::UpdatePhysicsHook, (void*)UpdatePhysicsHook); entity->RemoveHook(Entity::UpdateWorldHook, (void*)UpdateWorldHook); Actor::Detach(); } void BaseActor::PostRenderHook(Entity* entity) { BaseActor* script = (BaseActor*)entity->GetUserData(); Leadwerks::Context* context = Leadwerks::Context::GetCurrent(); if (script != nullptr) { script->PostRender(context); } } void BaseActor::UpdatePhysicsHook(Entity* entity) { BaseActor* script = (BaseActor*)entity->GetUserData(); if (script != nullptr) { script->UpdatePhysics(); } } void BaseActor::UpdateWorldHook(Entity* entity) { BaseActor* script = (BaseActor*)entity->GetUserData(); if (script != nullptr) { script->UpdateWorld(); } } } You may need to static cast your Actors based off this when you go to attach the actor to the entity with Entity->SetActor().
  4. It also seems selected objects still pop up in there as well! (Redness)
  5. I expected Editor Hints would get skipped, but they don't.
  6. reepblue

    Anatomy of a Bug

    Really happy to see this bug fixed. Great work!
  7. Just want to mention that Einlander's script is collision based, and mine is aabb based. The difference is that if you wish props to enter with swept collision enabled, the object will collide into the trigger like it's a wall ignoring any collision rules. I haven't tried Einlander's but I'm sure it's also useful. Pretty much, mine mimics Source's BaseTrigger class, and Einlander mimics Unity's. Use whatever works best for you.
  8. I like to post on the forum so if any users who wish to do the same thing, can find it with the search engine. I'm gonna pack all my scripts up in one big chunk when they are fully tested and ironed out.
  9. I forgot IsAABBOverlap.lua. Place in the functions directory. -- Thanks to CrazyCarpet for this snippet! function IsAABBOverlap(hostent, testent, usesizetest) if hostent == nil then return false end if usesizetest == nil then usesizetest = false end if usesizetest then local aabb = hostent:GetAABB(Entity.GlobalAABB) local eaabb = testent:GetAABB(Entity.GlobalAABB) if (eaabb.min.x > aabb.max.x) or (aabb.min.x > eaabb.max.x) then return false end if (eaabb.min.y > aabb.max.y) or (aabb.min.y > eaabb.max.y) then return false end if (eaabb.min.z > aabb.max.z) or (aabb.min.z > eaabb.max.z) then return false end return true else local aabb = hostent:GetAABB(Entity.GlobalAABB) local pos = testent:GetPosition(true) if pos.x < aabb.min.x then return false end if pos.y < aabb.min.y then return false end if pos.z < aabb.min.z then return false end if pos.x > aabb.max.x then return false end if pos.y > aabb.max.y then return false end if pos.z > aabb.max.z then return false end return true end return false end
  10. Unlike CollisionTrigger, VolumeTrigger does it's work by it's entity's aabb radius being called on the UpdatePhysics thread. VolumeTrigger also keeps track of what objects are in the volume, and entities with swept collision can enter the volume because it doesn't use shapes for triggering. --[[ This script will make any entity act as a volume trigger. Having a trigger be AABB tests rather than collision has it's perks as it's easier to keep track of what entities are in the volume. Also, objects with swept collision can now activate triggers! ----NOTES---- filter <entity> = Use this feild if you wish to have a specific entity trigger outputs. enabled <bool> = Toggle the trigger on and off onlyonce <bool> = When true, the trigger deactivate forever when triggered the first time. sizetest <bool> = When true, the overlap test will preform a aabb radius on both the trigger and entity in question. If false, only the entity's position will be tested. Make this true if you want a true collision like trigger. allowcharacters <bool> = Toggles if characters can activate. allowprops <bool> = Toggles if props can activate. allowdebri <bool> = Toggles if debris can activate. allowprojectiles <bool> = Toggles if projectiles can activate. ]]-- import "Scripts/Functions/IsAABBOverlap.lua" Script.filter=nil--entity "Filter" Script.enabled=true--bool "Enabled" Script.onlyonce=false --bool "Only Once" Script.sizetest=false --bool "Size Test" -- These values will get ignored if there is no filter. Script.allowcharacters=true --bool "Allow Characters" Script.allowprops=true --bool "Allow Props" Script.allowdebris=true --bool "Allow Debris" Script.allowprojectiles=true --bool "Allow Projectiles" function TriggerForEachEntityInAABBDoCallback(entity,extra) local volumeent = extra local filterent = volumeent.script.filter -- Always skip these! if entity == volumeent then return end if entity:GetClass() == Object.PivotClass then return end if entity:GetClass() == Object.BoneClass then return end if entity:GetClass() == Object.DirectionalLightClass then return end if entity:GetClass() == Object.SpotLightClass then return end if entity:GetClass() == Object.PointLightClass then return end if entity:GetClass() == Object.ListenerClass then return end if entity:GetClass() == Object.ProbeClass then return end -- Don't count static brushes! if entity:GetCollisionType() == Collision.Scene then if entity:GetMass() <= 0 then return end end -- If we're not looking for a specific entity, filter by collision types. if filterent == nil then if entity:GetCollisionType() == Collision.None then return end if entity:GetCollisionType() == Collision.Character and not volumeent.script.allowcharacters then return end if entity:GetCollisionType() == Collision.Prop and not volumeent.script.allowprops then return end if entity:GetCollisionType() == Collision.Debris and not volumeent.script.allowdebris then return end if entity:GetCollisionType() == Collision.Projectile and not volumeent.script.allowprojectiles then return end if IsAABBOverlap(volumeent,entity,volumeent.script.sizetest) == true then volumeent.script:onstartTouch(entity) end elseif entity == filterent then if IsAABBOverlap(volumeent,filterent,volumeent.script.sizetest) == true then volumeent.script:onstartTouch(entity) end end end function Script:SearchForEntites() self.entity.world:ForEachEntityInAABBDo(self.entity:GetAABB(Entity.GlobalAABB),"TriggerForEachEntityInAABBDoCallback",self.entity) end function Script:IsAlreadyTouching(entity) local key,value for key,value in pairs(self.touchingents) do if value == entity then return true end end return false end function Script:Start() self.touchingents={} self.triggered=false -- Disable Shadows self.entity:SetShadowMode(0) -- Ignore all picking. self.entity:SetPickMode(0) -- Automaticly fix the Physics self.entity:SetCollisionType(Collision.None) self.entity:SetMass(0) self.entity:SetKeyValue("type", "trigger") self.entity:SetViewRange(Entity.NearViewRange) end function Script:UpdatePhysics() if not self.enabled then return end if onlyonce and self.triggered then return end self:SearchForEntites() if table.getn(self.touchingents) > 0 then local key,value for key,value in pairs(self.touchingents) do local zentity = value if zentity ~= nil then if IsAABBOverlap(self.entity,zentity,self.sizetest) == false then self:onendTouch(key, zentity) break end end end end end function Script:onstartTouch(entity) if self:IsAlreadyTouching(entity) == false then if table.getn(self.touchingents) == 0 then -- If it's the first item, call a special function. self.component:CallOutputs("onstartTouchAll") self.component:CallOutputs("onstartTouch") else self.component:CallOutputs("onstartTouch") end table.insert(self.touchingents, entity) self.triggered=true --System:Print("Added " ..entity:GetKeyValue("name") .. " to list") end end function Script:onendTouch(key, entity) if table.getn(self.touchingents) < 0 then return end if table.getn(self.touchingents) == 1 then -- If it's the last item, call a special function. self.component:CallOutputs("onendTouchAll") self.component:CallOutputs("onendTouch") else self.component:CallOutputs("onendTouch") end --System:Print("Removing " ..entity:GetKeyValue("name") .. " from list") table.remove(self.touchingents, key) end
  11. Just tried to re-detail the Vectronic and I noticed that the probes no longer make a difference. I also tried this with a blank project as well. Pretty much: Create a new map Place a few boxes and shapes Add in a probe Notice that the probe doesn't make the shadows lighter or make reflections. You can set the values to max, and it still will not make a difference.
  12. Probes build a cubemap texture once based on the location of the entity, and then applies it to the surrounding materials in it's radius. SSR is a post processing effect that in which all reflections update consistently. I haven't take a look at the new SSR, but here's hoping that it follows specular and roughness values.
  13. If you can help me get the Vectronic Demo pass the generic error when I upload to Seam, I'd be more than willing to update that to 4.2!
  14. Alright, sounds understandable. It's not too hard to do a hook to get those functions working again. Thanks for answering, just wanted to know if there was any improvement since the 22nd.
  15. Are all the functions working now? What's your plan for integrating actors with the editor?
  16. Here is a trigger material. Seems the blend mode only works if Z-Sort is on. (Intentional?) Edit: Added transparency! triggermat2.zip
  17. That makes me smile. You also forgot to mention this, which also makes me smile: Whoops, misread, this is experimental atm. http://www.leadwerks.com/werkspace/topic/15235-actor-class-for-c-entity-management/ Hopefully you can fix the bugs you listed soon. Also, did you mind taking a look at this? http://www.leadwerks.com/werkspace/topic/15355-exceptions-problem-visual-studio-17/ I was having similar issues. I'm about to start a new project so I can properly report what "kicks the bucket" more exclusively. Also, why didn't you use my workshop button graphic? Does it need more work or you don't like my take on it?
  18. Yeah, I get odd issues with the debug builds when loading a map. I thought it was something with my map loading code. Does the stock code have issues?
  19. A beam script that'll stretch a sprite from one point to another. Useful for lasers and cables. You can enable or disable auto updating if it isn't necessary. --[[ This script will create a simple sprite that looks like a beam or a cable. The beam is does not do any raycasting along and gets updated via the physics step. You can apply a script to the beam to change it's appearance such as flickering or pulsing. ]]-- Script.fxscriptfile=""--path "Beam Script" "Script (*.lua):lua|Scripts/Objects/Effects" Script.beamcolor=Vec4(1,1,1,1) --color "Beam Color" Script.beambrightness=1.0--float "Beam Brightness" Script.materialfile=""--path "Material" "Material (*.mat):mat|Materials" Script.beamwidth = .25 --float "Beam Width" Script.startpoint = nil --entity "Start Position" Script.endpoint = nil --entity "End Position" Script.beamhidden = false --bool "Hidden" Script.autoupdate = true --bool "Auto-Update" function Script:Start() -- Ignore pickers from picking us! self.entity:SetPickMode(0) -- Beam Sprite self.sprite = Sprite:Create() local material = Material:Load(self.materialfile) if material then self.sprite:SetMaterial(material) material:Release() else System:Debug("Beam material is missing.") end self.sprite:SetViewMode(6)--Rotate around z axis if self.fxscriptfile ~= nil then self.sprite:SetScript(self.fxscriptfile) end self.sprite:SetColor(self.beamcolor) self.sprite:SetIntensity(self.beambrightness) if not self.beamhidden then self.sprite:Show() else self.sprite:Hide() end -- If the first feild is nil, assume the user want's it to be the entity that holds this script. if self.startpoint == nil then self.startpoint = self.entity end -- A end point is needed. If nil, report error. if self.endpoint == nil then System:Debug("End point is nil.") end -- Only draw the beam once of auto-update is false. if not self.autoupdate then self:UpdateBeam() end end function Script:UpdateBeam() -- Return if the beam is hidden. if self.sprite:Hidden() then return end local p0 = self:GetStartPoint() local p1 = self:GetEndPoint() self.allignvector = p0 - p1 self.sprite:SetPosition((p0+p1)/2) self.sprite:AlignToVector(self.allignvector:Normalize(),2) -- Find distance between the two points. local distanceX = math.pow(p0.x - p1.x, 2) local distanceY = math.pow(p0.y - p1.y, 2) local distanceZ = math.pow(p0.z - p1.z, 2) local total_distance = math.sqrt(distanceX + distanceY + distanceZ) -- Modify the size of the beam based on the 2 points. self.sprite:SetSize(self.beamwidth, math.abs(total_distance)) end function Script:UpdatePhysics() if self.autoupdate then self:UpdateBeam() end end function Script:GetStartPoint() return self.startpoint:GetPosition(true) end function Script:GetEndPoint() return self.endpoint:GetPosition(true) end function Script:TurnOn()--in if self:IsOn() then return end self.sprite:Show() end function Script:TurnOff()--in if not self:IsOn() then return end self.sprite:Hide() end function Script:Toggle()--in if self:IsOn() then self:TurnOff() else self:TurnOn() end end function Script:IsOn() return not self.sprite:Hidden() end function Script:Release() self.sprite:Release() end If you're looking for a laser beam in which the end position is the end of a pick test, you can check out this post for details on how to do it. This script just has the basic functionality. You can reuse the script for more complex effects by ether cloning the script, or setting the script to an entity and then modifying it's values like. -- Make Pivot local p = Pivot:Create() -- Set Script to Pivot p:SetScript("scripts/objects/effects/beam.lua") -- Modify some values p.script.beamcolor=Vec4(1,0,0,1) p.script.autoupdate = false .... ....
  20. Cool, if you manage to get to finishing it, I'd be more than happy to have a look.
  21. Really like the flash drive idea as a prize, those are always handy! Also thanks for the extra 2 weeks. things can be busy with the holidays and all. I'll see what I can come up with and make it workshop friendly unlike last time.
  22. Like the flicker script, this will modify an entities intensity to create a pulsing effect. If any improvements can be made, let me know! Script.frequency=10.0--float "Frequency" Script.Recursive=true--bool function Script:Start() self:SaveIntensity(self.entity,self.Recursive) end --Store the original intensity values function Script:SaveIntensity(entity,recursive) entity:SetKeyValue("Pulse_Intensity",entity:GetIntensity()) if recursive then local n for n=0,entity:CountChildren()-1 do self:SaveIntensity(entity:GetChild(n),true) end end end --Apply a modified intensity value function Script:ApplyIntensity(entity,intensity,recursive) local i = entity:GetKeyValue("Pulse_Intensity") if i~="" then entity:SetIntensity(tonumber(i) * intensity) if recursive then local n for n=0,entity:CountChildren()-1 do self:ApplyIntensity(entity:GetChild(n),intensity,true) end end end end function Script:Draw() if self.color==nil then self.color = self.entity:GetColor() end local alpha = Math:Sin(Time:Millisecs()/self.frequency)*0.25+0.75 self:ApplyIntensity(self.entity,alpha,self.Recursive) end
  23. Odd, Josh mentioned he did that already, Maybe it didn't get pushed?
  24. Sadly most people on the Leadwerks forum use lua so C++ talk is kind of scarce. You'll need to purchase the Professional Edition DLC if you haven't already. First, join the beta branch. Leadwerks is going forward with Visual Studio 2017, and you can get the IDE here. Please note that Visual Studio is for Windows, and Code::Blocks is only for Linux. When you create a project or update an existing project, the project files for both IDE's will get cloned to your project. The code is set up to launch the engine, and call Main.lua/App.lua script. Again, Leadwerks at the moment is more focused on Lua, and I personally recommend only using C++ for program management (Time, level loading, etc) over game objects. (doors, swtiches)
  25. That's how I did it in the Vectronic Demo, it was kind of a pain tho.
×
×
  • Create New...