void Spline::SetKnot(const Variant& knot, unsigned index) { if (index < knots_.Size()) { if (knots_.Size() > 0 && knots_[0].GetType() == knot.GetType()) knots_[index] = knot; else if (knots_.Empty()) knots_.Push(knot); else LOGERRORF("Attempted to set a Spline's Knot value of type %s where elements are already using %s", knot.GetTypeName().CString(), knots_[0].GetTypeName().CString()); } }
void Spline::AddKnot(const Variant& knot, unsigned index) { if (index > knots_.Size()) index = knots_.Size(); if (knots_.Size() > 0 && knots_[0].GetType() == knot.GetType()) knots_.Insert(index, knot); else if (knots_.Empty()) knots_.Push(knot); else LOGERRORF("Attempted to add Knot to Spline of type %s where elements are already using %s", knot.GetTypeName().CString(), knots_[0].GetTypeName().CString()); }
void AEPreferences::Read() { rapidjson::Document document; String filepath = GetPreferencesFullPath(); File jsonFile(context_, filepath); if (!jsonFile.IsOpen()) return; String json; jsonFile.ReadText(json); if (!json.Length()) return; if (document.Parse<0>(json.CString()).HasParseError()) { LOGERRORF("Could not parse JSON data from %s", filepath.CString()); return; } Clear(); const Value::Member* recent_files = document.FindMember("recent_files"); if (recent_files && recent_files->value.IsArray()) { for (Value::ConstValueIterator itr = recent_files->value.Begin(); itr != recent_files->value.End(); itr++) { if (!(*itr).IsString()) continue; String path(itr->GetString()); recentProjects_.Push(path.CString()); } } const Value::Member* android_sdk_path = document.FindMember("android_sdk_path"); if (android_sdk_path && android_sdk_path->value.IsString()) androidSDKPath_ = android_sdk_path->value.GetString(); const Value::Member* jdk_root_path = document.FindMember("jdk_root_path"); if (jdk_root_path && jdk_root_path->value.IsString()) jdkRootPath_ = jdk_root_path->value.GetString(); const Value::Member* ant_path = document.FindMember("ant_path"); if (ant_path && ant_path->value.IsString()) antPath_ = ant_path->value.GetString(); UpdateRecentFiles(false); }
bool XMLFile::BeginLoad(Deserializer& source) { unsigned dataSize = source.GetSize(); if (!dataSize && !source.GetName().Empty()) { LOGERROR("Zero sized XML data in " + source.GetName()); return false; } SharedArrayPtr<char> buffer(new char[dataSize]); if (source.Read(buffer.Get(), dataSize) != dataSize) return false; if (!document_->load_buffer(buffer.Get(), dataSize)) { LOGERROR("Could not parse XML data from " + source.GetName()); document_->reset(); return false; } XMLElement rootElem = GetRoot(); String inherit = rootElem.GetAttribute("inherit"); if (!inherit.Empty()) { // The existence of this attribute indicates this is an RFC 5261 patch file ResourceCache* cache = GetSubsystem<ResourceCache>(); XMLFile* inheritedXMLFile = cache->GetResource<XMLFile>(inherit); if (!inheritedXMLFile) { LOGERRORF("Could not find inherited XML file: %s", inherit.CString()); return false; } // Patch this XMLFile and leave the original inherited XMLFile as it is pugi::xml_document* patchDocument = document_; document_ = new pugi::xml_document(); document_->reset(*inheritedXMLFile->document_); Patch(rootElem); delete patchDocument; // Store resource dependencies so we know when to reload/repatch when the inherited resource changes cache->StoreResourceDependency(this, inherit); // Approximate patched data size dataSize += inheritedXMLFile->GetMemoryUse(); } // Note: this probably does not reflect internal data structure size accurately SetMemoryUse(dataSize); return true; }
bool BuildBase::BuildClean(const String& path) { if (buildFailed_) { LOGERRORF("BuildBase::BuildClean - Attempt to clean directory of failed build, %s", path.CString()); return false; } FileSystem* fileSystem = GetSubsystem<FileSystem>(); if (!fileSystem->DirExists(path)) return true; // On Windows, do a little dance with the folder to avoid issues // with deleting folder and immediately recreating it String pathName, fileName, ext; SplitPath(path, pathName, fileName, ext); pathName = AddTrailingSlash(pathName); unsigned i = 0; while (true) { String newPath = ToString("%s%s_Temp_%u", pathName.CString(), fileName.CString(), i++); if (!fileSystem->DirExists(newPath)) { if (!MoveFileExW(GetWideNativePath(path).CString(), GetWideNativePath(newPath).CString(), MOVEFILE_WRITE_THROUGH)) { FailBuild(ToString("BuildBase::BuildClean: Unable to move directory %s -> ", path.CString(), newPath.CString())); return false; } // Remove the moved directory return BuildRemoveDirectory(newPath); } else { LOGWARNINGF("BuildBase::BuildClean - temp build folder exists, removing: %s", newPath.CString()); fileSystem->RemoveDir(newPath, true); } if (i == 255) { FailBuild(ToString("BuildBase::BuildClean: Unable to move directory ( i == 255) %s -> ", path.CString(), newPath.CString())); return false; } } return false; }
void XMLFile::AddAttribute(const pugi::xml_node& patch, pugi::xpath_node& original) { pugi::xml_attribute attribute = patch.attribute("type"); if (!patch.first_child() && patch.first_child().type() != pugi::node_pcdata) { LOGERRORF("XML Patch failed calling Add due to attempting to add non text to an attribute for %s.", attribute.value()); return; } String name(attribute.value()); name = name.Substring(1); pugi::xml_attribute newAttribute = original.node().append_attribute(name.CString()); newAttribute.set_value(patch.child_value()); }
void XMLFile::PatchAdd(const pugi::xml_node& patch, pugi::xpath_node& original) { // If not a node, log an error if (original.attribute()) { LOGERRORF("XML Patch failed calling Add due to not selecting a node, %s attribute was selected.", original.attribute().name()); return; } // If no type add node, if contains '@' treat as attribute pugi::xml_attribute type = patch.attribute("type"); if (!type || strlen(type.value()) <= 0) AddNode(patch, original); else if (type.value()[0] == '@') AddAttribute(patch, original); }
bool CubemapGenerator::Render() { if(!InitRender()) { LOGERRORF("Unable to init render"); return false; } GetScene()->SendEvent(E_CUBEMAPRENDERBEGIN); SubscribeToEvent(E_BEGINFRAME, HANDLER(CubemapGenerator, HandleBeginFrame)); SubscribeToEvent(E_ENDFRAME, HANDLER(CubemapGenerator, HandleEndFrame)); return true; }
void BuildBase::FailBuild(const String& message) { if (buildFailed_) { LOGERRORF("BuildBase::FailBuild - Attempt to fail already failed build: %s", message.CString()); return; } buildFailed_ = true; BuildError(message); BuildSystem* buildSystem = GetSubsystem<BuildSystem>(); buildSystem->BuildComplete(platformID_, buildPath_, false, message); }
bool JSONFile::ParseJSON(const String& json, JSONValue& value, bool reportError) { rapidjson::Document document; if (document.Parse<0>(json.CString()).HasParseError()) { if (reportError) LOGERRORF("Could not parse JSON data from string with error: %s", document.GetParseError()); return false; } ToJSONValue(value, document); return true; }
bool AppPanini::Init(Renderer* pRenderer, RenderTarget* pRenderTarget, PaniniParameters params) { ASSERT(pRenderer); ASSERT(pRenderTarget); bool bSuccess = initializeRenderingResources(pRenderer, pRenderTarget); if (!bSuccess) { LOGERRORF("Error initializing Panini Projection Post Process rendering resources."); return false; } gPaniniParametersStatic = params; bUsingStaticPaniniParams = true; return bSuccess; }
bool BuildBase::BuildCopyFile(const String& srcFileName, const String& destFileName) { if (buildFailed_) { LOGERRORF("BuildBase::BuildCopyFile - Attempt to copy file of failed build, %s", srcFileName.CString()); return false; } FileSystem* fileSystem = GetSubsystem<FileSystem>(); bool result = fileSystem->Copy(srcFileName, destFileName); if (!result) { FailBuild(ToString("BuildBase::BuildCopyFile: Unable to copy file %s -> %s", srcFileName.CString(), destFileName.CString())); return false; } return true; }
JSASTProgram::JSASTProgram(const String &path, const String &json) : JSASTNode(JSAST_PROGRAM) , document_(new Document()) { if (document_->Parse<0>(json.CString()).HasParseError()) { LOGERRORF("Could not parse JSON data from %s", path.CString()); return; } else { //StringBuffer buffer; //PrettyWriter<StringBuffer> writer(buffer, &(document_->GetAllocator())); //writer.SetIndent(' ', 3); //document_->Accept(writer); //LOGINFOF("%s", buffer.GetString()); } Parse(*document_); }
bool AppPanini::Init(Renderer* pRenderer, RenderTarget* pRenderTarget, Gui* pGuiWindow, void (*pfnPaniniToggleCallback)(bool)) #endif { ASSERT(pRenderer); ASSERT(pRenderTarget); ASSERT(pGuiWindow); ASSERT(pfnPaniniToggleCallback); bool bSuccess = initializeRenderingResources(pRenderer, pRenderTarget); if (!bSuccess) { LOGERRORF("Error initializing Panini Projection Post Process rendering resources."); return false; } // UI SETTINGS //---------------------------------------------------------------------------------------------------------------- PaniniParameters& params = gPaniniSettingsDynamic.mParams; // shorthand tinystl::vector<UIProperty>& dynamicProps = gPaniniSettingsDynamic.mDynamicUIControls.mDynamicProperties; // shorthand UIProperty fov("Camera Horizontal FoV", params.FoVH, 30.0f, 179.0f, 1.0f); addProperty(pGuiWindow, &fov); UIProperty toggle("Enable Panini Projection", gPaniniSettingsDynamic.mEnablePaniniProjection); addProperty(pGuiWindow, &toggle); dynamicProps.push_back(UIProperty("Panini D Parameter", params.D, 0.0f, 1.0f, 0.001f)); dynamicProps.push_back(UIProperty("Panini S Parameter", params.S, 0.0f, 1.0f, 0.001f)); dynamicProps.push_back(UIProperty("Screen Scale" , params.scale, 1.0f, 10.0f, 0.01f)); if (gPaniniSettingsDynamic.mEnablePaniniProjection) { gPaniniSettingsDynamic.mDynamicUIControls.ShowDynamicProperties(pGuiWindow); } gPaniniSettingsDynamic.pGui = pGuiWindow; g_pfnPaniniToggleCallback = pfnPaniniToggleCallback; return bSuccess; }
bool BuildBase::BuildRemoveDirectory(const String& path) { if (buildFailed_) { LOGERRORF("BuildBase::BuildRemoveDirectory - Attempt to remove directory of failed build, %s", path.CString()); return false; } FileSystem* fileSystem = GetSubsystem<FileSystem>(); if (!fileSystem->DirExists(path)) return true; bool result = fileSystem->RemoveDir(path, true); if (!result) { FailBuild(ToString("BuildBase::BuildRemoveDirectory: Unable to remove directory %s", path.CString())); return false; } return true; }
void openWindow(const char* app_name, WindowsDesc* winDesc) { winDesc->fullscreenRect = { 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) }; // If user provided invalid or zero rect, get the rect from renderer if (getRectWidth(winDesc->windowedRect) <= 0 || getRectHeight(winDesc->windowedRect) <= 0) { getRecommendedResolution(&winDesc->windowedRect); } RECT clientRect = { (LONG)winDesc->windowedRect.left, (LONG)winDesc->windowedRect.top, (LONG)winDesc->windowedRect.right, (LONG)winDesc->windowedRect.bottom }; AdjustWindowRect(&clientRect, WS_OVERLAPPEDWINDOW, FALSE); winDesc->windowedRect = { (int)clientRect.left, (int)clientRect.top, (int)clientRect.right, (int)clientRect.bottom }; RectDesc& rect = winDesc->fullScreen ? winDesc->fullscreenRect : winDesc->windowedRect; WCHAR app[MAX_PATH]; size_t charConverted = 0; mbstowcs_s(&charConverted, app, app_name, MAX_PATH); HWND hwnd = CreateWindowW(CONFETTI_WINDOW_CLASS, app, WS_OVERLAPPEDWINDOW | ((winDesc->visible) ? WS_VISIBLE : 0), CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, (HINSTANCE)GetModuleHandle(NULL), 0 ); if (hwnd) { GetClientRect(hwnd, &clientRect); winDesc->windowedRect = { (int)clientRect.left, (int)clientRect.top, (int)clientRect.right, (int)clientRect.bottom }; winDesc->handle = hwnd; gHWNDMap.insert({ hwnd, winDesc }); if (winDesc->visible) { if (winDesc->maximized) { ShowWindow(hwnd, SW_MAXIMIZE); } else if (winDesc->minimized) { ShowWindow(hwnd, SW_MINIMIZE); } else if (winDesc->fullScreen) { adjustWindow(winDesc); } } LOGINFOF("Created window app %s", app_name); } else { LOGERRORF("Failed to create window app %s", app_name); } }
void JSBModule::Load(const String &moduleJSONFilename) { ResourceCache* cache = JSBind::context_->GetSubsystem<ResourceCache>(); JSONFile* moduleJSONFile = cache->GetResource<JSONFile>(moduleJSONFilename); if (!moduleJSONFile) { LOGERRORF("Couldn't load module json: %s", moduleJSONFilename.CString()); ErrorExit("Couldn't load module json"); } JSONValue moduleJSON = moduleJSONFile->GetRoot(); JSONValue sources = moduleJSON.GetChild("sources"); JSONValue classes = moduleJSON.GetChild("classes"); JSONValue includes = moduleJSON.GetChild("includes"); JSONValue classes_rename = moduleJSON.GetChild("classes_rename"); JSONValue overloads = moduleJSON.GetChild("overloads"); JSONValue requires = moduleJSON.GetChild("requires"); HashMap<String, String> rename; if (requires.IsArray()) { for (unsigned j = 0; j < requires.GetSize(); j++) { requirements_.Push(requires.GetString(j)); } } if (classes_rename.IsObject()) { Vector<String> childNames = classes_rename.GetValueNames(); for (unsigned j = 0; j < childNames.Size(); j++) { String classname = childNames.At(j); String crename = classes_rename.GetString(classname); rename[classname] = crename; } } if (includes.IsArray()) { for (unsigned j = 0; j < includes.GetSize(); j++) { includes_.Push(includes.GetString(j)); } } if (classes.IsArray()) { for (unsigned j = 0; j < classes.GetSize(); j++) { String classname = classes.GetString(j); if (rename.Contains(classname)) bindings_->RegisterClass(classname, rename[classname]); else bindings_->RegisterClass(classname); } } if (overloads.IsObject()) { Vector<String> childNames = overloads.GetChildNames(); for (unsigned j = 0; j < childNames.Size(); j++) { String classname = childNames.At(j); JSBClass* klass = bindings_->GetClass(classname); if (!klass) { ErrorExit("Bad overload klass"); } JSONValue classoverloads = overloads.GetChild(classname); Vector<String> functionNames = classoverloads.GetChildNames(); for (unsigned k = 0; k < functionNames.Size(); k++) { JSONValue sig = classoverloads.GetChild(functionNames[k]); if (!sig.IsArray()) { ErrorExit("Bad overload defintion"); } Vector<String> values; for (unsigned x = 0; x < sig.GetSize(); x++) { values.Push(sig.GetString(x)); } JSBFunctionOverride* fo = new JSBFunctionOverride(functionNames[k], values); klass->AddFunctionOverride(fo); } } } this->name_ = moduleJSON.GetString("name"); if (this->name_ == "Graphics") { #ifdef _MSC_VER sources.AddString("Graphics/Direct3D9"); #else sources.AddString("Graphics/OpenGL"); #endif } for (unsigned j = 0; j < sources.GetSize(); j++) { String sourceFolder = sources.GetString(j); Vector<String> fileNames; String sourceRoot = "Atomic"; if (sourceFolder == "Javascript") sourceRoot = "AtomicJS"; JSBind::fileSystem_->ScanDir(fileNames, JSBind::ROOT_FOLDER + "/Source/" + sourceRoot + "/" + sourceFolder, "*.h", SCAN_FILES, false); for (unsigned k = 0; k < fileNames.Size(); k++) { // TODO: filter String filepath = JSBind::ROOT_FOLDER + "/Source/" + sourceRoot + "/" + sourceFolder + "/" + fileNames[k]; this->headerFiles_.Push(filepath); } } }
bool JSBModule::Load(const String& jsonFilename) { JSBind* jsbind = GetSubsystem<JSBind>(); LOGINFOF("Loading Module: %s", jsonFilename.CString()); SharedPtr<File> jsonFile(new File(context_, jsonFilename)); if (!jsonFile->IsOpen()) { LOGERRORF("Unable to open module json: %s", jsonFilename.CString()); return false; } moduleJSON_ = new JSONFile(context_); if (!moduleJSON_->BeginLoad(*jsonFile)) { LOGERRORF("Unable to parse module json: %s", jsonFilename.CString()); return false; } JSONValue root = moduleJSON_->GetRoot(); name_ = root.GetString("name"); JSONValue requires = root.GetChild("requires"); if (requires.IsArray()) { for (unsigned j = 0; j < requires.GetSize(); j++) { requirements_.Push(requires.GetString(j)); } } JSONValue classes = root.GetChild("classes"); for (unsigned i = 0; i < classes.GetSize(); i++) { classnames_.Push(classes.GetString(i)); } JSONValue classes_rename = root.GetChild("classes_rename"); if (classes_rename.IsObject()) { Vector<String> childNames = classes_rename.GetValueNames(); for (unsigned j = 0; j < childNames.Size(); j++) { String classname = childNames.At(j); String crename = classes_rename.GetString(classname); classRenames_[classname] = crename; } } JSONValue includes = root.GetChild("includes"); if (includes.IsArray()) { for (unsigned j = 0; j < includes.GetSize(); j++) { includes_.Push(includes.GetString(j)); } } JSONValue sources = root.GetChild("sources"); for (unsigned i = 0; i < sources.GetSize(); i++) { sourceDirs_.Push(sources.GetString(i)); } if (name_ == "Graphics") { #ifdef _MSC_VER if (jsbind->GetPlatform() == "ANDROID" || jsbind->GetPlatform() == "WEB") { sourceDirs_.Push("Source/Atomic/Graphics/OpenGL"); } else { #ifdef ATOMIC_D3D11 sourceDirs_.Push("Source/Atomic/Graphics/Direct3D11"); #else sourceDirs_.Push("Source/Atomic/Graphics/Direct3D9"); #endif } #else sourceDirs_.Push("Source/Atomic/Graphics/OpenGL"); #endif } ScanHeaders(); return true; }
void LicenseSystem::HandleVerification(StringHash eventType, VariantMap& eventData) { CurlRequest* request = (CurlRequest*) (eventData[CurlComplete::P_CURLREQUEST].GetPtr()); if (serverVerification_.NotNull()) { assert(request == serverVerification_); if (serverVerification_->GetError().Length()) { LOGERRORF("Unable to verify with server: %s", serverVerification_->GetError().CString()); } else { LicenseParse parse; int code = ParseResponse(serverVerification_->GetResponse(), parse); // Not activated if (code == 4) { } else if (code == 2) { // something is wrong with the key LOGERRORF("Error with product key"); RemoveLicense(); ResetLicense(); UIModalOps* ops = GetSubsystem<UIModalOps>(); ops->Hide(); ops->ShowActivation(); } else if (code == 3) { // something is wrong on the activation server key_ = ""; } else if (code == 1) { // exceeded code, should not happen here as we aren't activating key_ = ""; } else if (code == 0) { // we should raise an error if there is a mismatch between local and server keys // when the local says there are more enabled than server? // otherwise, they could be being added bool mismatch = false; if (parse.licenseWindows_ != licenseWindows_) mismatch = true; if (parse.licenseMac_ != licenseMac_) mismatch = true; if (parse.licenseWindows_ != licenseWindows_) mismatch = true; if (parse.licenseAndroid_ != licenseAndroid_) mismatch = true; if (parse.licenseIOS_ != licenseIOS_) mismatch = true; if (parse.licenseHTML5_ != licenseHTML5_) mismatch = true; if (parse.licenseModule3D_ != licenseModule3D_) mismatch = true; if (mismatch) { LOGERROR("License Mismatch, reseting"); licenseWindows_ = parse.licenseWindows_; licenseMac_ = parse.licenseMac_; licenseAndroid_ = parse.licenseAndroid_; licenseIOS_= parse.licenseIOS_; licenseHTML5_= parse.licenseHTML5_; licenseModule3D_= parse.licenseModule3D_; SaveLicense(); } //if (!HasPlatformLicense()) //{ // UIModalOps* ops = GetSubsystem<UIModalOps>(); // if (!ops->ModalActive()) // ops->ShowPlatformsInfo(); // } } } UnsubscribeFromEvents(serverVerification_); serverVerification_ = 0; } }
bool ShaderProgram::Link() { PROFILE(LinkShaderProgram); Release(); if (!graphics || !graphics->IsInitialized()) { LOGERROR("Can not link shader program without initialized Graphics subsystem"); return false; } if (!vs || !ps) { LOGERROR("Shader(s) are null, can not link shader program"); return false; } if (!vs->GLShader() || !ps->GLShader()) { LOGERROR("Shaders have not been compiled, can not link shader program"); return false; } const String& vsSourceCode = vs->Parent() ? vs->Parent()->SourceCode() : String::EMPTY; const String& psSourceCode = ps->Parent() ? ps->Parent()->SourceCode() : String::EMPTY; program = glCreateProgram(); if (!program) { LOGERROR("Could not create shader program"); return false; } glAttachShader(program, vs->GLShader()); glAttachShader(program, ps->GLShader()); glLinkProgram(program); int linked; glGetProgramiv(program, GL_LINK_STATUS, &linked); if (!linked) { int length, outLength; String errorString; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); errorString.Resize(length); glGetProgramInfoLog(program, length, &outLength, &errorString[0]); glDeleteProgram(program); program = 0; LOGERRORF("Could not link shaders %s: %s", FullName().CString(), errorString.CString()); return false; } LOGDEBUGF("Linked shaders %s", FullName().CString()); glUseProgram(program); char nameBuffer[MAX_NAME_LENGTH]; int numAttributes, numUniforms, numUniformBlocks, nameLength, numElements; GLenum type; attributes.Clear(); glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &numAttributes); for (int i = 0; i < numAttributes; ++i) { glGetActiveAttrib(program, i, (GLsizei)MAX_NAME_LENGTH, &nameLength, &numElements, &type, nameBuffer); VertexAttribute newAttribute; newAttribute.name = String(nameBuffer, nameLength); newAttribute.semantic = SEM_POSITION; newAttribute.index = 0; for (size_t j = 0; elementSemanticNames[j]; ++j) { if (newAttribute.name.StartsWith(elementSemanticNames[j], false)) { int index = NumberPostfix(newAttribute.name); if (index >= 0) newAttribute.index = (unsigned char)index; break; } newAttribute.semantic = (ElementSemantic)(newAttribute.semantic + 1); } if (newAttribute.semantic == MAX_ELEMENT_SEMANTICS) { LOGWARNINGF("Found vertex attribute %s with no known semantic in shader program %s", newAttribute.name.CString(), FullName().CString()); continue; } newAttribute.location = glGetAttribLocation(program, newAttribute.name.CString()); attributes.Push(newAttribute); } glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numUniforms); int numTextures = 0; for (int i = 0; i < numUniforms; ++i) { glGetActiveUniform(program, i, MAX_NAME_LENGTH, &nameLength, &numElements, &type, nameBuffer); String name(nameBuffer, nameLength); if (type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_SHADOW) { // Assign sampler uniforms to a texture unit according to the number appended to the sampler name int location = glGetUniformLocation(program, name.CString()); int unit = NumberPostfix(name); // If no unit number specified, assign in appearance order starting from unit 0 if (unit < 0) unit = numTextures; // Array samplers may have multiple elements, assign each sequentially if (numElements > 1) { Vector<int> units; for (int j = 0; j < numElements; ++j) units.Push(unit++); glUniform1iv(location, numElements, &units[0]); } else glUniform1iv(location, 1, &unit); numTextures += numElements; } } glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks); for (int i = 0; i < numUniformBlocks; ++i) { glGetActiveUniformBlockName(program, i, (GLsizei)MAX_NAME_LENGTH, &nameLength, nameBuffer); // Determine whether uniform block belongs to vertex or pixel shader String name(nameBuffer, nameLength); bool foundVs = vsSourceCode.Contains(name); bool foundPs = psSourceCode.Contains(name); if (foundVs && foundPs) { LOGWARNINGF("Found uniform block %s in both vertex and pixel shader in shader program %s"); continue; } // Vertex shader constant buffer bindings occupy slots starting from zero to maximum supported, pixel shader bindings // from that point onward unsigned blockIndex = glGetUniformBlockIndex(program, name.CString()); int bindingIndex = NumberPostfix(name); // If no number postfix in the name, use the block index if (bindingIndex < 0) bindingIndex = blockIndex; if (foundPs) bindingIndex += (unsigned)graphics->NumVSConstantBuffers(); glUniformBlockBinding(program, blockIndex, bindingIndex); } return true; }