diff options
Diffstat (limited to 'Source/Objects/placeholderobject.cpp')
-rw-r--r-- | Source/Objects/placeholderobject.cpp | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/Source/Objects/placeholderobject.cpp b/Source/Objects/placeholderobject.cpp new file mode 100644 index 00000000..8253354d --- /dev/null +++ b/Source/Objects/placeholderobject.cpp @@ -0,0 +1,386 @@ +//----------------------------------------------------------------------------- +// Name: placeholderobject.cpp +// Developer: Wolfire Games LLC +// Description: +// License: Read below +//----------------------------------------------------------------------------- +// +// Copyright 2022 Wolfire Games LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//----------------------------------------------------------------------------- +#include "placeholderobject.h" + +#include <Editors/actors_editor.h> +#include <Editors/map_editor.h> + +#include <Graphics/textures.h> +#include <Graphics/Billboard.h> +#include <Graphics/camera.h> +#include <Graphics/pxdebugdraw.h> +#include <Graphics/shaders.h> + +#include <Internal/common.h> +#include <Internal/memwrite.h> +#include <Internal/profiler.h> + +#include <Objects/envobject.h> +#include <Objects/prefab.h> + +#include <Main/scenegraph.h> +#include <Main/engine.h> + +#include <Math/vec3math.h> +#include <Game/EntityDescription.h> + +extern bool shadow_cache_dirty; +extern bool g_debug_runtime_disable_placeholder_object_draw; + +PlaceholderObject::PlaceholderObject(): + special_type_(kSpawn), + connect_to_type_filter_flags_(1ULL << EntityType::_movement_object), + visible_(true), + connect_id_(-1), + title_debug_string_id(-1), + editor_label_offset_prev(0.0f), + editor_label_scale_prev(0.0f), + unsaved_changes(false) +{ + box_.dims = vec3(1.0f); +} + +void PlaceholderObject::DisposePreviewObjects() { + for(unsigned i=0, len=preview_objects_.size(); i < len; ++i){ + delete preview_objects_[i]; + } + preview_objects_.clear(); +} + +void PlaceholderObject::SetPreview( const std::string& path ) { + if(preview_path_ == path){ + return; + } + preview_path_ = path; + DisposePreviewObjects(); + EntityDescriptionList desc_list; + std::string file_type; + Path source; + ActorsEditor_LoadEntitiesFromFile(path, desc_list,&file_type, &source); + preview_objects_.reserve(desc_list.size()); + for(unsigned i=0, len=desc_list.size(); i < len; ++i){ + Object* obj = CreateObjectFromDesc(desc_list[i]); + if(obj) { + if(obj->GetType() == _env_object){ + EnvObject* eo = (EnvObject*)obj; + eo->placeholder_ = true; + eo->added_to_physics_scene_ = true; + // TODO: find another way to specify stipple + //eo->shader_id_ = Shaders::Instance()->returnProgram(eo->ofr->shader_name + " #HALFTONE_STIPPLE"); + } + if(scenegraph_){ + obj->scenegraph_ = scenegraph_; + obj->Initialize(); + } + preview_objects_.push_back(obj); + } else { + LOGE << "Failed at loading content for Placeholder Preview object" << std::endl; + } + } +} + +PlaceholderObject::~PlaceholderObject() { + ClearEditorLabel(); + DisposePreviewObjects(); +} + +void PlaceholderObject::Draw() { + if (g_debug_runtime_disable_placeholder_object_draw) { + return; + } + + if(!scenegraph_->map_editor->IsTypeEnabled(_placeholder_object) || + scenegraph_->map_editor->state_ == MapEditor::kInGame || + !visible_ || + Graphics::Instance()->media_mode() || + ActiveCameras::Instance()->Get()->GetFlags() == Camera::kPreviewCamera) + { + if(title_debug_string_id != -1){ + DebugDraw::Instance()->SetVisible(title_debug_string_id, false); + } + } else { + if(title_debug_string_id != -1){ + DebugDraw::Instance()->SetVisible(title_debug_string_id, true); + } + + bool old_shadow_cache_dirty = shadow_cache_dirty; + for(unsigned i=0, len=preview_objects_.size(); i < len; ++i){ + preview_objects_[i]->SetTransformationMatrix(GetTransform()); + preview_objects_[i]->ReceiveObjectMessage(OBJECT_MSG::DRAW); + } + shadow_cache_dirty = old_shadow_cache_dirty; // We don't want to update static shadow maps just because we moved this preview object + + if(ActiveCameras::Get()->GetFlags() == Camera::kEditorCamera) { + if(billboard_texture_ref_.valid() ) { + DebugDraw::Instance()->AddBillboard(billboard_texture_ref_->GetTextureRef(), GetTranslation(), GetScale()[0], vec4(1.0f), kStraight, _delete_on_draw); + } + DrawEditorLabel(); + } + else + { + ClearEditorLabel(); + } + + if(connect_id_ != -1){ + Object* obj = scenegraph_->GetObjectFromID(connect_id_); + if(obj){ + DebugDraw::Instance()->AddLine(GetTranslation(), obj->GetTranslation(), vec4(1.0f,1.0f,1.0f,0.5f), _delete_on_draw); + } + } + } +} + +void PlaceholderObject::GetDesc(EntityDescription &desc) const { + Object::GetDesc(desc); + desc.AddString(EDF_FILE_PATH, preview_path_); + if(billboard_texture_ref_.valid()){ + desc.AddString(EDF_BILLBOARD_PATH, billboard_path_); + } + desc.AddInt(EDF_SPECIAL_TYPE, special_type_); + std::vector<int> connections; + connections.push_back(connect_id_); + desc.AddIntVec(EDF_CONNECTIONS, connections); +} + +bool PlaceholderObject::SetFromDesc( const EntityDescription& desc ) { + bool ret = Object::SetFromDesc(desc); + + if( ret ) { + // Kludge to fill in the idName: (if the idName field is blank -- fill it in based on the object id + if( sp.HasParam("LocName") && sp.IsParamString("LocName") && sp.GetStringVal("LocName") == "" ) + { + char locationChars[256]; + sprintf( locationChars, "location%d", GetID() ); + std::string locationStr( locationChars ); + sp.ASRemove("LocName"); + sp.ASAddString("LocName", locationStr ); + + } + + if( sp.HasParam("Name") && sp.IsParamString("Name") && sp.GetStringVal("Name") == "arena_spawn" ) + { + SetBillboard("Data/UI/spawner/thumbs/Utility/placeholder_arena_spawn.png"); + } + + if( sp.HasParam("Name") && sp.IsParamString("Name") && sp.GetStringVal("Name") == "arena_battle" ) + { + SetBillboard("Data/UI/spawner/thumbs/Utility/placeholder_arena_battle.png"); + } + + for(unsigned i=0; i<desc.fields.size(); ++i){ + const EntityDescriptionField& field = desc.fields[i]; + switch(field.type){ + case EDF_FILE_PATH: { + std::string path; + field.ReadString(&path); + SetPreview(path); + break;} + case EDF_BILLBOARD_PATH: { + std::string path; + field.ReadString(&path); + SetBillboard(path); + break;} + case EDF_SPECIAL_TYPE: + memread(&special_type_, sizeof(int), 1, field.data); + break; + case EDF_CONNECTIONS: { + std::vector<int> connections; + field.ReadIntVec(&connections); + if(!connections.empty()){ + connect_id_ = connections[0]; + } + break;} + } + } + } + + return ret; +} + +void PlaceholderObject::SetVisible(bool visible) { + visible_ = visible; +} + +PlaceholderObject::PlaceholderObjectType PlaceholderObject::GetSpecialType() { + return special_type_; +} + +void PlaceholderObject::SetSpecialType(PlaceholderObject::PlaceholderObjectType val) { + special_type_ = val; +} + +bool PlaceholderObject::Initialize() { + for(int i=0, len=preview_objects_.size(); i<len; ++i){ + Object* obj = preview_objects_[i]; + obj->scenegraph_ = scenegraph_; + obj->Initialize(); + } + obj_file = "placeholder_object"; + return true; +} + +void PlaceholderObject::SetBillboard(const std::string& path) { + Textures::Instance()->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + billboard_texture_ref_ = Engine::Instance()->GetAssetManager()->LoadSync<TextureAsset>(path, PX_SRGB, 0x0); + billboard_path_ = path; +} + +uint64_t PlaceholderObject::GetConnectToTypeFilterFlags() { + return connect_to_type_filter_flags_; +} + +void PlaceholderObject::SetConnectToTypeFilterFlags(uint64_t entity_type_flags) { + connect_to_type_filter_flags_ = entity_type_flags; +} + +bool PlaceholderObject::ConnectTo( Object& other, bool checking_other /*= false*/ ) { + if(other.GetType() == _hotspot_object) { + return Object::ConnectTo(other, checking_other); + } + if(!connectable()){ + return false; + } + if(connect_to_type_filter_flags_ == (1ULL << EntityType::_any_type) || + (connect_to_type_filter_flags_ != 1ULL << EntityType::_no_type && (1ULL << other.GetType() & connect_to_type_filter_flags_) != 0)) { + //If the target object is part of a prefab, we want to connect the placeholder to the prefab, to maintain the connection. + Prefab* parent = other.GetPrefabParent(); + if( parent ) { + connect_id_ = parent->GetID(); + } else { + connect_id_ = other.GetID(); + } + return true; + } else { + return false; + } +} + +bool PlaceholderObject::AcceptConnectionsFrom(Object::ConnectionType type, Object& object) { + return connectable() && type == kCTMovementObjects; // Not sure this is correct because I have no clue how placeholders work yet +} + +bool PlaceholderObject::Disconnect( Object& other, bool checking_other ) { + if(other.GetType() == _hotspot_object) { + return Object::Disconnect(other, checking_other); + } + if(!connectable()){ + return false; + } + if(connect_id_ == other.GetID()){ + connect_id_ = -1; + return true; + } else { + return false; + } +} + +void PlaceholderObject::GetConnectionIDs(std::vector<int>* cons) { + if( connect_id_ != -1 ) { + cons->push_back(connect_id_); + } +} + +bool PlaceholderObject::connectable() { + return (special_type_ == kPlayerConnect); +} + +int PlaceholderObject::GetConnectID() { + return connect_id_; +} + +void PlaceholderObject::NotifyDeleted( Object* o ) { + Object::NotifyDeleted(o); + if(connect_id_ == o->GetID()){ + connect_id_ = -1; + } +} + +void PlaceholderObject::Moved(Object::MoveType type) { + Object::Moved(type); + label_position_update = true; +} + +void PlaceholderObject::GetDisplayName(char* buf, int buf_size) { + if(editor_display_name.length() > 0){ + if( GetName().empty() ) { + FormatString(buf, buf_size, "%d, %s", GetID(), editor_display_name.c_str()); + } else { + FormatString(buf, buf_size, "%s, %s", GetName().c_str(), editor_display_name.c_str()); + } + } else { + if( GetName().empty() ) { + FormatString(buf, buf_size, "%d: Empty Object", GetID()); + } else { + FormatString(buf, buf_size, "%s: Empty Object", GetName().c_str()); + } + } +} + +ObjectSanityState PlaceholderObject::GetSanity() { + uint32_t sanity_flags = 0; + if( special_type_ == kPlayerConnect && connect_id_ == -1 ) { + if( connect_id_ == -1 ) { + sanity_flags |= kObjectSanity_PO_UnsetConnectID; + } + } + return ObjectSanityState(GetType(),GetID(),sanity_flags); +} + +void PlaceholderObject::DrawEditorLabel() { + PROFILER_ZONE(g_profiler_ctx, "DrawEditorLabel"); + if( prev_editor_label != editor_label || editor_label_scale != editor_label_scale_prev) + { + ClearEditorLabel(); + } + + if( title_debug_string_id == -1 && editor_label.empty() == false ) + { + title_debug_string_id = DebugDraw::Instance()->AddText(vec3(0.0f), editor_label, editor_label_scale, _persistent, _DD_NO_FLAG); + prev_editor_label = editor_label; + editor_label_scale_prev = editor_label_scale; + label_position_update = true; + } + + if( (label_position_update || editor_label_offset != editor_label_offset_prev) && title_debug_string_id != -1 ) + { + DebugDraw::Instance()->SetPosition(title_debug_string_id, GetTranslation() + editor_label_offset * GetScale()[1]); + editor_label_offset_prev = editor_label_offset; + label_position_update = false; + } +} + +void PlaceholderObject::ClearEditorLabel() { + if( title_debug_string_id != -1 ) + { + DebugDraw::Instance()->Remove(title_debug_string_id); + title_debug_string_id = -1; + } +} + +void PlaceholderObject::RemapReferences(std::map<int,int> id_map) { + if( id_map.find(connect_id_) != id_map.end() ) { + connect_id_ = id_map[connect_id_]; + } else { + connect_id_ = -1; + } +} |